@tagadapay/headless-sdk 1.3.2 → 1.5.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/README.md +84 -7
- package/dist/core/client.d.ts +6 -0
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +6 -0
- package/dist/core/client.js.map +1 -1
- package/dist/core/http.js +2 -2
- package/dist/core/http.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/modules/checkout.d.ts +113 -12
- package/dist/core/modules/checkout.d.ts.map +1 -1
- package/dist/core/modules/checkout.js +201 -55
- package/dist/core/modules/checkout.js.map +1 -1
- package/dist/core/modules/payment.d.ts +120 -4
- package/dist/core/modules/payment.d.ts.map +1 -1
- package/dist/core/modules/payment.js +336 -7
- package/dist/core/modules/payment.js.map +1 -1
- package/dist/core/types.d.ts +112 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/react/hooks/useCheckout.d.ts.map +1 -1
- package/dist/react/hooks/useCheckout.js +9 -15
- package/dist/react/hooks/useCheckout.js.map +1 -1
- package/dist/react/hooks/usePayment.d.ts +58 -13
- package/dist/react/hooks/usePayment.d.ts.map +1 -1
- package/dist/react/hooks/usePayment.js +124 -11
- package/dist/react/hooks/usePayment.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/stripe/StripeExpressButton.d.ts +30 -0
- package/dist/stripe/StripeExpressButton.d.ts.map +1 -0
- package/dist/stripe/StripeExpressButton.js +32 -0
- package/dist/stripe/StripeExpressButton.js.map +1 -0
- package/dist/stripe/StripeExpressCheckout.d.ts +98 -0
- package/dist/stripe/StripeExpressCheckout.d.ts.map +1 -0
- package/dist/stripe/StripeExpressCheckout.js +198 -0
- package/dist/stripe/StripeExpressCheckout.js.map +1 -0
- package/dist/stripe/index.d.ts +8 -0
- package/dist/stripe/index.d.ts.map +1 -0
- package/dist/stripe/index.js +15 -0
- package/dist/stripe/index.js.map +1 -0
- package/dist/stripe/useStripeExpress.d.ts +54 -0
- package/dist/stripe/useStripeExpress.d.ts.map +1 -0
- package/dist/stripe/useStripeExpress.js +126 -0
- package/dist/stripe/useStripeExpress.js.map +1 -0
- package/dist/tagada-headless-react.min.js +2 -2
- package/dist/tagada-headless-react.min.js.map +3 -3
- package/dist/tagada-headless.js +483 -66
- package/dist/tagada-headless.min.js +2 -2
- package/dist/tagada-headless.min.js.map +3 -3
- package/package.json +9 -3
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
const EXPRESS_METHOD_KEYS = ['apple_pay', 'google_pay', 'paypal', 'link', 'klarna_express'];
|
|
2
|
+
/**
|
|
3
|
+
* Session-based Stripe Express Checkout integration.
|
|
4
|
+
*
|
|
5
|
+
* Mounts the Stripe `ExpressCheckoutElement` (Apple Pay, Google Pay, Link,
|
|
6
|
+
* PayPal, Klarna express) into any DOM container, wired to a Tagada
|
|
7
|
+
* checkout session. Drives the full flow:
|
|
8
|
+
* mount → wallet confirm → backend `payDirect` (`processStripeExpress`)
|
|
9
|
+
* → `stripe.confirmPayment` → poll payment status → emit `success`.
|
|
10
|
+
*
|
|
11
|
+
* **Session-free / partner S2S flow?** Use the lower-level primitive
|
|
12
|
+
* `startStripeExpressCheckout` exported from `@tagadapay/core-js`
|
|
13
|
+
* (also re-exported from `@tagadapay/headless-sdk/stripe`). It uses
|
|
14
|
+
* Stripe's older Payment Request API, stops at tokenization, and
|
|
15
|
+
* returns a `paymentMethodId` for partner-server-side processing.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { createHeadlessClient } from '@tagadapay/headless-sdk';
|
|
20
|
+
* import { StripeExpressCheckout } from '@tagadapay/headless-sdk/stripe';
|
|
21
|
+
*
|
|
22
|
+
* const client = createHeadlessClient({ storeId: 'store_xxx' });
|
|
23
|
+
* const session = await client.checkout.loadSession(checkoutToken);
|
|
24
|
+
* const express = await client.payment.getExpressMethods(session.id);
|
|
25
|
+
*
|
|
26
|
+
* const ece = new StripeExpressCheckout({
|
|
27
|
+
* client,
|
|
28
|
+
* publishableKey: express.applePay?.publishableKey!,
|
|
29
|
+
* processorId: express.applePay?.processorId!,
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* ece.on('success', ({ payment }) => console.log('Paid!', payment.id));
|
|
33
|
+
* ece.on('error', (msg) => console.error(msg));
|
|
34
|
+
*
|
|
35
|
+
* await ece.mount(document.getElementById('express-container')!, {
|
|
36
|
+
* checkoutSessionId: session.id,
|
|
37
|
+
* amount: session.totals.total,
|
|
38
|
+
* currency: session.totals.currency,
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export class StripeExpressCheckout {
|
|
43
|
+
constructor(opts) {
|
|
44
|
+
this.stripe = null;
|
|
45
|
+
this.elements = null;
|
|
46
|
+
this.expressElement = null;
|
|
47
|
+
this.container = null;
|
|
48
|
+
this.isProcessing = false;
|
|
49
|
+
this.listeners = {};
|
|
50
|
+
this.client = opts.client;
|
|
51
|
+
this.publishableKey = opts.publishableKey;
|
|
52
|
+
this.processorId = opts.processorId;
|
|
53
|
+
this.enabledMethods = opts.enabledMethods ?? [...EXPRESS_METHOD_KEYS];
|
|
54
|
+
this.buttonHeight = opts.buttonHeight ?? 48;
|
|
55
|
+
this.buttonType = opts.buttonType ?? 'buy';
|
|
56
|
+
this.emailRequired = opts.emailRequired ?? true;
|
|
57
|
+
this.billingAddressRequired = opts.billingAddressRequired ?? true;
|
|
58
|
+
}
|
|
59
|
+
on(event, handler) {
|
|
60
|
+
if (!this.listeners[event]) {
|
|
61
|
+
this.listeners[event] = new Set();
|
|
62
|
+
}
|
|
63
|
+
this.listeners[event].add(handler);
|
|
64
|
+
}
|
|
65
|
+
off(event, handler) {
|
|
66
|
+
this.listeners[event]?.delete(handler);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Load Stripe.js, create Elements, and mount the ExpressCheckoutElement.
|
|
70
|
+
*/
|
|
71
|
+
async mount(container, opts) {
|
|
72
|
+
this.container = container;
|
|
73
|
+
const { loadStripe } = await import('@stripe/stripe-js');
|
|
74
|
+
const stripe = await loadStripe(this.publishableKey);
|
|
75
|
+
if (!stripe) {
|
|
76
|
+
this.emit('error', 'Failed to load Stripe.js');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
this.stripe = stripe;
|
|
80
|
+
const amount = Math.max(Math.round(opts.amount), 1);
|
|
81
|
+
const currency = opts.currency.toLowerCase();
|
|
82
|
+
this.elements = stripe.elements({
|
|
83
|
+
mode: 'payment',
|
|
84
|
+
amount,
|
|
85
|
+
currency,
|
|
86
|
+
});
|
|
87
|
+
const methodEnabled = (key) => this.enabledMethods.includes(key);
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Stripe TS types don't expose expressCheckout overload
|
|
89
|
+
this.expressElement = this.elements.create('expressCheckout', {
|
|
90
|
+
buttonType: {
|
|
91
|
+
applePay: this.buttonType,
|
|
92
|
+
googlePay: this.buttonType,
|
|
93
|
+
},
|
|
94
|
+
buttonHeight: this.buttonHeight,
|
|
95
|
+
paymentMethods: {
|
|
96
|
+
applePay: methodEnabled('apple_pay') ? 'always' : 'never',
|
|
97
|
+
googlePay: methodEnabled('google_pay') ? 'always' : 'never',
|
|
98
|
+
link: methodEnabled('link') ? 'auto' : 'never',
|
|
99
|
+
paypal: methodEnabled('paypal') ? 'auto' : 'never',
|
|
100
|
+
klarna: methodEnabled('klarna_express') ? 'auto' : 'never',
|
|
101
|
+
},
|
|
102
|
+
emailRequired: this.emailRequired,
|
|
103
|
+
billingAddressRequired: this.billingAddressRequired,
|
|
104
|
+
});
|
|
105
|
+
this.expressElement.on('ready', ({ availablePaymentMethods }) => {
|
|
106
|
+
if (availablePaymentMethods) {
|
|
107
|
+
this.emit('ready', { availablePaymentMethods });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
this.expressElement.on('cancel', () => {
|
|
111
|
+
this.isProcessing = false;
|
|
112
|
+
this.emit('cancel', undefined);
|
|
113
|
+
});
|
|
114
|
+
this.expressElement.on('confirm', async (event) => {
|
|
115
|
+
if (this.isProcessing)
|
|
116
|
+
return;
|
|
117
|
+
this.isProcessing = true;
|
|
118
|
+
try {
|
|
119
|
+
const { error: submitError } = await this.elements.submit();
|
|
120
|
+
if (submitError) {
|
|
121
|
+
this.emit('error', submitError.message ?? 'Validation failed');
|
|
122
|
+
this.isProcessing = false;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const payResult = await this.client.payment.processStripeExpress({
|
|
126
|
+
checkoutSessionId: opts.checkoutSessionId,
|
|
127
|
+
processorId: this.processorId,
|
|
128
|
+
paymentMethod: event.expressPaymentType,
|
|
129
|
+
});
|
|
130
|
+
const clientSecret = this.extractClientSecret(payResult);
|
|
131
|
+
if (!clientSecret) {
|
|
132
|
+
this.emit('error', 'Express checkout configuration missing — no client secret returned');
|
|
133
|
+
this.isProcessing = false;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const { error: confirmError } = await this.stripe.confirmPayment({
|
|
137
|
+
elements: this.elements,
|
|
138
|
+
clientSecret,
|
|
139
|
+
confirmParams: { return_url: window.location.href },
|
|
140
|
+
redirect: 'if_required',
|
|
141
|
+
});
|
|
142
|
+
if (confirmError) {
|
|
143
|
+
this.emit('error', confirmError.message ?? 'Payment confirmation failed');
|
|
144
|
+
this.isProcessing = false;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const paymentId = payResult.payment.id;
|
|
148
|
+
const status = await this.client.payment.pollPaymentStatus(paymentId);
|
|
149
|
+
if (status.status === 'succeeded') {
|
|
150
|
+
this.emit('success', { payment: status, order: status.order });
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.emit('error', `Payment ${status.status}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
const msg = err instanceof Error ? err.message : 'Express checkout failed';
|
|
158
|
+
this.emit('error', msg);
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
this.isProcessing = false;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
this.expressElement.mount(container);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Update the payment amount (e.g. after a cart change).
|
|
168
|
+
*/
|
|
169
|
+
updateAmount(amount, currency) {
|
|
170
|
+
if (!this.elements)
|
|
171
|
+
return;
|
|
172
|
+
const update = { amount: Math.max(Math.round(amount), 1) };
|
|
173
|
+
if (currency)
|
|
174
|
+
update.currency = currency.toLowerCase();
|
|
175
|
+
this.elements.update(update);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Clean up: unmount the element and release references.
|
|
179
|
+
*/
|
|
180
|
+
unmount() {
|
|
181
|
+
this.expressElement?.unmount();
|
|
182
|
+
this.expressElement = null;
|
|
183
|
+
this.elements = null;
|
|
184
|
+
this.stripe = null;
|
|
185
|
+
this.container = null;
|
|
186
|
+
this.listeners = {};
|
|
187
|
+
}
|
|
188
|
+
emit(event, data) {
|
|
189
|
+
this.listeners[event]?.forEach((handler) => handler(data));
|
|
190
|
+
}
|
|
191
|
+
extractClientSecret(payResult) {
|
|
192
|
+
return payResult.payment?.requireActionData?.metadata?.stripeExpressCheckout
|
|
193
|
+
? (payResult.payment.requireActionData.metadata
|
|
194
|
+
.stripeExpressCheckout.clientSecret)
|
|
195
|
+
: undefined;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=StripeExpressCheckout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StripeExpressCheckout.js","sourceRoot":"","sources":["../../src/stripe/StripeExpressCheckout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { StripeExpressCheckout } from './StripeExpressCheckout.js';
|
|
2
|
+
export { useStripeExpress } from './useStripeExpress.js';
|
|
3
|
+
export type { UseStripeExpressOptions, UseStripeExpressReturn } from './useStripeExpress.js';
|
|
4
|
+
export { StripeExpressButton } from './StripeExpressButton.js';
|
|
5
|
+
export type { StripeExpressButtonProps } from './StripeExpressButton.js';
|
|
6
|
+
export type { StripeExpressOptions } from '../core/types.js';
|
|
7
|
+
export { startStripeExpressCheckout, isStripeExpressAvailable, type StripeExpressOptions as CoreStripeExpressOptions, type StripeExpressShippingAddress, type StripeExpressTokenResult, type StripeExpressCallbacks, } from '@tagadapay/core-js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/stripe/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAO7D,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,KAAK,oBAAoB,IAAI,wBAAwB,EACrD,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────
|
|
2
|
+
// Session-based Stripe Express Checkout — drives Stripe's Express
|
|
3
|
+
// Checkout Element (drop-in widget) wired to a checkout session.
|
|
4
|
+
// Used by sites built on `@tagadapay/headless-sdk`.
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────
|
|
6
|
+
export { StripeExpressCheckout } from './StripeExpressCheckout.js';
|
|
7
|
+
export { useStripeExpress } from './useStripeExpress.js';
|
|
8
|
+
export { StripeExpressButton } from './StripeExpressButton.js';
|
|
9
|
+
// ─────────────────────────────────────────────────────────────────
|
|
10
|
+
// Session-free wallet tokenization — re-exported from `@tagadapay/core-js`
|
|
11
|
+
// for partner / S2S flows that don't use a checkout session. Stops at
|
|
12
|
+
// Stripe `paymentMethodId`; the partner forwards it to their server.
|
|
13
|
+
// ─────────────────────────────────────────────────────────────────
|
|
14
|
+
export { startStripeExpressCheckout, isStripeExpressAvailable, } from '@tagadapay/core-js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/stripe/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,kEAAkE;AAClE,iEAAiE;AACjE,oDAAoD;AACpD,oEAAoE;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAK/D,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,qEAAqE;AACrE,oEAAoE;AACpE,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,GAKzB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ExpressMethods, PaymentStatus, PaymentSetupConfig } from '../core/types.js';
|
|
2
|
+
export interface UseStripeExpressOptions {
|
|
3
|
+
checkoutSessionId: string;
|
|
4
|
+
amount: number;
|
|
5
|
+
currency: string;
|
|
6
|
+
onSuccess?: (result: {
|
|
7
|
+
payment: PaymentStatus;
|
|
8
|
+
order?: {
|
|
9
|
+
id: string;
|
|
10
|
+
checkoutSessionId?: string;
|
|
11
|
+
};
|
|
12
|
+
}) => void;
|
|
13
|
+
onError?: (error: string) => void;
|
|
14
|
+
onCancel?: () => void;
|
|
15
|
+
/** Override payment setup config (skips API discovery). */
|
|
16
|
+
paymentSetupConfig?: PaymentSetupConfig;
|
|
17
|
+
}
|
|
18
|
+
export interface UseStripeExpressReturn {
|
|
19
|
+
/** Attach this ref to a <div> — the express buttons will mount inside it. */
|
|
20
|
+
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
21
|
+
/** True once the Stripe element has rendered at least one wallet button. */
|
|
22
|
+
isReady: boolean;
|
|
23
|
+
/** True while a payment is being confirmed. */
|
|
24
|
+
isProcessing: boolean;
|
|
25
|
+
/** Discovered express methods (null while loading). */
|
|
26
|
+
expressMethods: ExpressMethods | null;
|
|
27
|
+
/** Update the displayed amount after cart changes. */
|
|
28
|
+
updateAmount: (amount: number, currency?: string) => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* React hook that mounts the Stripe Express Checkout Element into a ref'd container.
|
|
32
|
+
*
|
|
33
|
+
* Handles the full lifecycle: discover config -> load Stripe -> mount ECE ->
|
|
34
|
+
* onConfirm -> processStripeExpress -> stripe.confirmPayment -> poll -> callbacks.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* import { useStripeExpress } from '@tagadapay/headless-sdk/stripe';
|
|
39
|
+
*
|
|
40
|
+
* function ExpressSection({ sessionId, totals }) {
|
|
41
|
+
* const { containerRef, isReady } = useStripeExpress({
|
|
42
|
+
* checkoutSessionId: sessionId,
|
|
43
|
+
* amount: totals.total,
|
|
44
|
+
* currency: totals.currency,
|
|
45
|
+
* onSuccess: () => router.push('/confirmation'),
|
|
46
|
+
* onError: (msg) => toast.error(msg),
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* return <div ref={containerRef} style={{ display: isReady ? 'block' : 'none' }} />;
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export declare function useStripeExpress(opts: UseStripeExpressOptions): UseStripeExpressReturn;
|
|
54
|
+
//# sourceMappingURL=useStripeExpress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStripeExpress.d.ts","sourceRoot":"","sources":["../../src/stripe/useStripeExpress.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE1F,MAAM,WAAW,uBAAuB;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7G,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAED,MAAM,WAAW,sBAAsB;IACrC,6EAA6E;IAC7E,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACrD,4EAA4E;IAC5E,OAAO,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,YAAY,EAAE,OAAO,CAAC;IACtB,uDAAuD;IACvD,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,sDAAsD;IACtD,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,sBAAsB,CAoFtF"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
2
|
+
import { useHeadlessClient } from '../react/provider.js';
|
|
3
|
+
import { StripeExpressCheckout } from './StripeExpressCheckout.js';
|
|
4
|
+
/**
|
|
5
|
+
* React hook that mounts the Stripe Express Checkout Element into a ref'd container.
|
|
6
|
+
*
|
|
7
|
+
* Handles the full lifecycle: discover config -> load Stripe -> mount ECE ->
|
|
8
|
+
* onConfirm -> processStripeExpress -> stripe.confirmPayment -> poll -> callbacks.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { useStripeExpress } from '@tagadapay/headless-sdk/stripe';
|
|
13
|
+
*
|
|
14
|
+
* function ExpressSection({ sessionId, totals }) {
|
|
15
|
+
* const { containerRef, isReady } = useStripeExpress({
|
|
16
|
+
* checkoutSessionId: sessionId,
|
|
17
|
+
* amount: totals.total,
|
|
18
|
+
* currency: totals.currency,
|
|
19
|
+
* onSuccess: () => router.push('/confirmation'),
|
|
20
|
+
* onError: (msg) => toast.error(msg),
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* return <div ref={containerRef} style={{ display: isReady ? 'block' : 'none' }} />;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function useStripeExpress(opts) {
|
|
28
|
+
const client = useHeadlessClient();
|
|
29
|
+
const containerRef = useRef(null);
|
|
30
|
+
const eceRef = useRef(null);
|
|
31
|
+
const [isReady, setIsReady] = useState(false);
|
|
32
|
+
const [isProcessing, setIsProcessing] = useState(false);
|
|
33
|
+
const [expressMethods, setExpressMethods] = useState(null);
|
|
34
|
+
const callbacksRef = useRef(opts);
|
|
35
|
+
callbacksRef.current = opts;
|
|
36
|
+
const { checkoutSessionId, amount, currency, paymentSetupConfig } = opts;
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!checkoutSessionId || !containerRef.current)
|
|
39
|
+
return;
|
|
40
|
+
let mounted = true;
|
|
41
|
+
let instance = null;
|
|
42
|
+
const init = async () => {
|
|
43
|
+
const express = await client.payment.getExpressMethods(checkoutSessionId, paymentSetupConfig ? { paymentSetupConfig } : undefined);
|
|
44
|
+
if (!mounted)
|
|
45
|
+
return;
|
|
46
|
+
setExpressMethods(express);
|
|
47
|
+
const stripeMethod = findStripeExpressMethod(express);
|
|
48
|
+
if (!stripeMethod?.publishableKey || !stripeMethod?.processorId)
|
|
49
|
+
return;
|
|
50
|
+
instance = new StripeExpressCheckout({
|
|
51
|
+
client,
|
|
52
|
+
publishableKey: stripeMethod.publishableKey,
|
|
53
|
+
processorId: stripeMethod.processorId,
|
|
54
|
+
enabledMethods: stripeMethod.enabledMethods,
|
|
55
|
+
});
|
|
56
|
+
instance.on('ready', () => {
|
|
57
|
+
if (mounted)
|
|
58
|
+
setIsReady(true);
|
|
59
|
+
});
|
|
60
|
+
instance.on('success', (result) => {
|
|
61
|
+
if (mounted)
|
|
62
|
+
setIsProcessing(false);
|
|
63
|
+
callbacksRef.current.onSuccess?.(result);
|
|
64
|
+
});
|
|
65
|
+
instance.on('error', (msg) => {
|
|
66
|
+
if (mounted)
|
|
67
|
+
setIsProcessing(false);
|
|
68
|
+
callbacksRef.current.onError?.(msg);
|
|
69
|
+
});
|
|
70
|
+
instance.on('cancel', () => {
|
|
71
|
+
if (mounted)
|
|
72
|
+
setIsProcessing(false);
|
|
73
|
+
callbacksRef.current.onCancel?.();
|
|
74
|
+
});
|
|
75
|
+
eceRef.current = instance;
|
|
76
|
+
if (containerRef.current) {
|
|
77
|
+
await instance.mount(containerRef.current, {
|
|
78
|
+
checkoutSessionId,
|
|
79
|
+
amount,
|
|
80
|
+
currency,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
void init();
|
|
85
|
+
return () => {
|
|
86
|
+
mounted = false;
|
|
87
|
+
instance?.unmount();
|
|
88
|
+
eceRef.current = null;
|
|
89
|
+
setIsReady(false);
|
|
90
|
+
};
|
|
91
|
+
}, [client, checkoutSessionId, paymentSetupConfig]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
eceRef.current?.updateAmount(amount, currency);
|
|
94
|
+
}, [amount, currency]);
|
|
95
|
+
const updateAmount = useCallback((newAmount, newCurrency) => {
|
|
96
|
+
eceRef.current?.updateAmount(newAmount, newCurrency);
|
|
97
|
+
}, []);
|
|
98
|
+
return { containerRef, isReady, isProcessing, expressMethods, updateAmount };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Find a Stripe ECE-capable method from the express methods map.
|
|
102
|
+
* Returns publishableKey, processorId, and list of enabled sub-methods.
|
|
103
|
+
*/
|
|
104
|
+
function findStripeExpressMethod(express) {
|
|
105
|
+
const allMethods = [
|
|
106
|
+
{ key: 'apple_pay', entry: express.applePay },
|
|
107
|
+
{ key: 'google_pay', entry: express.googlePay },
|
|
108
|
+
{ key: 'paypal', entry: express.paypal },
|
|
109
|
+
{ key: 'link', entry: express.link },
|
|
110
|
+
{ key: 'klarna_express', entry: express.klarna },
|
|
111
|
+
];
|
|
112
|
+
for (const { entry } of allMethods) {
|
|
113
|
+
if (entry?.publishableKey && entry.processorId) {
|
|
114
|
+
const enabledMethods = allMethods
|
|
115
|
+
.filter(({ entry: e }) => e?.available && e.publishableKey === entry.publishableKey)
|
|
116
|
+
.map(({ key }) => key);
|
|
117
|
+
return {
|
|
118
|
+
publishableKey: entry.publishableKey,
|
|
119
|
+
processorId: entry.processorId,
|
|
120
|
+
enabledMethods,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=useStripeExpress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStripeExpress.js","sourceRoot":"","sources":["../../src/stripe/useStripeExpress.ts"],"names":[],"mappings":"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"}
|