@akinon/pz-flow-payment 1.99.0-snapshot-ZERO-3640-20250919140935 → 1.100.0-rc.71
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/CHANGELOG.md +33 -2
- package/package.json +1 -1
- package/src/views/index.tsx +117 -136
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# @akinon/pz-flow-payment
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.100.0-rc.71
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- 1b9e9be: BRDG-14604: Refactor FlowPayment component to utilize RTK Query mutations for payment options and wallet selection, enhancing session management and initialization logic
|
|
8
|
+
- d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
|
|
9
|
+
- 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
|
|
10
|
+
|
|
11
|
+
## 1.99.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- d58538b: ZERO-3638: Enhance RC pipeline: add fetch, merge, and pre-release setup with conditional commit
|
|
8
16
|
|
|
9
17
|
## 1.98.0
|
|
10
18
|
|
|
@@ -19,6 +27,29 @@
|
|
|
19
27
|
### Minor Changes
|
|
20
28
|
|
|
21
29
|
- 69e4cc5: BRDG-14604: Refactor FlowPayment component to optimize flow initialization and cleanup logic
|
|
30
|
+
- d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
|
|
31
|
+
- 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
|
|
32
|
+
|
|
33
|
+
## 1.96.0-rc.60
|
|
34
|
+
|
|
35
|
+
## 1.96.0-rc.59
|
|
36
|
+
|
|
37
|
+
## 1.96.0-rc.58
|
|
38
|
+
|
|
39
|
+
## 1.96.0-rc.57
|
|
40
|
+
|
|
41
|
+
## 1.96.0-rc.56
|
|
42
|
+
|
|
43
|
+
### Minor Changes
|
|
44
|
+
|
|
45
|
+
- 69e4cc5: BRDG-14604: Refactor FlowPayment component to optimize flow initialization and cleanup logic
|
|
46
|
+
|
|
47
|
+
## 1.96.0-rc.55
|
|
48
|
+
|
|
49
|
+
### Minor Changes
|
|
50
|
+
|
|
51
|
+
- d8be48fb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
|
|
52
|
+
- 8b1d24eb: ZERO-3422: Update fetch method to use dynamic request method in wallet complete redirection middleware
|
|
22
53
|
|
|
23
54
|
## 1.95.0
|
|
24
55
|
|
package/package.json
CHANGED
package/src/views/index.tsx
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { checkoutApi } from '@akinon/next/data/client/checkout';
|
|
2
2
|
import { useAppDispatch, useAppSelector } from '@akinon/next/redux/hooks';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
useSetPaymentOptionMutation,
|
|
5
|
+
useSetWalletSelectionPageMutation,
|
|
6
|
+
useSetWalletPaymentPageMutation
|
|
7
|
+
} from '@akinon/next/data/client/checkout';
|
|
5
8
|
import {
|
|
6
9
|
ComponentOptions,
|
|
7
10
|
CustomTranslations,
|
|
@@ -9,7 +12,8 @@ import {
|
|
|
9
12
|
PartialDesignTokens,
|
|
10
13
|
PaymentSessionResponse
|
|
11
14
|
} from '@checkout.com/checkout-web-components';
|
|
12
|
-
import {
|
|
15
|
+
import { RootState } from '@theme/redux/store';
|
|
16
|
+
import { useEffect, useRef, useMemo } from 'react';
|
|
13
17
|
|
|
14
18
|
export default function FlowPayment({
|
|
15
19
|
options
|
|
@@ -17,7 +21,7 @@ export default function FlowPayment({
|
|
|
17
21
|
options?: {
|
|
18
22
|
/**
|
|
19
23
|
* Environment to use for the payment components.
|
|
20
|
-
* Defaults to '
|
|
24
|
+
* Defaults to 'production'.
|
|
21
25
|
* If you want to test the payment components, you can set this to 'sandbox'.
|
|
22
26
|
*/
|
|
23
27
|
environment?: 'sandbox' | 'production';
|
|
@@ -54,16 +58,18 @@ export default function FlowPayment({
|
|
|
54
58
|
};
|
|
55
59
|
}) {
|
|
56
60
|
const { preOrder, walletPaymentData } = useAppSelector(
|
|
57
|
-
(state:
|
|
61
|
+
(state: RootState) => state.checkout
|
|
58
62
|
);
|
|
59
63
|
const dispatch = useAppDispatch();
|
|
60
64
|
const flowComponentRef = useRef<any>(null);
|
|
61
65
|
const lastAmountRef = useRef<string | null>(null);
|
|
62
66
|
const isInitializingRef = useRef<boolean>(false);
|
|
63
67
|
const walletPaymentInitialized = useRef<boolean>(false);
|
|
64
|
-
const [errors, setErrors] = useState<any>(null);
|
|
65
68
|
|
|
66
|
-
|
|
69
|
+
// RTK Query mutations
|
|
70
|
+
const [setPaymentOption] = useSetPaymentOptionMutation();
|
|
71
|
+
const [setWalletSelectionPage] = useSetWalletSelectionPageMutation();
|
|
72
|
+
const [setWalletPaymentPage] = useSetWalletPaymentPageMutation();
|
|
67
73
|
|
|
68
74
|
// Memoize the amount to track actual changes
|
|
69
75
|
const currentAmount = useMemo(() => {
|
|
@@ -71,88 +77,27 @@ export default function FlowPayment({
|
|
|
71
77
|
}, [preOrder.total_amount]);
|
|
72
78
|
|
|
73
79
|
const initWalletSelection = async () => {
|
|
74
|
-
const walletSelectionPageResponse = await dispatch(
|
|
75
|
-
checkoutApi.endpoints.setWalletSelectionPage.initiate({
|
|
76
|
-
payment_option: preOrder.payment_option?.pk
|
|
77
|
-
})
|
|
78
|
-
).unwrap();
|
|
79
|
-
|
|
80
|
-
const walletPaymentPageContext =
|
|
81
|
-
walletSelectionPageResponse.context_list.find(
|
|
82
|
-
(c) => c.page_name === 'WalletPaymentPage'
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
if (!walletPaymentPageContext) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// FIX: Only call setWalletPaymentPage if not already initialized
|
|
90
80
|
if (!walletPaymentInitialized.current) {
|
|
91
81
|
walletPaymentInitialized.current = true;
|
|
92
|
-
dispatch(checkoutApi.endpoints.setWalletPaymentPage.initiate({}));
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
82
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
const walletPaymentPageResponse = await dispatch(
|
|
101
|
-
checkoutApi.endpoints.setWalletPaymentPage.initiate({
|
|
102
|
-
payment_token: JSON.stringify(paymentData)
|
|
83
|
+
const walletSelectionPageResponse = await dispatch(
|
|
84
|
+
checkoutApi.endpoints.setWalletSelectionPage.initiate({
|
|
85
|
+
payment_option: preOrder.payment_option?.pk
|
|
103
86
|
})
|
|
104
87
|
).unwrap();
|
|
105
88
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
walletPaymentPageResponse.context_list.find(
|
|
113
|
-
(c) => c.page_name === 'WalletCompletePage'
|
|
114
|
-
)
|
|
115
|
-
) {
|
|
116
|
-
const paymentCompleteResponse = await dispatch(
|
|
117
|
-
checkoutApi.endpoints.setWalletCompletePage.initiate(true)
|
|
118
|
-
).unwrap();
|
|
89
|
+
const walletPaymentPageContext =
|
|
90
|
+
walletSelectionPageResponse.context_list.find(
|
|
91
|
+
(c) => c.page_name === 'WalletPaymentPage'
|
|
92
|
+
);
|
|
119
93
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
paymentCompleteResponse.context_list.find(
|
|
127
|
-
(c) => c.page_name === 'ThankYouPage'
|
|
128
|
-
)
|
|
129
|
-
) {
|
|
130
|
-
const redirectUrl = paymentCompleteResponse.context_list.find(
|
|
131
|
-
(c) => c.page_name === 'ThankYouPage'
|
|
132
|
-
)?.page_context.context_data.redirect_url;
|
|
133
|
-
|
|
134
|
-
const redirectUrlWithLocale = `${
|
|
135
|
-
window.location.origin
|
|
136
|
-
}${getUrlPathWithLocale(
|
|
137
|
-
redirectUrl,
|
|
138
|
-
getCookie('pz-locale') || 'en'
|
|
139
|
-
)}`;
|
|
140
|
-
|
|
141
|
-
window.location.href = redirectUrlWithLocale;
|
|
142
|
-
}
|
|
94
|
+
if (walletPaymentPageContext) {
|
|
95
|
+
dispatch(checkoutApi.endpoints.setWalletPaymentPage.initiate({}));
|
|
143
96
|
}
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.error('Error processing payment completion:', error);
|
|
146
|
-
setErrors(error);
|
|
147
97
|
}
|
|
148
98
|
};
|
|
149
99
|
|
|
150
|
-
const
|
|
151
|
-
console.error('Payment error occurred:', error);
|
|
152
|
-
setErrors(error);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const initFlowPaymentWebComponents = async ({
|
|
100
|
+
const refreshPaymentSessionAndInitFlow = async ({
|
|
156
101
|
publicKey
|
|
157
102
|
}: {
|
|
158
103
|
publicKey: string;
|
|
@@ -162,13 +107,70 @@ export default function FlowPayment({
|
|
|
162
107
|
return;
|
|
163
108
|
}
|
|
164
109
|
|
|
165
|
-
// Check if amount has actually changed
|
|
166
|
-
if (lastAmountRef.current === currentAmount && flowComponentRef.current) {
|
|
167
|
-
return; // Don't recreate component if amount hasn't changed
|
|
168
|
-
}
|
|
169
|
-
|
|
170
110
|
isInitializingRef.current = true;
|
|
171
111
|
|
|
112
|
+
try {
|
|
113
|
+
// Step 1: Re-set the current payment option to refresh the session with new amount
|
|
114
|
+
if (preOrder.payment_option?.pk) {
|
|
115
|
+
const paymentOptionResponse = await setPaymentOption(
|
|
116
|
+
preOrder.payment_option.pk
|
|
117
|
+
).unwrap();
|
|
118
|
+
|
|
119
|
+
// Check if WalletSelectionPage is available in the context list
|
|
120
|
+
const walletSelectionPageContext =
|
|
121
|
+
paymentOptionResponse.context_list?.find(
|
|
122
|
+
(c) => c.page_name === 'WalletSelectionPage'
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (!walletSelectionPageContext) {
|
|
126
|
+
console.warn(
|
|
127
|
+
'WalletSelectionPage not found in payment option response context list'
|
|
128
|
+
);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Step 2: Set wallet selection page
|
|
134
|
+
const walletSelectionResponse = await setWalletSelectionPage({
|
|
135
|
+
payment_option: preOrder.payment_option?.pk
|
|
136
|
+
}).unwrap();
|
|
137
|
+
|
|
138
|
+
const walletPaymentPageContext =
|
|
139
|
+
walletSelectionResponse.context_list?.find(
|
|
140
|
+
(c) => c.page_name === 'WalletPaymentPage'
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
if (!walletPaymentPageContext) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Step 3: Set wallet payment page to get updated payment session
|
|
148
|
+
const walletPaymentResponse = await setWalletPaymentPage({}).unwrap();
|
|
149
|
+
|
|
150
|
+
// Step 4: Initialize flow component with fresh payment session
|
|
151
|
+
await initFlowPaymentWebComponents({
|
|
152
|
+
publicKey,
|
|
153
|
+
paymentSession:
|
|
154
|
+
walletPaymentResponse?.pre_order?.context_extras ||
|
|
155
|
+
preOrder.context_extras
|
|
156
|
+
});
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error(
|
|
159
|
+
'Error refreshing payment session and initializing flow:',
|
|
160
|
+
error
|
|
161
|
+
);
|
|
162
|
+
} finally {
|
|
163
|
+
isInitializingRef.current = false;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const initFlowPaymentWebComponents = async ({
|
|
168
|
+
publicKey,
|
|
169
|
+
paymentSession
|
|
170
|
+
}: {
|
|
171
|
+
publicKey: string;
|
|
172
|
+
paymentSession?: any;
|
|
173
|
+
}) => {
|
|
172
174
|
try {
|
|
173
175
|
// Destroy existing flow component if it exists
|
|
174
176
|
if (flowComponentRef.current) {
|
|
@@ -186,49 +188,23 @@ export default function FlowPayment({
|
|
|
186
188
|
container.innerHTML = '';
|
|
187
189
|
}
|
|
188
190
|
|
|
189
|
-
//
|
|
190
|
-
let paymentSession = preOrder.context_extras;
|
|
191
|
-
|
|
192
|
-
// Only get fresh payment data if we don't have a valid session
|
|
193
|
-
if (!paymentSession && lastAmountRef.current !== currentAmount) {
|
|
194
|
-
// Check if another call is already in progress
|
|
195
|
-
if (!walletPaymentInitialized.current) {
|
|
196
|
-
walletPaymentInitialized.current = true;
|
|
197
|
-
const walletPaymentResponse = await dispatch(
|
|
198
|
-
checkoutApi.endpoints.setWalletPaymentPage.initiate({})
|
|
199
|
-
).unwrap();
|
|
200
|
-
paymentSession =
|
|
201
|
-
walletPaymentResponse?.pre_order?.context_extras ||
|
|
202
|
-
preOrder.context_extras;
|
|
203
|
-
} else {
|
|
204
|
-
// Use existing context_extras if another call was already made
|
|
205
|
-
paymentSession = preOrder.context_extras;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Update the last amount reference after getting fresh data
|
|
191
|
+
// Update the last amount reference
|
|
210
192
|
lastAmountRef.current = currentAmount;
|
|
211
193
|
|
|
212
194
|
const checkout = await loadCheckoutWebComponents({
|
|
213
195
|
publicKey,
|
|
214
|
-
environment,
|
|
196
|
+
environment: options?.environment || 'production',
|
|
215
197
|
locale: options?.locale || 'en',
|
|
216
198
|
translations: options?.translations,
|
|
217
|
-
paymentSession:
|
|
199
|
+
paymentSession:
|
|
200
|
+
paymentSession || (preOrder.context_extras as PaymentSessionResponse),
|
|
218
201
|
appearance: options?.appearance,
|
|
219
202
|
componentOptions: options?.componentOptions
|
|
220
203
|
? { flow: options.componentOptions }
|
|
221
204
|
: undefined
|
|
222
205
|
});
|
|
223
206
|
|
|
224
|
-
const flowComponent = checkout.create('flow'
|
|
225
|
-
onPaymentCompleted: async (_self, paymentResponse) => {
|
|
226
|
-
handlePaymentSuccess(paymentResponse);
|
|
227
|
-
},
|
|
228
|
-
onError: async (_self, error) => {
|
|
229
|
-
handlePaymentError(error);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
207
|
+
const flowComponent = checkout.create('flow');
|
|
232
208
|
flowComponentRef.current = flowComponent;
|
|
233
209
|
|
|
234
210
|
if (container) {
|
|
@@ -236,8 +212,6 @@ export default function FlowPayment({
|
|
|
236
212
|
}
|
|
237
213
|
} catch (error) {
|
|
238
214
|
console.error('Error initializing flow payment components:', error);
|
|
239
|
-
} finally {
|
|
240
|
-
isInitializingRef.current = false;
|
|
241
215
|
}
|
|
242
216
|
};
|
|
243
217
|
|
|
@@ -245,6 +219,7 @@ export default function FlowPayment({
|
|
|
245
219
|
initWalletSelection();
|
|
246
220
|
}, []);
|
|
247
221
|
|
|
222
|
+
// Initial flow component initialization
|
|
248
223
|
useEffect(() => {
|
|
249
224
|
if (
|
|
250
225
|
!preOrder.wallet_method ||
|
|
@@ -255,16 +230,37 @@ export default function FlowPayment({
|
|
|
255
230
|
return;
|
|
256
231
|
}
|
|
257
232
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
233
|
+
// Only initialize if component doesn't exist yet (initial mount)
|
|
234
|
+
if (!flowComponentRef.current) {
|
|
235
|
+
initFlowPaymentWebComponents({
|
|
236
|
+
publicKey: walletPaymentData.data.public_key
|
|
237
|
+
});
|
|
238
|
+
}
|
|
261
239
|
}, [
|
|
262
240
|
preOrder.wallet_method,
|
|
263
241
|
preOrder.token,
|
|
264
|
-
currentAmount, // Use memoized amount instead of preOrder.total_amount
|
|
265
242
|
walletPaymentData?.data?.public_key
|
|
266
243
|
]);
|
|
267
244
|
|
|
245
|
+
// Handle amount changes by refreshing payment session
|
|
246
|
+
useEffect(() => {
|
|
247
|
+
if (
|
|
248
|
+
!preOrder.wallet_method ||
|
|
249
|
+
!preOrder.token ||
|
|
250
|
+
!walletPaymentData?.data?.public_key ||
|
|
251
|
+
preOrder.wallet_method !== 'checkout_flow'
|
|
252
|
+
) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Only refresh if component exists and amount has changed
|
|
257
|
+
if (flowComponentRef.current && lastAmountRef.current !== currentAmount) {
|
|
258
|
+
refreshPaymentSessionAndInitFlow({
|
|
259
|
+
publicKey: walletPaymentData.data.public_key
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}, [currentAmount]);
|
|
263
|
+
|
|
268
264
|
// Cleanup function when component unmounts
|
|
269
265
|
useEffect(() => {
|
|
270
266
|
return () => {
|
|
@@ -280,20 +276,5 @@ export default function FlowPayment({
|
|
|
280
276
|
};
|
|
281
277
|
}, []);
|
|
282
278
|
|
|
283
|
-
return
|
|
284
|
-
<div className="flow-payment-container">
|
|
285
|
-
<div id="flow-container"></div>
|
|
286
|
-
{errors && (
|
|
287
|
-
<div className="text-error-100 text-xs mt-5">
|
|
288
|
-
{typeof errors === 'string'
|
|
289
|
-
? errors
|
|
290
|
-
: Array.isArray(errors)
|
|
291
|
-
? errors.join(', ')
|
|
292
|
-
: typeof errors === 'object'
|
|
293
|
-
? Object.values(errors ?? {}).join(', ')
|
|
294
|
-
: 'An error occurred during payment processing'}
|
|
295
|
-
</div>
|
|
296
|
-
)}
|
|
297
|
-
</div>
|
|
298
|
-
);
|
|
279
|
+
return <div id="flow-container" className="flow-payment-container"></div>;
|
|
299
280
|
}
|