@blocklet/payment-react-headless 1.26.0 → 1.26.2
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/es/checkout/context/CheckoutProvider.js +16 -4
- package/es/checkout/context/SessionContext.d.ts +2 -0
- package/es/checkout/core/crossSell.d.ts +3 -2
- package/es/checkout/core/crossSell.js +24 -8
- package/es/checkout/core/lineItems.d.ts +6 -5
- package/es/checkout/core/lineItems.js +48 -17
- package/es/checkout/core/promotion.d.ts +1 -1
- package/es/checkout/core/promotion.js +2 -1
- package/es/checkout/hooks/useBillingInterval.js +8 -5
- package/es/checkout/hooks/useCheckout.js +14 -9
- package/es/checkout/hooks/useCrossSell.js +11 -3
- package/es/checkout/hooks/useLineItems.js +36 -9
- package/es/checkout/hooks/usePaymentMethod.d.ts +1 -1
- package/es/checkout/hooks/usePaymentMethod.js +14 -4
- package/es/checkout/hooks/useUpsell.js +3 -3
- package/lib/checkout/context/CheckoutProvider.js +13 -4
- package/lib/checkout/context/SessionContext.d.ts +2 -0
- package/lib/checkout/core/crossSell.d.ts +3 -2
- package/lib/checkout/core/crossSell.js +36 -8
- package/lib/checkout/core/lineItems.d.ts +6 -5
- package/lib/checkout/core/lineItems.js +72 -18
- package/lib/checkout/core/promotion.d.ts +1 -1
- package/lib/checkout/core/promotion.js +4 -1
- package/lib/checkout/hooks/useBillingInterval.js +10 -5
- package/lib/checkout/hooks/useCheckout.js +18 -9
- package/lib/checkout/hooks/useCrossSell.js +5 -3
- package/lib/checkout/hooks/useLineItems.js +10 -8
- package/lib/checkout/hooks/usePaymentMethod.d.ts +1 -1
- package/lib/checkout/hooks/usePaymentMethod.js +20 -4
- package/lib/checkout/hooks/useUpsell.js +5 -3
- package/package.json +3 -3
- package/src/checkout/context/CheckoutProvider.tsx +18 -5
- package/src/checkout/context/SessionContext.ts +2 -0
- package/src/checkout/core/crossSell.ts +29 -8
- package/src/checkout/core/lineItems.ts +62 -18
- package/src/checkout/core/promotion.ts +6 -2
- package/src/checkout/hooks/useBillingInterval.ts +8 -5
- package/src/checkout/hooks/useCheckout.ts +15 -10
- package/src/checkout/hooks/useCrossSell.ts +11 -3
- package/src/checkout/hooks/useLineItems.ts +42 -9
- package/src/checkout/hooks/usePaymentMethod.ts +17 -5
- package/src/checkout/hooks/useUpsell.ts +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TCheckoutSessionExpanded, TPrice } from '@blocklet/payment-types';
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
2
|
+
import type { SessionData } from '../hooks/useCheckoutSession';
|
|
3
|
+
export declare function addCrossSellItem(sessionId: string, crossSellItemId: string, session: TCheckoutSessionExpanded | undefined | null, currencyId: string | null | undefined, refresh: (force?: boolean) => Promise<void>, sessionData?: SessionData | null, setSessionData?: (data: SessionData) => void): Promise<void>;
|
|
4
|
+
export declare function removeCrossSellItem(sessionId: string, session: TCheckoutSessionExpanded | undefined | null, currencyId: string | null | undefined, refresh: (force?: boolean) => Promise<void>, sessionData?: SessionData | null, setSessionData?: (data: SessionData) => void): Promise<void>;
|
|
4
5
|
export declare function fetchCrossSellItem(sessionId: string): Promise<TPrice | null>;
|
|
@@ -10,17 +10,45 @@ var _api = _interopRequireWildcard(require("../../shared/api"));
|
|
|
10
10
|
var _lineItems = require("./lineItems");
|
|
11
11
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
12
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
13
|
-
async function addCrossSellItem(sessionId, crossSellItemId, session, currencyId, refresh) {
|
|
14
|
-
|
|
13
|
+
async function addCrossSellItem(sessionId, crossSellItemId, session, currencyId, refresh, sessionData, setSessionData) {
|
|
14
|
+
const {
|
|
15
|
+
data
|
|
16
|
+
} = await _api.default.put(_api.API.CROSS_SELL(sessionId), {
|
|
15
17
|
to: crossSellItemId
|
|
16
18
|
});
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
let finalSession = data;
|
|
20
|
+
if (data.discounts?.length) {
|
|
21
|
+
const recalculated = await (0, _lineItems.recalculatePromotionIfNeeded)(session, sessionId, currencyId);
|
|
22
|
+
if (recalculated) finalSession = recalculated;
|
|
23
|
+
}
|
|
24
|
+
if (sessionData && setSessionData) {
|
|
25
|
+
setSessionData({
|
|
26
|
+
...sessionData,
|
|
27
|
+
checkoutSession: finalSession,
|
|
28
|
+
quotes: void 0
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
await refresh(true);
|
|
32
|
+
}
|
|
19
33
|
}
|
|
20
|
-
async function removeCrossSellItem(sessionId, session, currencyId, refresh) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
await
|
|
34
|
+
async function removeCrossSellItem(sessionId, session, currencyId, refresh, sessionData, setSessionData) {
|
|
35
|
+
const {
|
|
36
|
+
data
|
|
37
|
+
} = await _api.default.delete(_api.API.CROSS_SELL(sessionId));
|
|
38
|
+
let finalSession = data;
|
|
39
|
+
if (data.discounts?.length) {
|
|
40
|
+
const recalculated = await (0, _lineItems.recalculatePromotionIfNeeded)(session, sessionId, currencyId);
|
|
41
|
+
if (recalculated) finalSession = recalculated;
|
|
42
|
+
}
|
|
43
|
+
if (sessionData && setSessionData) {
|
|
44
|
+
setSessionData({
|
|
45
|
+
...sessionData,
|
|
46
|
+
checkoutSession: finalSession,
|
|
47
|
+
quotes: void 0
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
await refresh(true);
|
|
51
|
+
}
|
|
24
52
|
}
|
|
25
53
|
const pendingFetches = /* @__PURE__ */new Map();
|
|
26
54
|
function fetchCrossSellItem(sessionId) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { TCheckoutSessionExpanded, TLineItemExpanded, TPrice } from '@blocklet/payment-types';
|
|
2
|
-
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
2
|
+
import type { SessionData } from '../hooks/useCheckoutSession';
|
|
3
|
+
export declare function recalculatePromotionIfNeeded(session: TCheckoutSessionExpanded | undefined | null, sessionId: string, currencyId: string | null | undefined): Promise<TCheckoutSessionExpanded | null>;
|
|
4
|
+
export declare function adjustQuantity(sessionId: string, itemId: string, qty: number, currencyId: string | null | undefined, session: TCheckoutSessionExpanded | undefined | null, refresh: (force?: boolean) => Promise<void>, sessionData?: SessionData | null, setSessionData?: (data: SessionData) => void): Promise<void>;
|
|
5
|
+
export declare function performUpsell(sessionId: string, fromId: string, toId: string, session: TCheckoutSessionExpanded | undefined | null, currencyId: string | null | undefined, refresh: (force?: boolean) => Promise<void>, sessionData?: SessionData | null, setSessionData?: (data: SessionData) => void): Promise<void>;
|
|
6
|
+
export declare function performDownsell(sessionId: string, priceId: string, session: TCheckoutSessionExpanded | undefined | null, currencyId: string | null | undefined, refresh: (force?: boolean) => Promise<void>, sessionData?: SessionData | null, setSessionData?: (data: SessionData) => void): Promise<void>;
|
|
7
|
+
export declare function changeDonationAmount(sessionId: string, priceId: string, amount: string, session: TCheckoutSessionExpanded | undefined | null, currencyId: string | null | undefined, refresh: (force?: boolean) => Promise<void>, sessionData?: SessionData | null, setSessionData?: (data: SessionData) => void): Promise<void>;
|
|
7
8
|
export declare function getCrossSellItem(items: TLineItemExpanded[]): TPrice | null;
|
|
@@ -14,56 +14,110 @@ var _promotion = require("./promotion");
|
|
|
14
14
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
15
15
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
16
16
|
async function recalculatePromotionIfNeeded(session, sessionId, currencyId) {
|
|
17
|
-
if (!(0, _promotion.hasAppliedDiscounts)(session)) return;
|
|
17
|
+
if (!(0, _promotion.hasAppliedDiscounts)(session)) return null;
|
|
18
18
|
try {
|
|
19
|
-
await (0, _promotion.recalculatePromotion)(sessionId, currencyId);
|
|
20
|
-
} catch {
|
|
19
|
+
return await (0, _promotion.recalculatePromotion)(sessionId, currencyId);
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
21
23
|
}
|
|
22
|
-
async function adjustQuantity(sessionId, itemId, qty, currencyId, session, refresh) {
|
|
23
|
-
|
|
24
|
+
async function adjustQuantity(sessionId, itemId, qty, currencyId, session, refresh, sessionData, setSessionData) {
|
|
25
|
+
const {
|
|
26
|
+
data
|
|
27
|
+
} = await _api.default.put(_api.API.ADJUST_QUANTITY(sessionId), {
|
|
24
28
|
itemId,
|
|
25
29
|
quantity: qty,
|
|
26
30
|
currency_id: currencyId
|
|
27
31
|
});
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
let finalSession = data;
|
|
33
|
+
if (data.discounts?.length || (0, _promotion.hasAppliedDiscounts)(session)) {
|
|
34
|
+
const recalculated = await recalculatePromotionIfNeeded(session, sessionId, currencyId);
|
|
35
|
+
if (recalculated) finalSession = recalculated;
|
|
36
|
+
}
|
|
37
|
+
if (sessionData && setSessionData) {
|
|
38
|
+
setSessionData({
|
|
39
|
+
...sessionData,
|
|
40
|
+
checkoutSession: finalSession,
|
|
41
|
+
quotes: void 0
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
await refresh(true);
|
|
45
|
+
}
|
|
30
46
|
}
|
|
31
|
-
async function performUpsell(sessionId, fromId, toId, session, currencyId, refresh) {
|
|
47
|
+
async function performUpsell(sessionId, fromId, toId, session, currencyId, refresh, sessionData, setSessionData) {
|
|
32
48
|
if ((session?.line_items?.length || 0) > 1) {
|
|
33
49
|
try {
|
|
34
50
|
await _api.default.delete(_api.API.CROSS_SELL(sessionId));
|
|
35
51
|
} catch {}
|
|
36
52
|
}
|
|
37
|
-
|
|
53
|
+
const {
|
|
54
|
+
data
|
|
55
|
+
} = await _api.default.put(_api.API.UPSELL(sessionId), {
|
|
38
56
|
from: fromId,
|
|
39
57
|
to: toId
|
|
40
58
|
});
|
|
41
|
-
|
|
42
|
-
|
|
59
|
+
let finalSession = data;
|
|
60
|
+
if (data.discounts?.length || (0, _promotion.hasAppliedDiscounts)(session)) {
|
|
61
|
+
const recalculated = await recalculatePromotionIfNeeded(session, sessionId, currencyId);
|
|
62
|
+
if (recalculated) finalSession = recalculated;
|
|
63
|
+
}
|
|
64
|
+
if (sessionData && setSessionData) {
|
|
65
|
+
setSessionData({
|
|
66
|
+
...sessionData,
|
|
67
|
+
checkoutSession: finalSession,
|
|
68
|
+
quotes: void 0
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
await refresh(true);
|
|
72
|
+
}
|
|
43
73
|
}
|
|
44
|
-
async function performDownsell(sessionId, priceId, session, currencyId, refresh) {
|
|
74
|
+
async function performDownsell(sessionId, priceId, session, currencyId, refresh, sessionData, setSessionData) {
|
|
45
75
|
if ((session?.line_items?.length || 0) > 1) {
|
|
46
76
|
try {
|
|
47
77
|
await _api.default.delete(_api.API.CROSS_SELL(sessionId));
|
|
48
78
|
} catch {}
|
|
49
79
|
}
|
|
50
|
-
|
|
80
|
+
const {
|
|
81
|
+
data
|
|
82
|
+
} = await _api.default.put(_api.API.DOWNSELL(sessionId), {
|
|
51
83
|
from: priceId
|
|
52
84
|
});
|
|
53
|
-
|
|
54
|
-
|
|
85
|
+
let finalSession = data;
|
|
86
|
+
if (data.discounts?.length || (0, _promotion.hasAppliedDiscounts)(session)) {
|
|
87
|
+
const recalculated = await recalculatePromotionIfNeeded(session, sessionId, currencyId);
|
|
88
|
+
if (recalculated) finalSession = recalculated;
|
|
89
|
+
}
|
|
90
|
+
if (sessionData && setSessionData) {
|
|
91
|
+
setSessionData({
|
|
92
|
+
...sessionData,
|
|
93
|
+
checkoutSession: finalSession,
|
|
94
|
+
quotes: void 0
|
|
95
|
+
});
|
|
96
|
+
} else {
|
|
97
|
+
await refresh(true);
|
|
98
|
+
}
|
|
55
99
|
}
|
|
56
|
-
async function changeDonationAmount(sessionId, priceId, amount, session, currencyId, refresh) {
|
|
100
|
+
async function changeDonationAmount(sessionId, priceId, amount, session, currencyId, refresh, sessionData, setSessionData) {
|
|
57
101
|
const {
|
|
58
102
|
data
|
|
59
103
|
} = await _api.default.put(_api.API.CHANGE_AMOUNT(sessionId), {
|
|
60
104
|
priceId,
|
|
61
105
|
amount
|
|
62
106
|
});
|
|
107
|
+
let finalSession = data;
|
|
63
108
|
if (data?.discounts?.length) {
|
|
64
|
-
await recalculatePromotionIfNeeded(session, sessionId, currencyId);
|
|
109
|
+
const recalculated = await recalculatePromotionIfNeeded(session, sessionId, currencyId);
|
|
110
|
+
if (recalculated) finalSession = recalculated;
|
|
111
|
+
}
|
|
112
|
+
if (sessionData && setSessionData) {
|
|
113
|
+
setSessionData({
|
|
114
|
+
...sessionData,
|
|
115
|
+
checkoutSession: finalSession,
|
|
116
|
+
quotes: void 0
|
|
117
|
+
});
|
|
118
|
+
} else {
|
|
119
|
+
await refresh(true);
|
|
65
120
|
}
|
|
66
|
-
await refresh(true);
|
|
67
121
|
}
|
|
68
122
|
function getCrossSellItem(items) {
|
|
69
123
|
for (const item of items) {
|
|
@@ -5,6 +5,6 @@ export declare function applyPromotionCode(sessionId: string, code: string, curr
|
|
|
5
5
|
error?: string;
|
|
6
6
|
}>;
|
|
7
7
|
export declare function removePromotionCode(sessionId: string): Promise<void>;
|
|
8
|
-
export declare function recalculatePromotion(sessionId: string, currencyId: string | null | undefined): Promise<
|
|
8
|
+
export declare function recalculatePromotion(sessionId: string, currencyId: string | null | undefined): Promise<TCheckoutSessionExpanded>;
|
|
9
9
|
export declare function isPromotionActive(session: TCheckoutSessionExpanded | undefined | null): boolean;
|
|
10
10
|
export declare function hasAppliedDiscounts(session: TCheckoutSessionExpanded | undefined | null): boolean;
|
|
@@ -49,9 +49,12 @@ async function removePromotionCode(sessionId) {
|
|
|
49
49
|
await _api.default.delete(_api.API.REMOVE_PROMOTION(sessionId));
|
|
50
50
|
}
|
|
51
51
|
async function recalculatePromotion(sessionId, currencyId) {
|
|
52
|
-
|
|
52
|
+
const {
|
|
53
|
+
data
|
|
54
|
+
} = await _api.default.post(_api.API.RECALCULATE_PROMOTION_SESSION(sessionId), {
|
|
53
55
|
currency_id: currencyId
|
|
54
56
|
});
|
|
57
|
+
return data;
|
|
55
58
|
}
|
|
56
59
|
function isPromotionActive(session) {
|
|
57
60
|
return session?.allow_promotion_codes !== false;
|
|
@@ -16,23 +16,26 @@ function useBillingInterval() {
|
|
|
16
16
|
items,
|
|
17
17
|
session,
|
|
18
18
|
effectiveSessionId,
|
|
19
|
-
refresh
|
|
19
|
+
refresh,
|
|
20
|
+
sessionData,
|
|
21
|
+
setSessionData
|
|
20
22
|
} = (0, _SessionContext.useSessionContext)();
|
|
21
23
|
const {
|
|
22
24
|
currency
|
|
23
25
|
} = (0, _PaymentMethodContext.usePaymentMethodContext)();
|
|
24
26
|
const currencyId = currency?.id || null;
|
|
25
27
|
const [switching, setSwitching] = (0, _react.useState)(false);
|
|
28
|
+
const [pendingInterval, setPendingInterval] = (0, _react.useState)(null);
|
|
26
29
|
const upsell = (0, _ahooks.useMemoizedFn)(async (fromId, toId) => {
|
|
27
30
|
try {
|
|
28
|
-
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh);
|
|
31
|
+
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh, sessionData, setSessionData);
|
|
29
32
|
} catch (err) {
|
|
30
33
|
console.error("Failed to upsell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
31
34
|
}
|
|
32
35
|
});
|
|
33
36
|
const downsell = (0, _ahooks.useMemoizedFn)(async priceId => {
|
|
34
37
|
try {
|
|
35
|
-
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh);
|
|
38
|
+
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh, sessionData, setSessionData);
|
|
36
39
|
} catch (err) {
|
|
37
40
|
console.error("Failed to downsell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
38
41
|
}
|
|
@@ -41,12 +44,13 @@ function useBillingInterval() {
|
|
|
41
44
|
const parsed = (0, _billingInterval.parseBillingInterval)(items);
|
|
42
45
|
if (!parsed) return null;
|
|
43
46
|
return {
|
|
44
|
-
current: parsed.current,
|
|
47
|
+
current: pendingInterval || parsed.current,
|
|
45
48
|
available: parsed.available,
|
|
46
49
|
switching,
|
|
47
50
|
switch: async interval => {
|
|
48
51
|
const target = parsed.available.find(a => a.interval === interval);
|
|
49
52
|
if (!target || switching) return;
|
|
53
|
+
setPendingInterval(interval);
|
|
50
54
|
setSwitching(true);
|
|
51
55
|
try {
|
|
52
56
|
if (!parsed.firstItem.upsell_price_id && target.priceId) {
|
|
@@ -56,8 +60,9 @@ function useBillingInterval() {
|
|
|
56
60
|
}
|
|
57
61
|
} finally {
|
|
58
62
|
setSwitching(false);
|
|
63
|
+
setPendingInterval(null);
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
};
|
|
62
|
-
}, [items, effectiveSessionId, switching]);
|
|
67
|
+
}, [items, effectiveSessionId, switching, pendingInterval]);
|
|
63
68
|
}
|
|
@@ -21,6 +21,7 @@ function useCheckout(sessionId) {
|
|
|
21
21
|
error,
|
|
22
22
|
errorCode,
|
|
23
23
|
refresh,
|
|
24
|
+
setSessionData,
|
|
24
25
|
sessionData,
|
|
25
26
|
resolvedSessionId,
|
|
26
27
|
vendorCount,
|
|
@@ -30,12 +31,12 @@ function useCheckout(sessionId) {
|
|
|
30
31
|
} = (0, _useCheckoutSession.useCheckoutSession)(sessionId);
|
|
31
32
|
const session = sessionData?.checkoutSession;
|
|
32
33
|
const effectiveSessionId = resolvedSessionId || sessionId;
|
|
33
|
-
const paymentMethodHook = (0, _usePaymentMethod.usePaymentMethod)(sessionData, effectiveSessionId, refresh);
|
|
34
|
+
const paymentMethodHook = (0, _usePaymentMethod.usePaymentMethod)(sessionData, effectiveSessionId, refresh, setSessionData);
|
|
34
35
|
const pricingHook = (0, _usePricing.usePricing)(sessionData, effectiveSessionId, paymentMethodHook.currency, paymentMethodHook.isStripe, refresh, paymentMethodHook.current?.type || null);
|
|
35
36
|
const formHook = (0, _useCustomerForm.useCustomerForm)(sessionData, paymentMethodHook.currency?.id || null, paymentMethodHook.current?.id || null);
|
|
36
37
|
const isDonation = session?.submit_type === "donate";
|
|
37
38
|
const submitHook = (0, _useSubmit.useSubmit)(sessionData, effectiveSessionId, paymentMethodHook.currency?.id || null, paymentMethodHook.isStripe, paymentMethodHook.isCredit, isDonation, formHook.values, formHook.validate, refresh);
|
|
38
|
-
const items = session?.line_items || [];
|
|
39
|
+
const items = (0, _react.useMemo)(() => session?.line_items || [], [session?.line_items]);
|
|
39
40
|
const currencyId = paymentMethodHook.currency?.id || null;
|
|
40
41
|
const prevCurrencyRef = (0, _react.useRef)(null);
|
|
41
42
|
(0, _react.useEffect)(() => {
|
|
@@ -43,26 +44,34 @@ function useCheckout(sessionId) {
|
|
|
43
44
|
if (!currId || !session) return;
|
|
44
45
|
if (prevCurrencyRef.current === null || currId !== prevCurrencyRef.current) {
|
|
45
46
|
prevCurrencyRef.current = currId;
|
|
46
|
-
(0, _lineItems.recalculatePromotionIfNeeded)(session, effectiveSessionId, currId).then(
|
|
47
|
+
(0, _lineItems.recalculatePromotionIfNeeded)(session, effectiveSessionId, currId).then(recalculated => {
|
|
48
|
+
if (recalculated && sessionData) {
|
|
49
|
+
setSessionData({
|
|
50
|
+
...sessionData,
|
|
51
|
+
checkoutSession: recalculated,
|
|
52
|
+
quotes: void 0
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
47
56
|
}
|
|
48
57
|
}, [paymentMethodHook.currency?.id, session?.id]);
|
|
49
58
|
const updateQuantity = (0, _ahooks.useMemoizedFn)(async (itemId, qty) => {
|
|
50
59
|
try {
|
|
51
|
-
await (0, _lineItems.adjustQuantity)(effectiveSessionId, itemId, qty, currencyId, session, refresh);
|
|
60
|
+
await (0, _lineItems.adjustQuantity)(effectiveSessionId, itemId, qty, currencyId, session, refresh, sessionData, setSessionData);
|
|
52
61
|
} catch (err) {
|
|
53
62
|
console.error("Failed to update quantity:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
54
63
|
}
|
|
55
64
|
});
|
|
56
65
|
const upsell = (0, _ahooks.useMemoizedFn)(async (fromId, toId) => {
|
|
57
66
|
try {
|
|
58
|
-
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh);
|
|
67
|
+
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh, sessionData, setSessionData);
|
|
59
68
|
} catch (err) {
|
|
60
69
|
console.error("Failed to upsell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
61
70
|
}
|
|
62
71
|
});
|
|
63
72
|
const downsell = (0, _ahooks.useMemoizedFn)(async priceId => {
|
|
64
73
|
try {
|
|
65
|
-
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh);
|
|
74
|
+
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh, sessionData, setSessionData);
|
|
66
75
|
} catch (err) {
|
|
67
76
|
console.error("Failed to downsell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
68
77
|
}
|
|
@@ -87,14 +96,14 @@ function useCheckout(sessionId) {
|
|
|
87
96
|
const addCrossSell = (0, _ahooks.useMemoizedFn)(async () => {
|
|
88
97
|
if (!crossSellItem) return;
|
|
89
98
|
try {
|
|
90
|
-
await (0, _crossSell.addCrossSellItem)(effectiveSessionId, crossSellItem.id, session, currencyId, refresh);
|
|
99
|
+
await (0, _crossSell.addCrossSellItem)(effectiveSessionId, crossSellItem.id, session, currencyId, refresh, sessionData, setSessionData);
|
|
91
100
|
} catch (err) {
|
|
92
101
|
console.error("Failed to add cross-sell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
93
102
|
}
|
|
94
103
|
});
|
|
95
104
|
const removeCrossSell = (0, _ahooks.useMemoizedFn)(async () => {
|
|
96
105
|
try {
|
|
97
|
-
await (0, _crossSell.removeCrossSellItem)(effectiveSessionId, session, currencyId, refresh);
|
|
106
|
+
await (0, _crossSell.removeCrossSellItem)(effectiveSessionId, session, currencyId, refresh, sessionData, setSessionData);
|
|
98
107
|
} catch (err) {
|
|
99
108
|
console.error("Failed to remove cross-sell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
100
109
|
}
|
|
@@ -119,7 +128,7 @@ function useCheckout(sessionId) {
|
|
|
119
128
|
const setDonationAmount = (0, _ahooks.useMemoizedFn)(async (priceId, amount) => {
|
|
120
129
|
if (!isDonation) return;
|
|
121
130
|
try {
|
|
122
|
-
await (0, _lineItems.changeDonationAmount)(effectiveSessionId, priceId, amount, session, currencyId, refresh);
|
|
131
|
+
await (0, _lineItems.changeDonationAmount)(effectiveSessionId, priceId, amount, session, currencyId, refresh, sessionData, setSessionData);
|
|
123
132
|
} catch (err) {
|
|
124
133
|
console.error("Failed to change amount:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
125
134
|
}
|
|
@@ -16,7 +16,9 @@ function useCrossSell() {
|
|
|
16
16
|
items,
|
|
17
17
|
session,
|
|
18
18
|
effectiveSessionId,
|
|
19
|
-
refresh
|
|
19
|
+
refresh,
|
|
20
|
+
sessionData,
|
|
21
|
+
setSessionData
|
|
20
22
|
} = (0, _SessionContext.useSessionContext)();
|
|
21
23
|
const {
|
|
22
24
|
currency
|
|
@@ -53,7 +55,7 @@ function useCrossSell() {
|
|
|
53
55
|
const crossSellItemPrice = (0, _lineItems.getCrossSellItem)(items);
|
|
54
56
|
if (!crossSellItemPrice) return;
|
|
55
57
|
try {
|
|
56
|
-
await (0, _crossSell.addCrossSellItem)(effectiveSessionId, crossSellItemPrice.id, session, currencyId, refresh);
|
|
58
|
+
await (0, _crossSell.addCrossSellItem)(effectiveSessionId, crossSellItemPrice.id, session, currencyId, refresh, sessionData, setSessionData);
|
|
57
59
|
} catch (err) {
|
|
58
60
|
console.error("Failed to add cross-sell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
59
61
|
}
|
|
@@ -61,7 +63,7 @@ function useCrossSell() {
|
|
|
61
63
|
const remove = (0, _ahooks.useMemoizedFn)(async () => {
|
|
62
64
|
if (session?.status === "complete") return;
|
|
63
65
|
try {
|
|
64
|
-
await (0, _crossSell.removeCrossSellItem)(effectiveSessionId, session, currencyId, refresh);
|
|
66
|
+
await (0, _crossSell.removeCrossSellItem)(effectiveSessionId, session, currencyId, refresh, sessionData, setSessionData);
|
|
65
67
|
} catch (err) {
|
|
66
68
|
console.error("Failed to remove cross-sell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
67
69
|
}
|
|
@@ -17,7 +17,9 @@ function useLineItems() {
|
|
|
17
17
|
session,
|
|
18
18
|
effectiveSessionId,
|
|
19
19
|
isDonation,
|
|
20
|
-
refresh
|
|
20
|
+
refresh,
|
|
21
|
+
sessionData,
|
|
22
|
+
setSessionData
|
|
21
23
|
} = (0, _SessionContext.useSessionContext)();
|
|
22
24
|
const {
|
|
23
25
|
currency
|
|
@@ -34,7 +36,7 @@ function useLineItems() {
|
|
|
34
36
|
const qty = Math.max(1, parseInt(qtyStr, 10));
|
|
35
37
|
if (Number.isFinite(qty) && qty !== item.quantity) {
|
|
36
38
|
defaultQtyApplied.current = true;
|
|
37
|
-
(0, _lineItems.adjustQuantity)(effectiveSessionId, item.price_id, qty, currencyId, session, refresh);
|
|
39
|
+
(0, _lineItems.adjustQuantity)(effectiveSessionId, item.price_id, qty, currencyId, session, refresh, sessionData, setSessionData);
|
|
38
40
|
break;
|
|
39
41
|
}
|
|
40
42
|
}
|
|
@@ -44,18 +46,18 @@ function useLineItems() {
|
|
|
44
46
|
const updateQuantity = (0, _ahooks.useMemoizedFn)(async (itemId, qty) => {
|
|
45
47
|
if (session?.status === "complete") return;
|
|
46
48
|
try {
|
|
47
|
-
await (0, _lineItems.adjustQuantity)(effectiveSessionId, itemId, qty, currencyId, session, refresh);
|
|
49
|
+
await (0, _lineItems.adjustQuantity)(effectiveSessionId, itemId, qty, currencyId, session, refresh, sessionData, setSessionData);
|
|
48
50
|
} catch (err) {
|
|
49
51
|
console.error("Failed to update quantity:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
50
52
|
}
|
|
51
53
|
});
|
|
52
54
|
const upsell = (0, _ahooks.useMemoizedFn)(async (fromId, toId) => {
|
|
53
55
|
if (session?.status === "complete") return;
|
|
54
|
-
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh);
|
|
56
|
+
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh, sessionData, setSessionData);
|
|
55
57
|
});
|
|
56
58
|
const downsell = (0, _ahooks.useMemoizedFn)(async priceId => {
|
|
57
59
|
if (session?.status === "complete") return;
|
|
58
|
-
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh);
|
|
60
|
+
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh, sessionData, setSessionData);
|
|
59
61
|
});
|
|
60
62
|
const embeddedCrossSellItem = (0, _react.useMemo)(() => (0, _lineItems.getCrossSellItem)(items), [items]);
|
|
61
63
|
const [fetchedCrossSellItem, setFetchedCrossSellItem] = (0, _react.useState)(null);
|
|
@@ -87,7 +89,7 @@ function useLineItems() {
|
|
|
87
89
|
if (session?.status === "complete") return;
|
|
88
90
|
if (!crossSellItem) return;
|
|
89
91
|
try {
|
|
90
|
-
await (0, _crossSell.addCrossSellItem)(effectiveSessionId, crossSellItem.id, session, currencyId, refresh);
|
|
92
|
+
await (0, _crossSell.addCrossSellItem)(effectiveSessionId, crossSellItem.id, session, currencyId, refresh, sessionData, setSessionData);
|
|
91
93
|
} catch (err) {
|
|
92
94
|
console.error("Failed to add cross-sell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
93
95
|
}
|
|
@@ -95,7 +97,7 @@ function useLineItems() {
|
|
|
95
97
|
const removeCrossSell = (0, _ahooks.useMemoizedFn)(async () => {
|
|
96
98
|
if (session?.status === "complete") return;
|
|
97
99
|
try {
|
|
98
|
-
await (0, _crossSell.removeCrossSellItem)(effectiveSessionId, session, currencyId, refresh);
|
|
100
|
+
await (0, _crossSell.removeCrossSellItem)(effectiveSessionId, session, currencyId, refresh, sessionData, setSessionData);
|
|
99
101
|
} catch (err) {
|
|
100
102
|
console.error("Failed to remove cross-sell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
101
103
|
}
|
|
@@ -104,7 +106,7 @@ function useLineItems() {
|
|
|
104
106
|
if (session?.status === "complete") return;
|
|
105
107
|
if (!isDonation) return;
|
|
106
108
|
try {
|
|
107
|
-
await (0, _lineItems.changeDonationAmount)(effectiveSessionId, priceId, amount, session, currencyId, refresh);
|
|
109
|
+
await (0, _lineItems.changeDonationAmount)(effectiveSessionId, priceId, amount, session, currencyId, refresh, sessionData, setSessionData);
|
|
108
110
|
} catch (err) {
|
|
109
111
|
console.error("Failed to change amount:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
110
112
|
}
|
|
@@ -23,4 +23,4 @@ export interface UsePaymentMethodReturn {
|
|
|
23
23
|
status: 'idle' | 'ready' | 'processing' | 'succeeded' | 'failed';
|
|
24
24
|
} | null;
|
|
25
25
|
}
|
|
26
|
-
export declare function usePaymentMethod(sessionData: SessionData | null, sessionId: string, refreshSession: (force?: boolean) => Promise<void
|
|
26
|
+
export declare function usePaymentMethod(sessionData: SessionData | null, sessionId: string, refreshSession: (force?: boolean) => Promise<void>, setSessionData?: (data: SessionData) => void): UsePaymentMethodReturn;
|
|
@@ -9,10 +9,11 @@ var _ahooks = require("ahooks");
|
|
|
9
9
|
var _checkoutAugmented = require("../../types/checkout-augmented");
|
|
10
10
|
var _api = _interopRequireWildcard(require("../../shared/api"));
|
|
11
11
|
var _paymentMethod = require("../core/paymentMethod");
|
|
12
|
+
var _lineItems = require("../core/lineItems");
|
|
12
13
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
13
14
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
14
|
-
function usePaymentMethod(sessionData, sessionId, refreshSession) {
|
|
15
|
-
const methods = sessionData?.paymentMethods || [];
|
|
15
|
+
function usePaymentMethod(sessionData, sessionId, refreshSession, setSessionData) {
|
|
16
|
+
const methods = (0, _react.useMemo)(() => sessionData?.paymentMethods || [], [sessionData?.paymentMethods]);
|
|
16
17
|
const session = sessionData?.checkoutSession;
|
|
17
18
|
const [currencyId, setCurrencyId] = (0, _react.useState)(() => (0, _paymentMethod.getInitialCurrencyId)(session, methods));
|
|
18
19
|
const [switching, setSwitching] = (0, _react.useState)(false);
|
|
@@ -47,7 +48,9 @@ function usePaymentMethod(sessionData, sessionId, refreshSession) {
|
|
|
47
48
|
if (!method || !sessionId) return;
|
|
48
49
|
setSwitching(true);
|
|
49
50
|
try {
|
|
50
|
-
|
|
51
|
+
const {
|
|
52
|
+
data
|
|
53
|
+
} = await _api.default.put(_api.API.SWITCH_CURRENCY(sessionId), {
|
|
51
54
|
currency_id: newCurrencyId,
|
|
52
55
|
payment_method_id: method.id
|
|
53
56
|
});
|
|
@@ -55,7 +58,20 @@ function usePaymentMethod(sessionData, sessionId, refreshSession) {
|
|
|
55
58
|
try {
|
|
56
59
|
localStorage.setItem((0, _paymentMethod.getCurrencyStorageKey)(session?.user?.did), newCurrencyId);
|
|
57
60
|
} catch {}
|
|
58
|
-
|
|
61
|
+
let finalSession = data;
|
|
62
|
+
if (data.discounts?.length) {
|
|
63
|
+
const recalculated = await (0, _lineItems.recalculatePromotionIfNeeded)(session, sessionId, newCurrencyId);
|
|
64
|
+
if (recalculated) finalSession = recalculated;
|
|
65
|
+
}
|
|
66
|
+
if (sessionData && setSessionData) {
|
|
67
|
+
setSessionData({
|
|
68
|
+
...sessionData,
|
|
69
|
+
checkoutSession: finalSession,
|
|
70
|
+
quotes: void 0
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
await refreshSession(true);
|
|
74
|
+
}
|
|
59
75
|
} catch (err) {
|
|
60
76
|
console.error("Failed to switch currency:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
61
77
|
if (session?.currency_id) {
|
|
@@ -13,7 +13,9 @@ function useUpsell() {
|
|
|
13
13
|
const {
|
|
14
14
|
session,
|
|
15
15
|
effectiveSessionId,
|
|
16
|
-
refresh
|
|
16
|
+
refresh,
|
|
17
|
+
sessionData,
|
|
18
|
+
setSessionData
|
|
17
19
|
} = (0, _SessionContext.useSessionContext)();
|
|
18
20
|
const {
|
|
19
21
|
currency
|
|
@@ -21,14 +23,14 @@ function useUpsell() {
|
|
|
21
23
|
const currencyId = currency?.id || null;
|
|
22
24
|
const upsell = (0, _ahooks.useMemoizedFn)(async (fromId, toId) => {
|
|
23
25
|
try {
|
|
24
|
-
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh);
|
|
26
|
+
await (0, _lineItems.performUpsell)(effectiveSessionId, fromId, toId, session, currencyId, refresh, sessionData, setSessionData);
|
|
25
27
|
} catch (err) {
|
|
26
28
|
console.error("Failed to upsell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
27
29
|
}
|
|
28
30
|
});
|
|
29
31
|
const downsell = (0, _ahooks.useMemoizedFn)(async priceId => {
|
|
30
32
|
try {
|
|
31
|
-
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh);
|
|
33
|
+
await (0, _lineItems.performDownsell)(effectiveSessionId, priceId, session, currencyId, refresh, sessionData, setSessionData);
|
|
32
34
|
} catch (err) {
|
|
33
35
|
console.error("Failed to downsell:", (0, _checkoutAugmented.getErrorMessage)(err));
|
|
34
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react-headless",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.2",
|
|
4
4
|
"description": "Headless React hooks for payment-kit checkout",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@arcblock/ws": "^1.28.5",
|
|
37
37
|
"@blocklet/js-sdk": "workspace:*",
|
|
38
|
-
"@blocklet/payment-types": "1.26.
|
|
38
|
+
"@blocklet/payment-types": "1.26.2",
|
|
39
39
|
"@ocap/util": "^1.28.5",
|
|
40
40
|
"ahooks": "^3.8.5",
|
|
41
41
|
"google-libphonenumber": "^3.2.42",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "71242a68d27d56666487176425153dc08071960f"
|
|
64
64
|
}
|
|
@@ -38,12 +38,13 @@ export function CheckoutProvider({ sessionId, children }: CheckoutProviderProps)
|
|
|
38
38
|
|
|
39
39
|
const session = sessionData?.checkoutSession;
|
|
40
40
|
const effectiveSessionId = resolvedSessionId || sessionId;
|
|
41
|
-
const items = (session?.line_items || []) as TLineItemExpanded[];
|
|
41
|
+
const items = useMemo(() => (session?.line_items || []) as TLineItemExpanded[], [session?.line_items]);
|
|
42
42
|
const isDonation = session?.submit_type === 'donate';
|
|
43
43
|
|
|
44
44
|
const sessionValue = useMemo<SessionContextValue>(
|
|
45
45
|
() => ({
|
|
46
46
|
sessionData,
|
|
47
|
+
setSessionData,
|
|
47
48
|
sessionId,
|
|
48
49
|
effectiveSessionId,
|
|
49
50
|
isLoading,
|
|
@@ -60,6 +61,7 @@ export function CheckoutProvider({ sessionId, children }: CheckoutProviderProps)
|
|
|
60
61
|
}),
|
|
61
62
|
[
|
|
62
63
|
sessionData,
|
|
64
|
+
setSessionData,
|
|
63
65
|
sessionId,
|
|
64
66
|
effectiveSessionId,
|
|
65
67
|
isLoading,
|
|
@@ -77,16 +79,20 @@ export function CheckoutProvider({ sessionId, children }: CheckoutProviderProps)
|
|
|
77
79
|
);
|
|
78
80
|
|
|
79
81
|
// 2. Payment method layer
|
|
80
|
-
const paymentMethodHook = usePaymentMethodHook(sessionData, effectiveSessionId, refresh);
|
|
82
|
+
const paymentMethodHook = usePaymentMethodHook(sessionData, effectiveSessionId, refresh, setSessionData);
|
|
81
83
|
|
|
82
|
-
// Recalculate promotion when currency changes
|
|
84
|
+
// Recalculate promotion when currency changes — use response directly (no extra GET)
|
|
83
85
|
const prevCurrencyRef = useRef<string | null>(null);
|
|
84
86
|
useEffect(() => {
|
|
85
87
|
const currId = paymentMethodHook.currency?.id || null;
|
|
86
88
|
if (!currId || !session || session.status === 'complete') return;
|
|
87
89
|
if (prevCurrencyRef.current === null || currId !== prevCurrencyRef.current) {
|
|
88
90
|
prevCurrencyRef.current = currId;
|
|
89
|
-
recalculatePromotionIfNeeded(session, effectiveSessionId, currId).then(() =>
|
|
91
|
+
recalculatePromotionIfNeeded(session, effectiveSessionId, currId).then((recalculated) => {
|
|
92
|
+
if (recalculated && sessionData) {
|
|
93
|
+
setSessionData({ ...sessionData, checkoutSession: recalculated, quotes: undefined });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
90
96
|
}
|
|
91
97
|
}, [paymentMethodHook.currency?.id, session?.id]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
92
98
|
|
|
@@ -219,7 +225,14 @@ export function CheckoutProvider({ sessionId, children }: CheckoutProviderProps)
|
|
|
219
225
|
if (intervalRef.current) clearInterval(intervalRef.current);
|
|
220
226
|
document.removeEventListener('visibilitychange', handleVisibility);
|
|
221
227
|
};
|
|
222
|
-
|
|
228
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
229
|
+
}, [
|
|
230
|
+
hasDynamicPricing,
|
|
231
|
+
paymentMethodHook.isStripe,
|
|
232
|
+
effectiveSessionId,
|
|
233
|
+
paymentMethodHook.currency?.id,
|
|
234
|
+
session?.status,
|
|
235
|
+
]);
|
|
223
236
|
|
|
224
237
|
const exchangeRateValue = useMemo<ExchangeRateContextValue>(
|
|
225
238
|
() => ({
|