@blocklet/payment-react 1.25.10 → 1.26.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.
Files changed (160) hide show
  1. package/es/checkout-v2/checkout-v2.d.ts +2 -0
  2. package/es/checkout-v2/checkout-v2.js +121 -0
  3. package/es/checkout-v2/components/dialogs/checkout-dialogs.d.ts +1 -0
  4. package/es/checkout-v2/components/dialogs/checkout-dialogs.js +106 -0
  5. package/es/checkout-v2/components/left/billing-toggle.d.ts +6 -0
  6. package/es/checkout-v2/components/left/billing-toggle.js +118 -0
  7. package/es/checkout-v2/components/left/cross-sell-card.d.ts +10 -0
  8. package/es/checkout-v2/components/left/cross-sell-card.js +167 -0
  9. package/es/checkout-v2/components/left/product-item-card.d.ts +26 -0
  10. package/es/checkout-v2/components/left/product-item-card.js +571 -0
  11. package/es/checkout-v2/components/left/promotion-input.d.ts +19 -0
  12. package/es/checkout-v2/components/left/promotion-input.js +178 -0
  13. package/es/checkout-v2/components/left/staking-breakdown.d.ts +9 -0
  14. package/es/checkout-v2/components/left/staking-breakdown.js +48 -0
  15. package/es/checkout-v2/components/left/trial-info.d.ts +13 -0
  16. package/es/checkout-v2/components/left/trial-info.js +48 -0
  17. package/es/checkout-v2/components/right/currency-grid.d.ts +8 -0
  18. package/es/checkout-v2/components/right/currency-grid.js +48 -0
  19. package/es/checkout-v2/components/right/customer-info-card.d.ts +17 -0
  20. package/es/checkout-v2/components/right/customer-info-card.js +156 -0
  21. package/es/checkout-v2/components/right/status-feedback.d.ts +7 -0
  22. package/es/checkout-v2/components/right/status-feedback.js +17 -0
  23. package/es/checkout-v2/components/right/submit-button.d.ts +10 -0
  24. package/es/checkout-v2/components/right/submit-button.js +29 -0
  25. package/es/checkout-v2/components/right/subscription-disclaimer.d.ts +11 -0
  26. package/es/checkout-v2/components/right/subscription-disclaimer.js +8 -0
  27. package/es/checkout-v2/components/shared/exchange-rate-footer.d.ts +23 -0
  28. package/es/checkout-v2/components/shared/exchange-rate-footer.js +182 -0
  29. package/es/checkout-v2/components/shared/scenario-badge.d.ts +6 -0
  30. package/es/checkout-v2/components/shared/scenario-badge.js +47 -0
  31. package/es/checkout-v2/components/shared/total-display.d.ts +7 -0
  32. package/es/checkout-v2/components/shared/total-display.js +84 -0
  33. package/es/checkout-v2/index.d.ts +2 -0
  34. package/es/checkout-v2/index.js +1 -0
  35. package/es/checkout-v2/layouts/checkout-layout.d.ts +7 -0
  36. package/es/checkout-v2/layouts/checkout-layout.js +226 -0
  37. package/es/checkout-v2/panels/left/composite-panel.d.ts +1 -0
  38. package/es/checkout-v2/panels/left/composite-panel.js +423 -0
  39. package/es/checkout-v2/panels/left/credit-topup-panel.d.ts +1 -0
  40. package/es/checkout-v2/panels/left/credit-topup-panel.js +615 -0
  41. package/es/checkout-v2/panels/left/scenario-router.d.ts +1 -0
  42. package/es/checkout-v2/panels/left/scenario-router.js +19 -0
  43. package/es/checkout-v2/panels/right/payment-panel.d.ts +1 -0
  44. package/es/checkout-v2/panels/right/payment-panel.js +644 -0
  45. package/es/checkout-v2/types.d.ts +15 -0
  46. package/es/checkout-v2/types.js +0 -0
  47. package/es/checkout-v2/utils/format.d.ts +59 -0
  48. package/es/checkout-v2/utils/format.js +125 -0
  49. package/es/checkout-v2/utils/scenario-detector.d.ts +3 -0
  50. package/es/checkout-v2/utils/scenario-detector.js +17 -0
  51. package/es/checkout-v2/views/error-view.d.ts +7 -0
  52. package/es/checkout-v2/views/error-view.js +269 -0
  53. package/es/checkout-v2/views/loading-view.d.ts +5 -0
  54. package/es/checkout-v2/views/loading-view.js +158 -0
  55. package/es/checkout-v2/views/success-view.d.ts +29 -0
  56. package/es/checkout-v2/views/success-view.js +614 -0
  57. package/es/components/phone-field.d.ts +14 -0
  58. package/es/components/phone-field.js +96 -0
  59. package/es/index.d.ts +3 -1
  60. package/es/index.js +3 -1
  61. package/es/locales/en.js +45 -6
  62. package/es/locales/zh.js +45 -6
  63. package/es/payment/form/index.js +10 -1
  64. package/lib/checkout-v2/checkout-v2.d.ts +2 -0
  65. package/lib/checkout-v2/checkout-v2.js +151 -0
  66. package/lib/checkout-v2/components/dialogs/checkout-dialogs.d.ts +1 -0
  67. package/lib/checkout-v2/components/dialogs/checkout-dialogs.js +131 -0
  68. package/lib/checkout-v2/components/left/billing-toggle.d.ts +6 -0
  69. package/lib/checkout-v2/components/left/billing-toggle.js +126 -0
  70. package/lib/checkout-v2/components/left/cross-sell-card.d.ts +10 -0
  71. package/lib/checkout-v2/components/left/cross-sell-card.js +257 -0
  72. package/lib/checkout-v2/components/left/product-item-card.d.ts +26 -0
  73. package/lib/checkout-v2/components/left/product-item-card.js +738 -0
  74. package/lib/checkout-v2/components/left/promotion-input.d.ts +19 -0
  75. package/lib/checkout-v2/components/left/promotion-input.js +220 -0
  76. package/lib/checkout-v2/components/left/staking-breakdown.d.ts +9 -0
  77. package/lib/checkout-v2/components/left/staking-breakdown.js +96 -0
  78. package/lib/checkout-v2/components/left/trial-info.d.ts +13 -0
  79. package/lib/checkout-v2/components/left/trial-info.js +82 -0
  80. package/lib/checkout-v2/components/right/currency-grid.d.ts +8 -0
  81. package/lib/checkout-v2/components/right/currency-grid.js +96 -0
  82. package/lib/checkout-v2/components/right/customer-info-card.d.ts +17 -0
  83. package/lib/checkout-v2/components/right/customer-info-card.js +246 -0
  84. package/lib/checkout-v2/components/right/status-feedback.d.ts +7 -0
  85. package/lib/checkout-v2/components/right/status-feedback.js +30 -0
  86. package/lib/checkout-v2/components/right/submit-button.d.ts +10 -0
  87. package/lib/checkout-v2/components/right/submit-button.js +35 -0
  88. package/lib/checkout-v2/components/right/subscription-disclaimer.d.ts +11 -0
  89. package/lib/checkout-v2/components/right/subscription-disclaimer.js +33 -0
  90. package/lib/checkout-v2/components/shared/exchange-rate-footer.d.ts +23 -0
  91. package/lib/checkout-v2/components/shared/exchange-rate-footer.js +282 -0
  92. package/lib/checkout-v2/components/shared/scenario-badge.d.ts +6 -0
  93. package/lib/checkout-v2/components/shared/scenario-badge.js +57 -0
  94. package/lib/checkout-v2/components/shared/total-display.d.ts +7 -0
  95. package/lib/checkout-v2/components/shared/total-display.js +154 -0
  96. package/lib/checkout-v2/index.d.ts +2 -0
  97. package/lib/checkout-v2/index.js +13 -0
  98. package/lib/checkout-v2/layouts/checkout-layout.d.ts +7 -0
  99. package/lib/checkout-v2/layouts/checkout-layout.js +308 -0
  100. package/lib/checkout-v2/panels/left/composite-panel.d.ts +1 -0
  101. package/lib/checkout-v2/panels/left/composite-panel.js +515 -0
  102. package/lib/checkout-v2/panels/left/credit-topup-panel.d.ts +1 -0
  103. package/lib/checkout-v2/panels/left/credit-topup-panel.js +799 -0
  104. package/lib/checkout-v2/panels/left/scenario-router.d.ts +1 -0
  105. package/lib/checkout-v2/panels/left/scenario-router.js +29 -0
  106. package/lib/checkout-v2/panels/right/payment-panel.d.ts +1 -0
  107. package/lib/checkout-v2/panels/right/payment-panel.js +906 -0
  108. package/lib/checkout-v2/types.d.ts +15 -0
  109. package/lib/checkout-v2/types.js +1 -0
  110. package/lib/checkout-v2/utils/format.d.ts +59 -0
  111. package/lib/checkout-v2/utils/format.js +158 -0
  112. package/lib/checkout-v2/utils/scenario-detector.d.ts +3 -0
  113. package/lib/checkout-v2/utils/scenario-detector.js +23 -0
  114. package/lib/checkout-v2/views/error-view.d.ts +7 -0
  115. package/lib/checkout-v2/views/error-view.js +321 -0
  116. package/lib/checkout-v2/views/loading-view.d.ts +5 -0
  117. package/lib/checkout-v2/views/loading-view.js +168 -0
  118. package/lib/checkout-v2/views/success-view.d.ts +29 -0
  119. package/lib/checkout-v2/views/success-view.js +735 -0
  120. package/lib/components/phone-field.d.ts +14 -0
  121. package/lib/components/phone-field.js +130 -0
  122. package/lib/index.d.ts +3 -1
  123. package/lib/index.js +8 -0
  124. package/lib/locales/en.js +45 -6
  125. package/lib/locales/zh.js +45 -6
  126. package/lib/payment/form/index.js +10 -1
  127. package/package.json +4 -3
  128. package/src/checkout-v2/checkout-v2.tsx +155 -0
  129. package/src/checkout-v2/components/dialogs/checkout-dialogs.tsx +134 -0
  130. package/src/checkout-v2/components/left/billing-toggle.tsx +122 -0
  131. package/src/checkout-v2/components/left/cross-sell-card.tsx +170 -0
  132. package/src/checkout-v2/components/left/product-item-card.tsx +634 -0
  133. package/src/checkout-v2/components/left/promotion-input.tsx +207 -0
  134. package/src/checkout-v2/components/left/staking-breakdown.tsx +57 -0
  135. package/src/checkout-v2/components/left/trial-info.tsx +63 -0
  136. package/src/checkout-v2/components/right/currency-grid.tsx +59 -0
  137. package/src/checkout-v2/components/right/customer-info-card.tsx +214 -0
  138. package/src/checkout-v2/components/right/status-feedback.tsx +35 -0
  139. package/src/checkout-v2/components/right/submit-button.tsx +37 -0
  140. package/src/checkout-v2/components/right/subscription-disclaimer.tsx +27 -0
  141. package/src/checkout-v2/components/shared/exchange-rate-footer.tsx +221 -0
  142. package/src/checkout-v2/components/shared/scenario-badge.tsx +51 -0
  143. package/src/checkout-v2/components/shared/total-display.tsx +112 -0
  144. package/src/checkout-v2/index.ts +2 -0
  145. package/src/checkout-v2/layouts/checkout-layout.tsx +232 -0
  146. package/src/checkout-v2/panels/left/composite-panel.tsx +465 -0
  147. package/src/checkout-v2/panels/left/credit-topup-panel.tsx +681 -0
  148. package/src/checkout-v2/panels/left/scenario-router.tsx +22 -0
  149. package/src/checkout-v2/panels/right/payment-panel.tsx +703 -0
  150. package/src/checkout-v2/types.ts +18 -0
  151. package/src/checkout-v2/utils/format.ts +204 -0
  152. package/src/checkout-v2/utils/scenario-detector.ts +30 -0
  153. package/src/checkout-v2/views/error-view.tsx +293 -0
  154. package/src/checkout-v2/views/loading-view.tsx +162 -0
  155. package/src/checkout-v2/views/success-view.tsx +770 -0
  156. package/src/components/phone-field.tsx +119 -0
  157. package/src/index.ts +3 -0
  158. package/src/locales/en.tsx +45 -4
  159. package/src/locales/zh.tsx +43 -4
  160. package/src/payment/form/index.tsx +16 -1
