@tagadapay/headless-sdk 1.4.0 → 1.5.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/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/modules/checkout.d.ts +42 -4
- package/dist/core/modules/checkout.d.ts.map +1 -1
- package/dist/core/modules/checkout.js +72 -20
- package/dist/core/modules/checkout.js.map +1 -1
- package/dist/core/modules/payment.d.ts +58 -3
- package/dist/core/modules/payment.d.ts.map +1 -1
- package/dist/core/modules/payment.js +111 -7
- package/dist/core/modules/payment.js.map +1 -1
- package/dist/core/types.d.ts +32 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/react/hooks/useCheckout.d.ts +13 -0
- package/dist/react/hooks/useCheckout.d.ts.map +1 -1
- package/dist/react/hooks/useCheckout.js +23 -3
- package/dist/react/hooks/useCheckout.js.map +1 -1
- package/dist/react/hooks/usePayment.d.ts +19 -3
- package/dist/react/hooks/usePayment.d.ts.map +1 -1
- package/dist/react/hooks/usePayment.js +8 -3
- package/dist/react/hooks/usePayment.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- 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 +163 -33
- 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,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useStripeExpress } from './useStripeExpress.js';
|
|
3
|
+
/**
|
|
4
|
+
* Drop-in React component that renders Stripe Express Checkout buttons
|
|
5
|
+
* (Apple Pay, Google Pay, Link, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Internally uses `useStripeExpress` which handles the full flow:
|
|
8
|
+
* discover config -> load Stripe -> mount ECE -> confirm -> poll -> callbacks.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { StripeExpressButton } from '@tagadapay/headless-sdk/stripe';
|
|
13
|
+
*
|
|
14
|
+
* <StripeExpressButton
|
|
15
|
+
* checkoutSessionId={session.id}
|
|
16
|
+
* amount={totals.total}
|
|
17
|
+
* currency={totals.currency}
|
|
18
|
+
* onSuccess={() => router.push('/confirmation')}
|
|
19
|
+
* onError={(msg) => toast.error(msg)}
|
|
20
|
+
* />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function StripeExpressButton({ className, style, ...hookOpts }) {
|
|
24
|
+
const { containerRef, isReady } = useStripeExpress(hookOpts);
|
|
25
|
+
return (_jsx("div", { ref: containerRef, className: className, style: {
|
|
26
|
+
visibility: isReady ? 'visible' : 'hidden',
|
|
27
|
+
minHeight: isReady ? undefined : 0,
|
|
28
|
+
overflow: isReady ? undefined : 'hidden',
|
|
29
|
+
...style,
|
|
30
|
+
} }));
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=StripeExpressButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StripeExpressButton.js","sourceRoot":"","sources":["../../src/stripe/StripeExpressButton.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAUzD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,EACT,KAAK,EACL,GAAG,QAAQ,EACc;IACzB,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE7D,OAAO,CACL,cACE,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE;YACL,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;YAC1C,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAClC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;YACxC,GAAG,KAAK;SACT,GACD,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { HeadlessClient } from '../core/client.js';
|
|
2
|
+
import type { StripeExpressOptions, PaymentStatus } from '../core/types.js';
|
|
3
|
+
type EventMap = {
|
|
4
|
+
ready: {
|
|
5
|
+
availablePaymentMethods: Record<string, boolean> | undefined;
|
|
6
|
+
};
|
|
7
|
+
success: {
|
|
8
|
+
payment: PaymentStatus;
|
|
9
|
+
order?: {
|
|
10
|
+
id: string;
|
|
11
|
+
checkoutSessionId?: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
error: string;
|
|
15
|
+
cancel: void;
|
|
16
|
+
};
|
|
17
|
+
type EventHandler<K extends keyof EventMap> = (data: EventMap[K]) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Session-based Stripe Express Checkout integration.
|
|
20
|
+
*
|
|
21
|
+
* Mounts the Stripe `ExpressCheckoutElement` (Apple Pay, Google Pay, Link,
|
|
22
|
+
* PayPal, Klarna express) into any DOM container, wired to a Tagada
|
|
23
|
+
* checkout session. Drives the full flow:
|
|
24
|
+
* mount → wallet confirm → backend `payDirect` (`processStripeExpress`)
|
|
25
|
+
* → `stripe.confirmPayment` → poll payment status → emit `success`.
|
|
26
|
+
*
|
|
27
|
+
* **Session-free / partner S2S flow?** Use the lower-level primitive
|
|
28
|
+
* `startStripeExpressCheckout` exported from `@tagadapay/core-js`
|
|
29
|
+
* (also re-exported from `@tagadapay/headless-sdk/stripe`). It uses
|
|
30
|
+
* Stripe's older Payment Request API, stops at tokenization, and
|
|
31
|
+
* returns a `paymentMethodId` for partner-server-side processing.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { createHeadlessClient } from '@tagadapay/headless-sdk';
|
|
36
|
+
* import { StripeExpressCheckout } from '@tagadapay/headless-sdk/stripe';
|
|
37
|
+
*
|
|
38
|
+
* const client = createHeadlessClient({ storeId: 'store_xxx' });
|
|
39
|
+
* const session = await client.checkout.loadSession(checkoutToken);
|
|
40
|
+
* const express = await client.payment.getExpressMethods(session.id);
|
|
41
|
+
*
|
|
42
|
+
* const ece = new StripeExpressCheckout({
|
|
43
|
+
* client,
|
|
44
|
+
* publishableKey: express.applePay?.publishableKey!,
|
|
45
|
+
* processorId: express.applePay?.processorId!,
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* ece.on('success', ({ payment }) => console.log('Paid!', payment.id));
|
|
49
|
+
* ece.on('error', (msg) => console.error(msg));
|
|
50
|
+
*
|
|
51
|
+
* await ece.mount(document.getElementById('express-container')!, {
|
|
52
|
+
* checkoutSessionId: session.id,
|
|
53
|
+
* amount: session.totals.total,
|
|
54
|
+
* currency: session.totals.currency,
|
|
55
|
+
* });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare class StripeExpressCheckout {
|
|
59
|
+
private stripe;
|
|
60
|
+
private elements;
|
|
61
|
+
private expressElement;
|
|
62
|
+
private container;
|
|
63
|
+
private isProcessing;
|
|
64
|
+
private listeners;
|
|
65
|
+
private readonly client;
|
|
66
|
+
private readonly publishableKey;
|
|
67
|
+
private readonly processorId;
|
|
68
|
+
private readonly enabledMethods;
|
|
69
|
+
private readonly buttonHeight;
|
|
70
|
+
private readonly buttonType;
|
|
71
|
+
private readonly emailRequired;
|
|
72
|
+
private readonly billingAddressRequired;
|
|
73
|
+
constructor(opts: {
|
|
74
|
+
client: HeadlessClient;
|
|
75
|
+
} & StripeExpressOptions);
|
|
76
|
+
on<K extends keyof EventMap>(event: K, handler: EventHandler<K>): void;
|
|
77
|
+
off<K extends keyof EventMap>(event: K, handler: EventHandler<K>): void;
|
|
78
|
+
/**
|
|
79
|
+
* Load Stripe.js, create Elements, and mount the ExpressCheckoutElement.
|
|
80
|
+
*/
|
|
81
|
+
mount(container: HTMLElement, opts: {
|
|
82
|
+
checkoutSessionId: string;
|
|
83
|
+
amount: number;
|
|
84
|
+
currency: string;
|
|
85
|
+
}): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Update the payment amount (e.g. after a cart change).
|
|
88
|
+
*/
|
|
89
|
+
updateAmount(amount: number, currency?: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Clean up: unmount the element and release references.
|
|
92
|
+
*/
|
|
93
|
+
unmount(): void;
|
|
94
|
+
private emit;
|
|
95
|
+
private extractClientSecret;
|
|
96
|
+
}
|
|
97
|
+
export {};
|
|
98
|
+
//# sourceMappingURL=StripeExpressCheckout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StripeExpressCheckout.d.ts","sourceRoot":"","sources":["../../src/stripe/StripeExpressCheckout.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAa,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAavF,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE;QAAE,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;KAAE,CAAC;IACxE,OAAO,EAAE;QAAE,OAAO,EAAE,aAAa,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,IAAI,CAAC;CACd,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,QAAQ,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAwD;IAEzE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAU;gBAErC,IAAI,EAAE;QAAE,MAAM,EAAE,cAAc,CAAA;KAAE,GAAG,oBAAoB;IAWnE,EAAE,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAOtE,GAAG,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAIvE;;OAEG;IACG,KAAK,CACT,SAAS,EAAE,WAAW,EACtB,IAAI,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GACpE,OAAO,CAAC,IAAI,CAAC;IA4GhB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IAOrD;;OAEG;IACH,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,mBAAmB;CAS5B"}
|
|
@@ -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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"}
|