@viur/shop-components 0.13.2-0 → 0.13.2-1
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
|
@@ -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':
|
|
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
|
-
|
|
110
|
-
let resp = await shopStore.checkoutOrder();//.then((resp) => {
|
|
111
|
-
console.debug(resp);
|
|
105
|
+
state.loading = true;
|
|
112
106
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
118
|
-
|
|
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
|
-
|
|
133
|
-
|
|
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
|
-
})
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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:
|
|
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
|
|