@@ -0,0 +1,96 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useCallback } from "react";
3
+ import { Box, InputBase, InputAdornment, Typography } from "@mui/material";
4
+ import { defaultCountries, usePhoneInput } from "react-international-phone";
5
+ import { useMount } from "ahooks";
6
+ import CountrySelect from "./country-select.js";
7
+ import { isValidCountry } from "../libs/util.js";
8
+ import { getPhoneUtil } from "../libs/phone-validator.js";
9
+ export default function PhoneField({
10
+ value,
11
+ country: externalCountry,
12
+ onChange,
13
+ onCountryChange,
14
+ label,
15
+ error = void 0,
16
+ onBlur = void 0
17
+ }) {
18
+ const isUpdatingRef = useRef(false);
19
+ const safeUpdate = useCallback((callback) => {
20
+ if (isUpdatingRef.current) return;
21
+ try {
22
+ isUpdatingRef.current = true;
23
+ callback();
24
+ } finally {
25
+ requestAnimationFrame(() => {
26
+ isUpdatingRef.current = false;
27
+ });
28
+ }
29
+ }, []);
30
+ const { phone, handlePhoneValueChange, inputRef, country, setCountry } = usePhoneInput({
31
+ defaultCountry: isValidCountry(externalCountry) ? externalCountry : "us",
32
+ value: value || "",
33
+ countries: defaultCountries,
34
+ onChange: (data) => {
35
+ safeUpdate(() => {
36
+ onChange(data.phone);
37
+ onCountryChange(data.country);
38
+ });
39
+ }
40
+ });
41
+ useMount(() => {
42
+ getPhoneUtil().catch((err) => {
43
+ console.error("Failed to preload phone validator:", err);
44
+ });
45
+ });
46
+ useEffect(() => {
47
+ if (!externalCountry || externalCountry === country) return;
48
+ safeUpdate(() => {
49
+ setCountry(externalCountry);
50
+ });
51
+ }, [externalCountry, country, setCountry, safeUpdate]);
52
+ const handleCountryChange = useCallback(
53
+ (v) => {
54
+ safeUpdate(() => {
55
+ setCountry(v);
56
+ onCountryChange(v);
57
+ });
58
+ },
59
+ [setCountry, safeUpdate, onCountryChange]
60
+ );
61
+ return /* @__PURE__ */ jsxs(Box, { sx: { mb: 1.5 }, children: [
62
+ /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 13, fontWeight: 600, color: "text.primary", mb: 0.5 }, children: label }),
63
+ /* @__PURE__ */ jsx(
64
+ InputBase,
65
+ {
66
+ fullWidth: true,
67
+ value: phone,
68
+ onChange: handlePhoneValueChange,
69
+ onBlur,
70
+ type: "tel",
71
+ inputRef,
72
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", sx: { mr: 0.25, ml: -0.5 }, children: /* @__PURE__ */ jsx(
73
+ CountrySelect,
74
+ {
75
+ value: country,
76
+ onChange: handleCountryChange,
77
+ sx: {
78
+ ".MuiOutlinedInput-notchedOutline": { borderColor: "transparent !important" },
79
+ "& .MuiSelect-select": { py: 0, pr: "20px !important" }
80
+ },
81
+ showDialCode: true
82
+ }
83
+ ) }),
84
+ sx: {
85
+ bgcolor: (theme) => theme.palette.mode === "dark" ? "rgba(255,255,255,0.06)" : "grey.50",
86
+ borderRadius: "8px",
87
+ px: 1.5,
88
+ py: 0.75,
89
+ fontSize: 14,
90
+ "& .MuiInputBase-input": { p: 0 }
91
+ }
92
+ }
93
+ ),
94
+ error && /* @__PURE__ */ jsx(Typography, { sx: { fontSize: 12, color: "error.main", mt: 0.25 }, children: error })
95
+ ] });
96
+ }
package/es/index.d.ts CHANGED
@@ -46,6 +46,7 @@ import PromotionCode from './components/promotion-code';
46
46
  import SourceDataViewer from './components/source-data-viewer';
