@viur/shop-components 0.13.2-0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viur/shop-components",
3
- "version": "0.13.2-0",
3
+ "version": "0.14.0",
4
4
  "description": "Frontend Vue components for the shop module of ViUR",
5
5
  "repository": {
6
6
  "type": "git",
@@ -81,7 +81,6 @@
81
81
  </sl-dialog>
82
82
  </template>
83
83
 
84
- paypal?
85
84
  <template v-if="shopStore.state.order?.['payment_provider'] !== null && shopStore.state.order?.['payment_provider'].startsWith('paypal')">
86
85
  <sl-dialog v-if="state.paymentPopup" :label="$t('viur.shop.order_pay')" :open="state.paymentPopup" @sl-after-hide="state.paymentPopup=false">
87
86
  <payment-provider-paypal @cancel="paymentCanceled"></payment-provider-paypal>
@@ -1,6 +1,4 @@
1
1
  <template>
2
- PAYPAL HERE
3
-
4
2
  <div class="loading-wrapper" v-if="state.loading">
5
3
  <sl-spinner class="loading"></sl-spinner>
6
4
  </div>
@@ -25,16 +23,15 @@ import {Request} from '@viur/vue-utils';
25
23
  import {HTTPError} from '@viur/vue-utils/utils/request.js';
26
24
  import {useIntervalFn} from '@vueuse/core';
27
25
  import {onBeforeMount, reactive} from 'vue';
28
- import {useAddress} from '../composables/address.js';
29
26
  import {useOrder} from '../composables/order';
30
27
  import {useViurShopStore} from '../shop';
31
28
 
32
29
  const shopStore = useViurShopStore();
33
30
  const {fetchOrder} = useOrder();
34
- const {saveBirthdate} = useAddress();
35
31
 
36
32
  const emits = defineEmits(['cancel']);
37
33
 
34
+ // TODO: Duplicate code
38
35
  const {pause: PaymentCheckPause, resume: PaymentCheckResume, isActive: PaymentCheckIsActive} = useIntervalFn(() => {
39
36
  console.debug('checking ...');
40
37
 
@@ -56,6 +53,7 @@ const state = reactive({
56
53
  errorMessage: null,
57
54
  waitPayment: false,
58
55
  order_id: null,
56
+ debugPaypal: false,
59
57
  });
60
58
 
61
59
  /**
@@ -66,7 +64,6 @@ function initPaypalForm() {
66
64
  console.error(`PayPal Checkout does not work with ${shopStore.state.order?.['payment_provider']}.`);
67
65
  return null;
68
66
  }
69
- const client_id = shopStore.state.paymentProviderData.public_key;
70
67
 
71
68
  const scriptConfig = {
72
69
  // https://developer.paypal.com/sdk/js/configuration/#configure-and-customize-your-integration
@@ -75,7 +72,7 @@ function initPaypalForm() {
75
72
  'currency': 'EUR',
76
73
  'components': 'buttons,applepay',
77
74
  'enable-funding': 'venmo,paylater,card,sofort,sepa,giropay',
78
- 'debug': shopStore.state.debug,
75
+ 'debug': state.debugPaypal,
79
76
  };
80
77
 
81
78
  const paypalScriptPromise = new Promise((resolve, reject) => {
@@ -88,7 +85,6 @@ function initPaypalForm() {
88
85
  document.head.appendChild(paypalScript);
89
86
  });
90
87
 
91
-
92
88
  paypalScriptPromise.then(() => {
93
89
  console.debug('paypalScriptPromise resolved - READY');
94
90
  console.debug(shopStore.state.paymentProviderData);
@@ -106,92 +102,91 @@ function initPaypalForm() {
106
102
 
107
103
  async createOrder() {
108
104
  console.debug('createOrder');
109
- try {
110
- let resp = await shopStore.checkoutOrder();//.then((resp) => {
111
- console.debug(resp);
105
+ state.loading = true;
112
106
 
113
- // const orderData = await resp.json();
114
- const orderData = await resp.payment;
115
- // const orderData = await response.json();
107
+ if (shopStore.state.order?.['is_ordered'] && shopStore.state.order?.['is_checkout_in_progress'] && !shopStore.state.order?.['is_paid']) {
108
+ // already ordered; needs a re-checkout method to create a new order. But we can try it again with the last order_id
109
+ state.order_id = (shopStore.state.order?.payment?.payments ?? []).at(-1)?.payment_id;
110
+ return state.order_id;
111
+ }
116
112
 
117
- // let orderData = shopStore.state.paymentProviderData;
118
- console.debug(orderData);
113
+ try {
114
+ const resp = await shopStore.checkoutOrder(); // must be inline awaited to return order_id on success
115
+ // TODO: re-checkout with new attempt or different method
116
+ console.debug('checkoutOrder', resp);
117
+ const orderData = resp.payment;
119
118
 
120
119
  if (orderData.id) {
120
+ // SUCCESS; return the order_id to the PayPal instance
121
121
  state.order_id = orderData.id;
122
122
  return orderData.id;
123
+ } else {
124
+ // ERROR; show error message
125
+ const errorDetail = orderData?.details?.[0];
126
+ const errorMessage = errorDetail
127
+ ? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})`
128
+ : JSON.stringify(orderData);
129
+ console.error(errorDetail);
130
+ paymentError(`Could not initiate PayPal Checkout...<br><br>${errorMessage}`);
123
131
  }
124
-
125
- const errorDetail = orderData?.details?.[0];
126
- const errorMessage = errorDetail
127
- ? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})`
128
- : JSON.stringify(orderData);
129
-
130
- throw new Error(errorMessage);
131
132
  } catch (error) {
132
- console.error(error);
133
- // resultMessage(`Could not initiate PayPal Checkout...<br><br>${error}`);
133
+ paymentError(error);
134
+ return null;
135
+ } finally {
136
+ state.loading = false;
134
137
  }
135
138
  },
136
139
 
140
+ /**
141
+ * Buyer approved the payment, send it to the backend to capture it and mark as paid.
142
+ */
137
143
  async onApprove(data, actions) {
138
144
  console.debug('onApprove', data, actions);
139
145
  state.loading = true;
140
146
 
141
- // buyer approved the payment, send it to the backend to capture it and mark as paid
142
147
  const paymenttarget = shopStore.state.order?.['payment_provider'].replace(/-/g, '_');
143
148
  Request.post(`${shopStore.state.shopUrl}/pp_${paymenttarget}/capture_order`, {
144
149
  dataObj: {
145
150
  order_key: shopStore.state.orderKey,
146
151
  order_id: state.order_id,
147
152
  },
148
- }).then(async (resp) => {
149
- console.debug('capture_order', resp);
150
- const data = await resp.json();
151
- const orderData = data.payment;
152
- console.debug(orderData);
153
-
154
- // Three cases to handle:
155
- // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
156
- // (2) Other non-recoverable errors -> Show a failure message
157
- // (3) Successful transaction -> Show confirmation or thank you message
158
- const errorDetail = orderData?.details?.[0];
159
-
160
- if (errorDetail?.issue === 'INSTRUMENT_DECLINED') {
161
- // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
162
- // recoverable state, per
163
- // https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/
164
- return actions.restart();
165
- } else if (errorDetail) {
166
- // (2) Other non-recoverable errors -> Show a failure message
167
- paymentError(`${errorDetail.description} (${orderData.debug_id})`);
168
- } else if (!orderData.purchase_units) {
169
- console.error(`No purchase_units`);
170
- paymentError(`Missing purchase_units`);
171
- } else {
172
- // (3) Successful transaction -> Show confirmation or thank you message
173
- // Or go to another URL: actions.redirect('thank_you.html');
174
- const transaction =
175
- orderData?.purchase_units?.[0]?.payments?.captures?.[0] ||
176
- orderData?.purchase_units?.[0]?.payment?.authorizations?.[0];
177
- console.debug('Capture result', orderData, JSON.stringify(orderData, null, 2));
178
-
179
- state.loading = false;
180
- state.hasError = false;
181
- state.waitPayment = true;
182
- PaymentCheckResume();
183
- }
184
- }).catch(error => {
185
- paymentError(error);
186
- });
153
+ })
154
+ .then(async (resp) => {
155
+ console.debug('capture_order', resp);
156
+ const data = await resp.json();
157
+ const orderData = data.payment;
158
+
159
+ // Three cases to handle:
160
+ // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
161
+ // (2) Other non-recoverable errors -> Show a failure message
162
+ // (3) Successful transaction -> Show confirmation or thank you message
163
+ const errorDetail = orderData?.details?.[0];
164
+
165
+ if (errorDetail?.issue === 'INSTRUMENT_DECLINED') {
166
+ // (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
167
+ // recoverable state, per
168
+ // https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/
169
+ return actions.restart();
170
+ } else if (errorDetail) {
171
+ // (2) Other non-recoverable errors -> Show a failure message
172
+ paymentError(`${errorDetail.description} (${orderData?.debug_id})`);
173
+ } else if (!orderData.purchase_units) {
174
+ paymentError(`Missing purchase_units`);
175
+ } else {
176
+ // (3) Successful transaction -> Show confirmation or thank you message
177
+ // Or go to another URL: actions.redirect('thank_you.html');
178
+ state.loading = false;
179
+ state.hasError = false;
180
+ state.waitPayment = true;
181
+ PaymentCheckResume();
182
+ }
183
+ })
184
+ .catch(paymentError);
187
185
  },
188
186
 
189
- onError: (err) => {
190
- console.error(err);
191
- paymentError(err);
192
- },
187
+ onError: paymentError,
193
188
 
194
- appSwitchWhenAvailable: true,
189
+ // appSwitchWhenAvailable: true,
195
190
  });
196
191
  paypalButtons.render('#paypal-button-container');
197
192
  });
@@ -93,6 +93,7 @@ const {saveBirthdate} = useAddress();
93
93
 
94
94
  const emits = defineEmits(['cancel']);
95
95
 
96
+ // TODO: Duplicate code
96
97
  const {pause: PaymentCheckPause, resume: PaymentCheckResume, isActive: PaymentCheckIsActive} = useIntervalFn(() => {
97
98
  console.debug('checking ...');
98
99
 
package/src/shop.js CHANGED
@@ -303,6 +303,11 @@ export const useViurShopStore = defineStore("viurshopStore", () => {
303
303
  checkoutStart,
304
304
  checkoutOrder,
305
305
  addTab,
306
- removeTab
306
+ removeTab,
307
+
308
+ /**
309
+ * @deprecated since version 0.14.0 - Use checkoutStart instead
310
+ */
311
+ checkout: checkoutStart, // TODO: Remove alias
307
312
  }
308
313
  })