47
47
  import SlippageConfig from './components/slippage-config';
48
48
  import DynamicPricingUnavailable from './components/dynamic-pricing-unavailable';
49
+ import { CheckoutV2 } from './checkout-v2';
49
50
  export { PaymentThemeProvider } from './theme';
50
51
  export * from './libs/util';
51
52
  export * from './libs/connect';
@@ -60,7 +61,8 @@ export * from './hooks/scroll';
60
61
  export * from './hooks/keyboard';
61
62
  export * from './libs/validator';
62
63
  export { translations, createTranslator } from './locales';
63
- export { createLazyComponent, api, dayjs, FormInput, FormLabel, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, StripePaymentAction, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, PromotionCode, SourceDataViewer, SlippageConfig, DynamicPricingUnavailable, PromotionSection, TotalSection, };
64
+ export { createLazyComponent, api, dayjs, FormInput, FormLabel, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, TxLink, TxGas, SafeGuard, PricingItem, CountrySelect, Table, TruncatedText, Link, OverdueInvoicePayment, StripePaymentAction, PaymentBeneficiaries, LoadingButton, DonateDetails, ResumeSubscription, CreditGrantsList, CreditTransactionsList, DateRangePicker, CreditStatusChip, AutoTopupModal, AutoTopup, Collapse, PromotionCode, SourceDataViewer, SlippageConfig, DynamicPricingUnavailable, PromotionSection, TotalSection, CheckoutV2, };
64
65
  export type { CountrySelectProps } from './components/country-select';
65
66
  export type { StripePaymentActionProps } from './components/stripe-payment-action';
66
67
  export type { SlippageConfigValue, SlippageConfigProps } from './components/slippage-config';
68
+ export type { CheckoutV2Props } from './checkout-v2';
package/es/index.js CHANGED
@@ -46,6 +46,7 @@ import PromotionCode from "./components/promotion-code.js";
46
46
  import SourceDataViewer from "./components/source-data-viewer.js";
47
47
  import SlippageConfig from "./components/slippage-config.js";
48
48
  import DynamicPricingUnavailable from "./components/dynamic-pricing-unavailable.js";
49
+ import { CheckoutV2 } from "./checkout-v2/index.js";
49
50
  export { PaymentThemeProvider } from "./theme/index.js";
50
51
  export * from "./libs/util.js";
51
52
  export * from "./libs/connect.js";
@@ -110,5 +111,6 @@ export {
110
111
  SlippageConfig,
111
112
  DynamicPricingUnavailable,
112
113
  PromotionSection,
113
- TotalSection
114
+ TotalSection,
115
+ CheckoutV2
114
116
  };
package/es/locales/en.js CHANGED
@@ -19,6 +19,7 @@ export default flat({
19
19
  setup: "Setup",
20
20
  amount: "Amount",
21
21
  total: "Total",
22
+ totalDue: "Total Due",
22
23
  subtotal: "Subtotal",
23
24
  status: "Status",
24
25
  livemode: "Test mode",
@@ -85,6 +86,7 @@ export default flat({
85
86
  viewConsumptionDetail: "Consumption Detail",
86
87
  customer: "Customer",
87
88
  currency: "Currency",
89
+ network: "Network",
88
90
  custom: "Custom",
89
91
  description: "Description",
90
92
  statementDescriptor: "Statement descriptor",
@@ -276,11 +278,14 @@ export default flat({
276
278
  free: "{count} {interval}{count > 1 ? 's' : ''} free",
277
279
  least: "continue with at least",
278
280
  completed: {
279
- payment: "Thanks for your purchase",
280
- subscription: "Thanks for subscribing",
281
- setup: "Thanks for subscribing",
282
- donate: "Thanks for your tip",
283
- tip: "A payment to {payee} has been completed. You can view the details of this payment in your account."
281
+ payment: "Purchase successful",
282
+ subscription: "Subscription successful",
283
+ setup: "Subscription successful",
284
+ donate: "Donation successful",
285
+ tip: "A payment to {payee} has been completed. You can view the details of this payment in your account.",
286
+ summary: {
287
+ paid: "You've paid {amount}"
288
+ }
284
289
  },
285
290
  vendor: {
286
291
  accountRequired: "This action requires a unified account. Please switch accounts and try again.",
@@ -360,7 +365,8 @@ export default flat({
360
365
  schedule: {
361
366
  periodic: "Grant {amount} every {interval}.",
362
367
  withRefresh: "Grant {amount} every {interval}; unused credits expire with the next grant."
363
- }
368
+ },
369
+ topupDescription: "Purchase {creditName} at {unitPrice} per credit."
364
370
  },
365
371
  expired: {
366
372
  title: "Expired Link",
@@ -374,9 +380,42 @@ export default flat({
374
380
  title: "Nothing to show here",
375
381
  description: "It seems this checkout session is not configured properly"
376
382
  },
383
+ error: {
384
+ title: "Something went wrong"
385
+ },
377
386
  orderSummary: "Order Summary",
387
+ orderSummarySubtitle: "Items included in this purchase",
378
388
  paymentDetails: "Payment Details",
379
389
  productListTotal: "Includes {total} items",
390
+ headerTitle: {
391
+ subscribe: "Subscribe to {name}",
392
+ purchase: "Purchase {name}"
393
+ },
394
+ planFeatures: "Plan Features",
395
+ typeBadge: {
396
+ subscription: "SUBSCRIPTION",
397
+ topup: "TOP-UP",
398
+ oneTime: "ONE-TIME"
399
+ },
400
+ subtitle: {
401
+ subscriptionInterval: "{interval} subscription",
402
+ creditsTopup: "Credits top-up",
403
+ addonFor: "Add-on for {product}",
404
+ oneTime: "One-time purchase"
405
+ },
406
+ creditTopup: {
407
+ title: "Get {name}",
408
+ question: "How many {symbol} do you want?",
409
+ credits: "Credits",
410
+ increment: "Increments of {step} {symbol}",
411
+ validFor: "Credits are valid for {duration} {unit} after purchase.",
412
+ willReceive: "You'll receive",
413
+ packInfo: "Includes {packs} credit packs ({perPack} per pack)",
414
+ autoMatch: "We'll automatically match the closest credit pack.",
415
+ autoMatchTooltip: "{symbol} are sold in packs of {step}",
416
+ pendingWarning: "You have a usage overage of {pendingAmount}. You need at least {minCredits} to restore access.",
417
+ pendingEnough: "You have a usage overage of {pendingAmount}. After covering the overage, your available balance will be {availableAmount}."
418
+ },
380
419
  promotion: {
381
420
  add_code: "Add promotion code",
382
421
  enter_code: "Enter promotion code",
package/es/locales/zh.js CHANGED
@@ -19,6 +19,7 @@ export default flat({
19
19
  accessDenied: "\u60A8\u65E0\u6743\u8BBF\u95EE\u5176\u4ED6\u5BA2\u6237\u7684\u6570\u636E",
20
20
  amount: "\u91D1\u989D",
21
21
  total: "\u603B\u8BA1",
22
+ totalDue: "\u5E94\u4ED8\u603B\u989D",
22
23
  subtotal: "\u5C0F\u8BA1",
23
24
  status: "\u72B6\u6001",
24
25
  livemode: "\u6D4B\u8BD5\u6A21\u5F0F",
@@ -85,6 +86,7 @@ export default flat({
85
86
  viewConsumptionDetail: "\u6D88\u8D39\u8BE6\u60C5",
86
87
  customer: "\u5BA2\u6237",
87
88
  currency: "\u5E01\u79CD",
89
+ network: "\u7F51\u7EDC",
88
90
  custom: "\u81EA\u5B9A\u4E49",
89
91
  description: "\u63CF\u8FF0",
90
92
  statementDescriptor: "\u58F0\u660E\u63CF\u8FF0",
@@ -276,11 +278,14 @@ export default flat({
276
278
  free: "\u514D\u8D39\u8BD5\u7528 {count} {interval}",
277
279
  least: "\u81F3\u5C11",
278
280
  completed: {
279
- payment: "\u611F\u8C22\u60A8\u7684\u8D2D\u4E70",
280
- subscription: "\u611F\u8C22\u60A8\u7684\u8BA2\u9605",
281
- setup: "\u611F\u8C22\u60A8\u7684\u8BA2\u9605",
282
- donate: "\u611F\u8C22\u60A8\u7684\u652F\u6301",
283
- tip: "\u5411 {payee} \u7684\u4ED8\u6B3E\u5DF2\u5B8C\u6210\u3002\u60A8\u53EF\u4EE5\u5728\u60A8\u7684\u8D26\u6237\u4E2D\u67E5\u770B\u6B64\u4ED8\u6B3E\u7684\u8BE6\u7EC6\u4FE1\u606F\u3002"
281
+ payment: "\u8D2D\u4E70\u6210\u529F",
282
+ subscription: "\u8BA2\u9605\u6210\u529F",
283
+ setup: "\u8BA2\u9605\u6210\u529F",
284
+ donate: "\u6350\u8D60\u6210\u529F",
285
+ tip: "\u5411 {payee} \u7684\u4ED8\u6B3E\u5DF2\u5B8C\u6210\u3002\u60A8\u53EF\u4EE5\u5728\u60A8\u7684\u8D26\u6237\u4E2D\u67E5\u770B\u6B64\u4ED8\u6B3E\u7684\u8BE6\u7EC6\u4FE1\u606F\u3002",
286
+ summary: {
287
+ paid: "\u672C\u6B21\u652F\u4ED8 {amount}"
288
+ }
284
289
  },
285
290
  vendor: {
286
291
  accountRequired: "\u60A8\u5F53\u524D\u4F7F\u7528\u7684\u662F\u975E\u7EDF\u4E00\u8D26\u6237\u767B\u5F55\uFF0C\u6B64\u670D\u52A1\u9700\u8981\u60A8\u4F7F\u7528\u7EDF\u4E00\u8D26\u6237\u3002\u8BF7\u5207\u6362\u5230\u7EDF\u4E00\u8D26\u6237\u767B\u5F55\u540E\u91CD\u8BD5\u3002",
@@ -397,15 +402,49 @@ export default flat({
397
402
  schedule: {
398
403
  periodic: "\u6BCF{interval}\u53D1\u653E {amount}\u3002",
399
404
  withRefresh: "\u6BCF{interval}\u53D1\u653E {amount}\uFF0C\u672A\u4F7F\u7528\u989D\u5EA6\u5C06\u5728\u4E0B\u6B21\u53D1\u653E\u65F6\u8FC7\u671F\u3002"
400
- }
405
+ },
406
+ topupDescription: "\u8D2D\u4E70 {creditName}\uFF0C\u5355\u4EF7 {unitPrice}/\u989D\u5EA6\u3002"
401
407
  },
402
408
  emptyItems: {
403
409
  title: "\u6CA1\u6709\u4EFB\u4F55\u8D2D\u4E70\u9879\u76EE",
404
410
  description: "\u53EF\u80FD\u8FD9\u4E2A\u4ED8\u6B3E\u94FE\u63A5\u6CA1\u6709\u6B63\u786E\u914D\u7F6E"
405
411
  },
412
+ error: {
413
+ title: "\u51FA\u4E86\u70B9\u95EE\u9898"
414
+ },
406
415
  orderSummary: "\u8BA2\u5355\u6982\u89C8",
416
+ orderSummarySubtitle: "\u672C\u6B21\u4EA4\u6613\u5305\u542B\u4EE5\u4E0B\u9879\u76EE",
407
417
  paymentDetails: "\u652F\u4ED8\u4FE1\u606F",
408
418
  productListTotal: "\u5305\u62EC {total} \u9879",
419
+ headerTitle: {
420
+ subscribe: "\u8BA2\u9605 {name}",
421
+ purchase: "\u8D2D\u4E70 {name}"
422
+ },
423
+ planFeatures: "\u529F\u80FD\u7279\u6027",
424
+ typeBadge: {
425
+ subscription: "\u8BA2\u9605",
426
+ topup: "\u5145\u503C",
427
+ oneTime: "\u4E00\u6B21\u6027\u8D2D\u4E70"
428
+ },
429
+ subtitle: {
430
+ subscriptionInterval: "{interval}\u8BA2\u9605",
431
+ creditsTopup: "\u4F59\u989D\u5145\u503C",
432
+ addonFor: "{product} \u7684\u9644\u52A0\u9879",
433
+ oneTime: "\u4E00\u6B21\u6027\u8D2D\u4E70"
434
+ },
435
+ creditTopup: {
436
+ title: "\u8D2D\u4E70 {name}",
437
+ question: "\u4F60\u9700\u8981\u591A\u5C11 {symbol}\uFF1F",
438
+ credits: "\u989D\u5EA6",
439
+ increment: "\u6BCF\u6B21\u589E\u51CF {step} {symbol}",
440
+ validFor: "\u989D\u5EA6\u5728\u8D2D\u4E70\u540E {duration} {unit}\u5185\u6709\u6548\u3002",
441
+ willReceive: "\u4F60\u5C06\u83B7\u5F97",
442
+ packInfo: "\u5305\u542B {packs} \u4E2A\u989D\u5EA6\u5305\uFF08\u6BCF\u5305 {perPack}\uFF09",
443
+ autoMatch: "\u6211\u4EEC\u5C06\u81EA\u52A8\u5339\u914D\u6700\u63A5\u8FD1\u7684\u989D\u5EA6\u5305\u3002",
444
+ autoMatchTooltip: "{symbol} \u6309\u6BCF\u5305 {step} \u4E2A\u51FA\u552E",
445
+ pendingWarning: "\u60A8\u6709 {pendingAmount} \u7684\u4F7F\u7528\u8D85\u989D\uFF0C\u81F3\u5C11\u9700\u8981\u8D2D\u4E70 {minCredits} \u624D\u80FD\u6062\u590D\u8BBF\u95EE\u3002",
446
+ pendingEnough: "\u60A8\u6709 {pendingAmount} \u7684\u4F7F\u7528\u8D85\u989D\uFF0C\u6263\u9664\u540E\u60A8\u7684\u53EF\u7528\u4F59\u989D\u5C06\u4E3A {availableAmount}\u3002"
447
+ },
409
448
  connectModal: {
410
449
  title: "{action}",
411
450
  scan: "\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u5B8C\u6210\u672C\u6B21\u652F\u4ED8",
@@ -144,6 +144,8 @@ export default function PaymentForm({
144
144
  } = useFormContext();
145
145
  const errorRef = useRef(null);
146
146
  const processingRef = useRef(false);
147
+ const idempotencyKeyRef = useRef("");
148
+ const sessionFingerprintRef = useRef("");
147
149
  const quantityInventoryStatus = useMemo(() => {
148
150
  let status = true;
149
151
  for (const item of checkoutSession.line_items) {
@@ -741,10 +743,17 @@ export default function PaymentForm({
741
743
  try {
742
744
  let result;
743
745
  const previewRate = checkoutSession.line_items?.find((item) => item?.exchange_rate)?.exchange_rate || void 0;
746
+ const items = checkoutSession.line_items || [];
747
+ const itemsSig = items.map((i) => `${i.upsell_price_id || i.price_id}:${i.quantity}`).join("|");
748
+ const fingerprint = `${checkoutSession.id}-${paymentCurrency?.id}-${itemsSig}`;
749
+ if (fingerprint !== sessionFingerprintRef.current || !idempotencyKeyRef.current) {
750
+ sessionFingerprintRef.current = fingerprint;
751
+ idempotencyKeyRef.current = generateIdempotencyKey(checkoutSession.id, paymentCurrency?.id || "");
752
+ }
744
753
  const payload = {
745
754
  ...data,
746
755
  // Final Freeze: Include these for new quote creation at submit
747
- idempotency_key: generateIdempotencyKey(checkoutSession.id, paymentCurrency?.id || ""),
756
+ idempotency_key: idempotencyKeyRef.current,
748
757
  preview_rate: previewRate || void 0,
749
758
  price_confirmed: state.priceChangeConfirm?.formData ? true : void 0
750
759
  };
@@ -0,0 +1,2 @@
1
+ import type { CheckoutV2Props } from './types';
2
+ export default function CheckoutV2({ id, onPaid, onError, theme, mode, extraParams, }: CheckoutV2Props): import("react").JSX.Element;
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = CheckoutV2;
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ var _react = require("react");
9
+ var _ahooks = require("ahooks");
10
+ var _ufo = require("ufo");
11
+ var _material = require("@mui/material");
12
+ var _paymentReactHeadless = require("@blocklet/payment-react-headless");
13
+ var _api = _interopRequireDefault(require("../libs/api"));
14
+ var _util = require("../libs/util");
15
+ var _theme = require("../theme");
16
+ var _mobile = require("../hooks/mobile");
17
+ var _checkoutLayout = _interopRequireDefault(require("./layouts/checkout-layout"));
18
+ var _scenarioRouter = _interopRequireDefault(require("./panels/left/scenario-router"));
19
+ var _paymentPanel = _interopRequireDefault(require("./panels/right/payment-panel"));
20
+ var _checkoutDialogs = _interopRequireDefault(require("./components/dialogs/checkout-dialogs"));
21
+ var _loadingView = _interopRequireDefault(require("./views/loading-view"));
22
+ var _errorView = _interopRequireDefault(require("./views/error-view"));
23
+ var _successView = _interopRequireDefault(require("./views/success-view"));
24
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
+ const plinkPromises = {};
26
+ function startFromPaymentLink(id, params) {
27
+ if (!plinkPromises[id]) {
28
+ plinkPromises[id] = _api.default.post(`/api/checkout-sessions/start/${id}?${(0, _util.mergeExtraParams)(params)}`).then(res => res?.data).finally(() => {
29
+ setTimeout(() => {
30
+ delete plinkPromises[id];
31
+ }, 3e3);
32
+ });
33
+ }
34
+ return plinkPromises[id];
35
+ }
36
+ function CheckoutRouter({
37
+ onPaid = void 0,
38
+ onError = void 0,
39
+ mode = "inline"
40
+ }) {
41
+ const {
42
+ isLoading,
43
+ error,
44
+ errorCode,
45
+ session
46
+ } = (0, _paymentReactHeadless.useSessionContext)();
47
+ const submit = (0, _paymentReactHeadless.useSubmitFeature)();
48
+ const {
49
+ isMobile
50
+ } = (0, _mobile.useMobile)();
51
+ (0, _react.useEffect)(() => {
52
+ if (error && onError) {
53
+ onError(new Error(error));
54
+ }
55
+ }, [error, onError]);
56
+ (0, _react.useEffect)(() => {
57
+ if (submit.status === "completed" && submit.result && onPaid) {
58
+ onPaid(submit.result);
59
+ }
60
+ }, [submit.status, submit.result, onPaid]);
61
+ if (isLoading) {
62
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingView.default, {
63
+ mode
64
+ });
65
+ }
66
+ if (error) {
67
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_errorView.default, {
68
+ error,
69
+ errorCode,
70
+ mode
71
+ });
72
+ }
73
+ const isCompleted = submit.status === "completed";
74
+ const mobileCompleted = isCompleted && isMobile;
75
+ return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
76
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_checkoutLayout.default, {
77
+ left: mobileCompleted ? null : /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Box, {
78
+ sx: {
79
+ flex: 1,
80
+ display: "flex",
81
+ flexDirection: "column",
82
+ ...(isCompleted ? {
83
+ opacity: 0.45,
84
+ pointerEvents: "none",
85
+ filter: "grayscale(0.3)",
86
+ transition: "all 0.5s ease"
87
+ } : {})
88
+ },
89
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_scenarioRouter.default, {})
90
+ }),
91
+ right: isCompleted ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_successView.default, {
92
+ submit,
93
+ session
94
+ }) : /* @__PURE__ */(0, _jsxRuntime.jsx)(_paymentPanel.default, {}),
95
+ mode
96
+ }), !isCompleted && /* @__PURE__ */(0, _jsxRuntime.jsx)(_checkoutDialogs.default, {})]
97
+ });
98
+ }
99
+ function CheckoutV2({
100
+ id,
101
+ onPaid,
102
+ onError,
103
+ theme = "default",
104
+ mode = "inline",
105
+ extraParams = {}
106
+ }) {
107
+ if (!id.startsWith("plink_") && !id.startsWith("cs_")) {
108
+ throw new Error("Either a checkoutSession or a paymentLink id is required.");
109
+ }
110
+ const isPaymentLink = id.startsWith("plink_");
111
+ const [resolvedSessionId, setResolvedSessionId] = (0, _react.useState)(isPaymentLink ? null : id);
112
+ (0, _ahooks.useRequest)(async () => {
113
+ if (!isPaymentLink) return null;
114
+ const data = await startFromPaymentLink(id, extraParams);
115
+ const csId = data?.checkoutSession?.id;
116
+ if (csId) {
117
+ setResolvedSessionId(csId);
118
+ if (mode === "standalone") {
119
+ window.history.replaceState(null, "", (0, _ufo.joinURL)((0, _util.getPrefix)(), `/checkout/pay/${csId}?${(0, _util.mergeExtraParams)(extraParams)}`));
120
+ }
121
+ }
122
+ return data;
123
+ }, {
124
+ ready: isPaymentLink
125
+ });
126
+ if (!resolvedSessionId) {
127
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingView.default, {
128
+ mode
129
+ });
130
+ }
131
+ const content = /* @__PURE__ */(0, _jsxRuntime.jsx)(_paymentReactHeadless.CheckoutProvider, {
132
+ sessionId: resolvedSessionId,
133
+ children: /* @__PURE__ */(0, _jsxRuntime.jsx)(CheckoutRouter, {
134
+ onPaid,
135
+ onError,
136
+ mode
137
+ })
138
+ });
139
+ if (theme === "inherit") {
140
+ return content;
141
+ }
142
+ if (theme && typeof theme === "object") {
143
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_theme.PaymentThemeProvider, {
144
+ theme,
145
+ children: content
146
+ });
147
+ }
148
+ return /* @__PURE__ */(0, _jsxRuntime.jsx)(_theme.PaymentThemeProvider, {
149
+ children: content
150
+ });
151
+ }
@@ -0,0 +1 @@
1
+ export default function CheckoutDialogs(): import("react").JSX.Element;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = CheckoutDialogs;
7
+ var _jsxRuntime = require("react/jsx-runtime");
8
+ var _material = require("@mui/material");
9
+ var _context = require("@arcblock/ux/lib/Locale/context");
10
+ var _paymentReactHeadless = require("@blocklet/payment-react-headless");
11
+ var _stripe = _interopRequireDefault(require("../../../payment/form/stripe"));
12
+ var _confirm = _interopRequireDefault(require("../../../components/confirm"));
13
+ var _priceChangeConfirm = _interopRequireDefault(require("../../../components/price-change-confirm"));
14
+ var _format = require("../../utils/format");
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
+ function getRedirectUrl(session) {
17
+ try {
18
+ const params = new URLSearchParams(window.location.search);
19
+ const redirect = params.get("redirect");
20
+ if (redirect) return decodeURIComponent(redirect);
21
+ } catch {}
22
+ if (session?.success_url) return session.success_url;
23
+ if (session?.payment_link?.after_completion?.redirect?.url) {
24
+ return session.payment_link.after_completion.redirect.url;
25
+ }
26
+ return void 0;
27
+ }
28
+ function CheckoutDialogs() {
29
+ const {
30
+ t
31
+ } = (0, _context.useLocaleContext)();
32
+ const {
33
+ session
34
+ } = (0, _paymentReactHeadless.useSessionContext)();
35
+ const {
36
+ currency,
37
+ stripe
38
+ } = (0, _paymentReactHeadless.usePaymentMethodContext)();
39
+ const submit = (0, _paymentReactHeadless.useSubmitFeature)();
40
+ const form = (0, _paymentReactHeadless.useCustomerFormFeature)();
41
+ const mode = session?.mode || "payment";
42
+ const stripeContext = submit.context?.type === "stripe" ? submit.context : null;
43
+ const showStripeDialog = submit.status === "waiting_stripe" && stripeContext?.clientSecret;
44
+ return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
45
+ children: [showStripeDialog && /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripe.default, {
46
+ clientSecret: stripeContext.clientSecret,
47
+ intentType: stripeContext.intentType || "payment_intent",
48
+ publicKey: stripe?.publishableKey || "",
49
+ mode,
50
+ customer: {
51
+ name: form.values.customer_name,
52
+ email: form.values.customer_email,
53
+ phone: form.values.customer_phone,
54
+ address: form.values.billing_address
55
+ },
56
+ returnUrl: getRedirectUrl(session),
57
+ onConfirm: submit.stripeConfirm,
58
+ onCancel: submit.stripeCancel
59
+ }), submit.status === "confirming_price" && submit.context?.type === "price_change" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_priceChangeConfirm.default, {
60
+ open: true,
61
+ changePercent: submit.context.changePercent,
62
+ onConfirm: submit.confirm,
63
+ onCancel: submit.cancel,
64
+ loading: false
65
+ }), submit.status === "confirming_fast_pay" && submit.context?.type === "fast_pay" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_confirm.default, {
66
+ onConfirm: submit.confirm,
67
+ onCancel: submit.cancel,
68
+ title: submit.context.payType === "credit" ? t("payment.checkout.fastPay.credit.title") : t("payment.checkout.fastPay.title"),
69
+ message: submit.context.payType === "credit" ? /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
70
+ children: t("payment.checkout.fastPay.credit.meteringSubscriptionMessage", {
71
+ available: `${(0, _format.formatTokenAmount)(submit.context.amount || "0", currency)} ${currency?.symbol || ""}`
72
+ })
73
+ }) : /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
74
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
75
+ children: t("payment.checkout.fastPay.autoPaymentReason")
76
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Divider, {
77
+ sx: {
78
+ mt: 1.5,
79
+ mb: 1.5
80
+ }
81
+ }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
82
+ spacing: 1,
83
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
84
+ sx: {
85
+ flexDirection: "row",
86
+ alignItems: "center",
87
+ justifyContent: "space-between"
88
+ },
89
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
90
+ sx: {
91
+ color: "text.primary",
92
+ whiteSpace: "nowrap"
93
+ },
94
+ children: t("payment.checkout.fastPay.payer")
95
+ }), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
96
+ sx: {
97
+ color: "text.secondary",
98
+ fontSize: 14
99
+ },
100
+ children: submit.context.payer ? `${submit.context.payer.slice(0, 10)}...${submit.context.payer.slice(-6)}` : ""
101
+ })]
102
+ }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
103
+ sx: {
104
+ flexDirection: "row",
105
+ alignItems: "center",
106
+ justifyContent: "space-between"
107
+ },
108
+ children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
109
+ sx: {
110
+ color: "text.primary"
111
+ },
112
+ children: t("payment.checkout.fastPay.amount")
113
+ }), /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Typography, {
114
+ children: [(0, _format.formatTokenAmount)(submit.context.amount || "0", currency), " ", currency?.symbol || ""]
115
+ })]
116
+ })]
117
+ })]
118
+ }),
119
+ loading: false,
120
+ color: "primary"
121
+ }), submit.status === "credit_insufficient" && submit.context?.type === "credit_insufficient" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_confirm.default, {
122
+ onConfirm: submit.cancel,
123
+ onCancel: submit.cancel,
124
+ title: t("payment.checkout.fastPay.credit.insufficientTitle"),
125
+ message: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
126
+ children: t("payment.checkout.fastPay.credit.insufficientMessage")
127
+ }),
128
+ confirm: t("common.confirm")
129
+ })]
130
+ });
131
+ }
@@ -0,0 +1,6 @@
1
+ import type { BillingIntervalData } from '@blocklet/payment-react-headless';
2
+ interface BillingToggleProps {
3
+ billingInterval: BillingIntervalData | null;
4
+ }
5
+ export default function BillingToggle({ billingInterval }: BillingToggleProps): import("react").JSX.Element | null;
6
+ export {};