@blocklet/payment-react 1.13.239 → 1.13.241

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 (104) hide show
  1. package/es/checkout/donate.js +7 -5
  2. package/es/checkout/form.js +2 -2
  3. package/es/checkout/table.js +2 -2
  4. package/es/components/blockchain/gas.js +1 -1
  5. package/es/components/blockchain/tx.js +1 -1
  6. package/es/components/confirm.d.ts +4 -2
  7. package/es/components/confirm.js +5 -2
  8. package/es/components/pricing-table.js +1 -1
  9. package/es/components/safe-guard.js +1 -1
  10. package/es/contexts/payment.js +2 -2
  11. package/es/history/invoice/list.js +62 -10
  12. package/es/history/mini-invoice/list.js +16 -8
  13. package/es/history/payment/list.js +2 -2
  14. package/es/hooks/subscription.d.ts +7 -0
  15. package/es/hooks/subscription.js +55 -0
  16. package/es/index.d.ts +4 -3
  17. package/es/index.js +4 -3
  18. package/es/{api.js → libs/api.js} +6 -2
  19. package/es/libs/did-connect.d.ts +10 -0
  20. package/es/libs/did-connect.js +11 -0
  21. package/es/{util.d.ts → libs/util.d.ts} +1 -1
  22. package/es/{util.js → libs/util.js} +1 -1
  23. package/es/locales/en.js +1 -0
  24. package/es/locales/zh.js +1 -0
  25. package/es/payment/form/index.js +28 -6
  26. package/es/payment/form/phone.js +1 -1
  27. package/es/payment/header.js +1 -1
  28. package/es/payment/index.js +9 -2
  29. package/es/payment/product-card.js +34 -14
  30. package/es/payment/product-item.js +26 -16
  31. package/es/payment/summary.js +12 -3
  32. package/es/types/shims.d.ts +1 -3
  33. package/lib/checkout/donate.js +6 -5
  34. package/lib/checkout/form.js +2 -2
  35. package/lib/checkout/table.js +2 -2
  36. package/lib/components/blockchain/gas.js +1 -1
  37. package/lib/components/blockchain/tx.js +1 -1
  38. package/lib/components/confirm.d.ts +4 -2
  39. package/lib/components/confirm.js +5 -2
  40. package/lib/components/pricing-table.js +1 -1
  41. package/lib/components/safe-guard.js +1 -1
  42. package/lib/contexts/payment.js +2 -2
  43. package/lib/history/invoice/list.js +77 -9
  44. package/lib/history/mini-invoice/list.js +17 -3
  45. package/lib/history/payment/list.js +2 -2
  46. package/lib/hooks/subscription.d.ts +7 -0
  47. package/lib/hooks/subscription.js +62 -0
  48. package/lib/index.d.ts +4 -3
  49. package/lib/index.js +17 -5
  50. package/lib/{api.js → libs/api.js} +5 -2
  51. package/lib/libs/did-connect.d.ts +10 -0
  52. package/lib/libs/did-connect.js +16 -0
  53. package/lib/{util.d.ts → libs/util.d.ts} +1 -1
  54. package/lib/{util.js → libs/util.js} +1 -1
  55. package/lib/locales/en.js +1 -0
  56. package/lib/locales/zh.js +1 -0
  57. package/lib/payment/form/index.js +35 -9
  58. package/lib/payment/form/phone.js +1 -1
  59. package/lib/payment/header.js +1 -1
  60. package/lib/payment/index.js +9 -2
  61. package/lib/payment/product-card.js +10 -0
  62. package/lib/payment/product-item.js +3 -2
  63. package/lib/payment/summary.js +4 -2
  64. package/lib/types/shims.d.ts +1 -3
  65. package/package.json +31 -30
  66. package/src/checkout/donate.tsx +7 -5
  67. package/src/checkout/form.tsx +2 -2
  68. package/src/checkout/table.tsx +2 -2
  69. package/src/components/blockchain/gas.tsx +1 -1
  70. package/src/components/blockchain/tx.tsx +1 -1
  71. package/src/components/confirm.tsx +7 -3
  72. package/src/components/pricing-table.tsx +1 -1
  73. package/src/components/safe-guard.tsx +1 -1
  74. package/src/contexts/payment.tsx +2 -2
  75. package/src/history/invoice/list.tsx +83 -19
  76. package/src/history/mini-invoice/list.tsx +19 -8
  77. package/src/history/payment/list.tsx +2 -2
  78. package/src/hooks/subscription.ts +68 -0
  79. package/src/index.ts +4 -3
  80. package/src/{api.ts → libs/api.ts} +7 -2
  81. package/src/libs/did-connect.ts +20 -0
  82. package/src/{util.ts → libs/util.ts} +4 -3
  83. package/src/locales/en.tsx +1 -0
  84. package/src/locales/zh.tsx +1 -0
  85. package/src/payment/form/index.tsx +36 -5
  86. package/src/payment/form/phone.tsx +1 -1
  87. package/src/payment/header.tsx +1 -1
  88. package/src/payment/index.tsx +9 -2
  89. package/src/payment/product-card.tsx +13 -3
  90. package/src/payment/product-item.tsx +7 -2
  91. package/src/payment/summary.tsx +7 -3
  92. package/src/types/shims.d.ts +1 -3
  93. /package/es/{api.d.ts → libs/api.d.ts} +0 -0
  94. /package/es/{dayjs.d.ts → libs/dayjs.d.ts} +0 -0
  95. /package/es/{dayjs.js → libs/dayjs.js} +0 -0
  96. /package/es/{theme.d.ts → libs/theme.d.ts} +0 -0
  97. /package/es/{theme.js → libs/theme.js} +0 -0
  98. /package/lib/{api.d.ts → libs/api.d.ts} +0 -0
  99. /package/lib/{dayjs.d.ts → libs/dayjs.d.ts} +0 -0
  100. /package/lib/{dayjs.js → libs/dayjs.js} +0 -0
  101. /package/lib/{theme.d.ts → libs/theme.d.ts} +0 -0
  102. /package/lib/{theme.js → libs/theme.js} +0 -0
  103. /package/src/{dayjs.ts → libs/dayjs.ts} +0 -0
  104. /package/src/{theme.ts → libs/theme.ts} +0 -0
@@ -19,9 +19,9 @@ import { useRequest, useSetState } from "ahooks";
19
19
  import omit from "lodash/omit";
20
20
  import uniqBy from "lodash/unionBy";
21
21
  import { useEffect } from "react";
22
- import api from "../api.js";
23
22
  import TxLink from "../components/blockchain/tx.js";
24
- import { formatBNStr, formatDateTime, formatError } from "../util.js";
23
+ import api from "../libs/api.js";
24
+ import { formatBNStr, formatDateTime, formatError } from "../libs/util.js";
25
25
  import CheckoutForm from "./form.js";
26
26
  const donationCache = {};
27
27
  const createOrUpdateDonation = (settings, livemode = true) => {
@@ -35,9 +35,9 @@ const createOrUpdateDonation = (settings, livemode = true) => {
35
35
  return donationCache[settings.target];
36
36
  };
37
37
  const supporterCache = {};
38
- const fetchSupporters = (target) => {
38
+ const fetchSupporters = (target, livemode = true) => {
39
39
  if (!supporterCache[target]) {
40
- supporterCache[target] = api.get("/api/donations", { params: { target } }).then((res) => res.data).finally(() => {
40
+ supporterCache[target] = api.get("/api/donations", { params: { target, livemode } }).then((res) => res.data).finally(() => {
41
41
  setTimeout(() => {
42
42
  delete supporterCache[target];
43
43
  }, 3e3);
@@ -126,7 +126,9 @@ export default function CheckoutDonate({ settings, livemode, onPaid, onError })
126
126
  exist: false
127
127
  });
128
128
  const donation = useRequest(() => createOrUpdateDonation(settings, livemode));
129
- const supporters = useRequest(() => donation.data ? fetchSupporters(donation.data.id) : Promise.resolve({}));
129
+ const supporters = useRequest(
130
+ () => donation.data ? fetchSupporters(donation.data.id, livemode) : Promise.resolve({})
131
+ );
130
132
  useEffect(() => {
131
133
  if (donation.data && state.supporterLoaded === false) {
132
134
  setState({ supporterLoaded: true });
@@ -3,9 +3,9 @@ import { useRequest, useSetState } from "ahooks";
3
3
  import noop from "lodash/noop";
4
4
  import { useEffect } from "react";
5
5
  import { joinURL } from "ufo";
6
- import api from "../api.js";
6
+ import api from "../libs/api.js";
7
+ import { getPrefix, mergeExtraParams } from "../libs/util.js";
7
8
  import Payment from "../payment/index.js";
8
- import { getPrefix, mergeExtraParams } from "../util.js";
9
9
  const promises = {};
10
10
  const startFromPaymentLink = (id, params) => {
11
11
  if (!promises[id]) {
@@ -5,10 +5,10 @@ import { Alert, CircularProgress, Stack, Typography } from "@mui/material";
5
5
  import { Box } from "@mui/system";
6
6
  import { useRequest } from "ahooks";
7
7
  import { useState } from "react";
8
- import api from "../api.js";
9
8
  import Livemode from "../components/livemode.js";
10
9
  import PricingTable from "../components/pricing-table.js";
11
- import { mergeExtraParams } from "../util.js";
10
+ import api from "../libs/api.js";
11
+ import { mergeExtraParams } from "../libs/util.js";
12
12
  import CheckoutForm from "./form.js";
13
13
  const fetchData = async (id) => {
14
14
  const { data } = await api.get(`/api/pricing-tables/${id}`);
@@ -3,7 +3,7 @@ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
3
3
  import { Typography } from "@mui/material";
4
4
  import { fromUnitToToken } from "@ocap/util";
5
5
  import { usePaymentContext } from "../../contexts/payment.js";
6
- import { getTxLink } from "../../util.js";
6
+ import { getTxLink } from "../../libs/util.js";
7
7
  TxGas.defaultProps = {};
8
8
  export default function TxGas(props) {
9
9
  const { t } = useLocaleContext();
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
3
3
  import { OpenInNewOutlined } from "@mui/icons-material";
4
4
  import { Link, Stack, Typography } from "@mui/material";
5
- import { getTxLink } from "../../util.js";
5
+ import { getTxLink } from "../../libs/util.js";
6
6
  TxLink.defaultProps = {
7
7
  mode: "dashboard",
8
8
  align: "left"
@@ -1,11 +1,12 @@
1
1
  import type { EventHandler } from 'react';
2
- declare function ConfirmDialog({ onConfirm, onCancel, title, message, confirm, cancel, loading, }: {
2
+ declare function ConfirmDialog({ onConfirm, onCancel, title, message, confirm, color, cancel, loading, }: {
3
3
  onConfirm: EventHandler<any>;
4
4
  onCancel: EventHandler<any>;
5
5
  title: string | React.ReactNode;
6
6
  message: string | React.ReactNode;
7
7
  confirm?: string | React.ReactNode;
8
- cancel?: string | React.ReactNode;
8
+ color?: string;
9
+ cancel?: boolean | string | React.ReactNode;
9
10
  loading?: boolean;
10
11
  }): import("react").JSX.Element;
11
12
  declare namespace ConfirmDialog {
@@ -13,6 +14,7 @@ declare namespace ConfirmDialog {
13
14
  loading: boolean;
14
15
  confirm: string;
15
16
  cancel: string;
17
+ color: string;
16
18
  };
17
19
  }
18
20
  export default ConfirmDialog;
@@ -8,6 +8,7 @@ export default function ConfirmDialog({
8
8
  title,
9
9
  message,
10
10
  confirm,
11
+ color,
11
12
  cancel,
12
13
  loading
13
14
  }) {
@@ -21,9 +22,10 @@ export default function ConfirmDialog({
21
22
  onCancel,
22
23
  confirmButton: {
23
24
  text: confirm || t("common.confirm"),
24
- props: { color: "error", size: "small", variant: "contained", disabled: !!loading }
25
+ props: { color, size: "small", variant: "contained", disabled: !!loading }
25
26
  },
26
27
  cancelButton: { text: cancel || t("common.cancel"), props: { color: "inherit", size: "small" } },
28
+ showCancelButton: typeof cancel !== "boolean" || !!cancel,
27
29
  children: /* @__PURE__ */ jsx(Typography, { children: message })
28
30
  }
29
31
  );
@@ -31,5 +33,6 @@ export default function ConfirmDialog({
31
33
  ConfirmDialog.defaultProps = {
32
34
  loading: false,
33
35
  confirm: "",
34
- cancel: ""
36
+ cancel: "",
37
+ color: "error"
35
38
  };
@@ -18,8 +18,8 @@ import {
18
18
  import { styled } from "@mui/system";
19
19
  import { useSetState } from "ahooks";
20
20
  import { useEffect, useState } from "react";
21
+ import { formatError, formatPriceAmount, formatRecurring } from "../libs/util.js";
21
22
  import Amount from "../payment/amount.js";
22
- import { formatError, formatPriceAmount, formatRecurring } from "../util.js";
23
23
  const groupItemsByRecurring = (items) => {
24
24
  const grouped = {};
25
25
  const recurring = {};
@@ -1,4 +1,4 @@
1
- import { PAYMENT_KIT_DID, isPaymentKitMounted } from "../util.js";
1
+ import { PAYMENT_KIT_DID, isPaymentKitMounted } from "../libs/util.js";
2
2
  export default function SafeGuard({ children }) {
3
3
  const mounted = isPaymentKitMounted();
4
4
  if (mounted === false) {
@@ -2,8 +2,8 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { Alert } from "@mui/material";
3
3
  import { useLocalStorageState, useRequest } from "ahooks";
4
4
  import { createContext, useContext } from "react";
5
- import api from "../api.js";
6
- import { getPrefix } from "../util.js";
5
+ import api from "../libs/api.js";
6
+ import { getPrefix } from "../libs/util.js";
7
7
  const prefix = getPrefix();
8
8
  const PaymentContext = createContext({ api });
9
9
  const { Provider, Consumer } = PaymentContext;
@@ -1,13 +1,25 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
3
+ import Toast from "@arcblock/ux/lib/Toast";
3
4
  import { OpenInNewOutlined } from "@mui/icons-material";
4
5
  import { Box, Button, CircularProgress, Hidden, Stack, Typography } from "@mui/material";
5
6
  import { styled } from "@mui/system";
6
- import { useInfiniteScroll } from "ahooks";
7
+ import { useInfiniteScroll, useSetState } from "ahooks";
8
+ import { useEffect } from "react";
7
9
  import { joinURL } from "ufo";
8
- import api from "../../api.js";
9
10
  import Status from "../../components/status.js";
10
- import { formatBNStr, formatToDate, formatToDatetime, getInvoiceStatusColor, getPrefix, getTxLink } from "../../util.js";
11
+ import { usePaymentContext } from "../../contexts/payment.js";
12
+ import { useSubscription } from "../../hooks/subscription.js";
13
+ import api from "../../libs/api.js";
14
+ import {
15
+ formatBNStr,
16
+ formatError,
17
+ formatToDate,
18
+ formatToDatetime,
19
+ getInvoiceStatusColor,
20
+ getPrefix,
21
+ getTxLink
22
+ } from "../../libs/util.js";
11
23
  const groupByDate = (items) => {
12
24
  const grouped = {};
13
25
  items.forEach((item) => {
@@ -32,6 +44,7 @@ const getInvoiceLink = (invoice, action) => {
32
44
  if (invoice.id.startsWith("in_")) {
33
45
  return {
34
46
  external: false,
47
+ connect: invoice.status === "uncollectible",
35
48
  url: joinURL(
36
49
  window.location.origin,
37
50
  getPrefix(),
@@ -41,6 +54,7 @@ const getInvoiceLink = (invoice, action) => {
41
54
  }
42
55
  return {
43
56
  external: true,
57
+ connect: false,
44
58
  url: getTxLink(invoice.paymentMethod, invoice.metadata?.payment_details).link
45
59
  };
46
60
  };
@@ -54,9 +68,12 @@ export default function CustomerInvoiceList({
54
68
  target,
55
69
  action
56
70
  }) {
57
- const { t, locale } = useLocaleContext();
58
71
  const size = pageSize || 10;
59
- const { data, loadMore, loadingMore, loading } = useInfiniteScroll(
72
+ const subscription = useSubscription("events");
73
+ const { t, locale } = useLocaleContext();
74
+ const { connect } = usePaymentContext();
75
+ const [state, setState] = useSetState({ paying: "" });
76
+ const { data, loadMore, loadingMore, loading, reloadAsync } = useInfiniteScroll(
60
77
  (d) => {
61
78
  const page = d ? Math.ceil(d.list.length / size) + 1 : 1;
62
79
  return fetchData({
@@ -71,9 +88,47 @@ export default function CustomerInvoiceList({
71
88
  });
72
89
  },
73
90
  {
74
- reloadDeps: [customer_id, subscription_id, status]
91
+ reloadDeps: [customer_id, subscription_id, status, include_staking]
75
92
  }
76
93
  );
94
+ useEffect(() => {
95
+ if (subscription && customer_id) {
96
+ subscription.on("invoice.paid", async ({ response }) => {
97
+ if (response.customer_id === customer_id) {
98
+ await reloadAsync();
99
+ }
100
+ });
101
+ }
102
+ }, [subscription]);
103
+ const onPay = (invoiceId) => {
104
+ if (state.paying) {
105
+ return;
106
+ }
107
+ setState({ paying: invoiceId });
108
+ connect.open({
109
+ action: "collect",
110
+ messages: {
111
+ scan: "",
112
+ title: t(`payment.customer.invoice.${action || "pay"}`),
113
+ success: t(`payment.customer.invoice.${action || "pay"}Success`),
114
+ error: t(`payment.customer.invoice.${action || "pay"}Error`),
115
+ confirm: ""
116
+ },
117
+ extraParams: { invoiceId, action },
118
+ onSuccess: () => {
119
+ connect.close();
120
+ setState({ paying: "" });
121
+ },
122
+ onClose: () => {
123
+ connect.close();
124
+ setState({ paying: "" });
125
+ },
126
+ onError: (err) => {
127
+ setState({ paying: "" });
128
+ Toast.error(formatError(err));
129
+ }
130
+ });
131
+ };
77
132
  if (loading || !data) {
78
133
  return /* @__PURE__ */ jsx(CircularProgress, {});
79
134
  }
@@ -114,7 +169,7 @@ export default function CustomerInvoiceList({
114
169
  ] }) }),
115
170
  /* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: /* @__PURE__ */ jsx(Typography, { children: formatToDate(invoice.created_at, locale, "HH:mm:ss") }) }),
116
171
  !action && /* @__PURE__ */ jsx(Hidden, { mdDown: true, children: /* @__PURE__ */ jsx(Box, { flex: 2, className: "invoice-description", textAlign: "right", children: /* @__PURE__ */ jsx(Typography, { children: invoice.description || invoice.id }) }) }),
117
- /* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: action ? /* @__PURE__ */ jsx(
172
+ /* @__PURE__ */ jsx(Box, { flex: 1, textAlign: "right", children: action ? link.connect ? /* @__PURE__ */ jsx(Button, { variant: "contained", color: "primary", size: "small", onClick: () => onPay(invoice.id), children: t("payment.customer.invoice.pay") }) : /* @__PURE__ */ jsx(
118
173
  Button,
119
174
  {
120
175
  component: "a",
@@ -154,9 +209,6 @@ const Root = styled(Stack)`
154
209
  .invoice-description {
155
210
  display: none !important;
156
211
  }
157
- svg[data-testid='OpenInNewOutlinedIcon'] {
158
- display: none !important;
159
- }
160
212
  }
161
213
 
162
214
  a.MuiButton-root {
@@ -14,9 +14,11 @@ import {
14
14
  Typography
15
15
  } from "@mui/material";
16
16
  import { useRequest } from "ahooks";
17
- import { joinURL } from "ufo";
18
- import api from "../../api.js";
17
+ import { useMemo } from "react";
18
+ import { joinURL, withQuery } from "ufo";
19
19
  import Status from "../../components/status.js";
20
+ import api from "../../libs/api.js";
21
+ import { getDidConnectQueryParams } from "../../libs/did-connect.js";
20
22
  import {
21
23
  formatBNStr,
22
24
  formatError,
@@ -26,7 +28,7 @@ import {
26
28
  getInvoiceStatusColor,
27
29
  getPrefix,
28
30
  getSubscriptionStatusColor
29
- } from "../../util.js";
31
+ } from "../../libs/util.js";
30
32
  const fetchInvoiceData = (params = {}) => {
31
33
  const search = new URLSearchParams();
32
34
  Object.keys(params).forEach((key) => {
@@ -57,6 +59,16 @@ export default function MiniInvoiceList() {
57
59
  include_staking: true
58
60
  })
59
61
  );
62
+ const subscriptionPageUrl = useMemo(() => {
63
+ if (!subscription) {
64
+ return "#";
65
+ }
66
+ const pageUrl = joinURL(window.location.origin, getPrefix(), `/customer/subscription/${subscription.id}`);
67
+ return withQuery(pageUrl, {
68
+ source: "embed",
69
+ ...getDidConnectQueryParams({ forceConnected: subscription.customer.did })
70
+ });
71
+ }, [subscription]);
60
72
  if (error) {
61
73
  return /* @__PURE__ */ jsx(Position, { children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: formatError(error) }) });
62
74
  }
@@ -152,11 +164,7 @@ export default function MiniInvoiceList() {
152
164
  variant: "contained",
153
165
  sx: { color: "#fff!important", width: subscription.service_actions?.length ? "auto" : "100%" },
154
166
  target: "_blank",
155
- href: joinURL(
156
- window.location.origin,
157
- getPrefix(),
158
- `/customer/subscription/${subscription.id}?source=embed`
159
- ),
167
+ href: subscriptionPageUrl,
160
168
  children: t("payment.customer.subscriptions.view")
161
169
  }
162
170
  )
@@ -2,10 +2,10 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
3
3
  import { Box, Button, CircularProgress, Stack, Typography } from "@mui/material";
4
4
  import { useInfiniteScroll } from "ahooks";
5
- import api from "../../api.js";
6
5
  import TxLink from "../../components/blockchain/tx.js";
7
6
  import Status from "../../components/status.js";
8
- import { formatBNStr, formatToDate, getPaymentIntentStatusColor } from "../../util.js";
7
+ import api from "../../libs/api.js";
8
+ import { formatBNStr, formatToDate, getPaymentIntentStatusColor } from "../../libs/util.js";
9
9
  const groupByDate = (items) => {
10
10
  const grouped = {};
11
11
  items.forEach((item) => {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @description channel 的值不能包含分隔符 / . : 等,否则前端接受不到事件
3
+ * @export
4
+ * @param {string} channel
5
+ * @return {*}
6
+ */
7
+ export declare function useSubscription(channel: string): any;
@@ -0,0 +1,55 @@
1
+ import { WsClient } from "@arcblock/ws";
2
+ import get from "lodash/get";
3
+ import { useEffect, useRef } from "react";
4
+ const RELAY_SOCKET_PREFIX = "/.well-known/service/relay";
5
+ const getAppId = () => get(window, "blocklet.appPid") || get(window, "blocklet.appId") || "";
6
+ const getRelayChannel = (token) => `relay:${getAppId()}:${token}`;
7
+ const getRelayProtocol = () => window.location.protocol === "https:" ? "wss:" : "ws:";
8
+ const getSocketHost = () => new URL(window.location.href).host;
9
+ export function useSubscription(channel) {
10
+ const socket = useRef(null);
11
+ const subscription = useRef(null);
12
+ useEffect(() => {
13
+ if (getAppId()) {
14
+ const needReconnect = !socket.current || socket.current.isConnected() === false;
15
+ if (needReconnect) {
16
+ socket.current = new WsClient(`${getRelayProtocol()}//${getSocketHost()}${RELAY_SOCKET_PREFIX}`, {
17
+ longpollerTimeout: 5e3,
18
+ // connection timeout
19
+ heartbeatIntervalMs: 30 * 1e3
20
+ });
21
+ socket.current.connect();
22
+ }
23
+ }
24
+ return () => {
25
+ if (socket.current) {
26
+ socket.current.disconnect();
27
+ socket.current = null;
28
+ }
29
+ };
30
+ }, []);
31
+ useEffect(() => {
32
+ if (channel) {
33
+ let needSubscription = false;
34
+ if (subscription.current) {
35
+ if (subscription.current.channel !== channel) {
36
+ socket.current?.unsubscribe(getRelayChannel(subscription.current.channel));
37
+ needSubscription = true;
38
+ }
39
+ } else {
40
+ needSubscription = true;
41
+ }
42
+ if (needSubscription) {
43
+ subscription.current = socket.current.subscribe(getRelayChannel(channel));
44
+ subscription.current.channel = channel;
45
+ }
46
+ }
47
+ return () => {
48
+ if (subscription.current) {
49
+ socket.current?.unsubscribe(getRelayChannel(subscription.current.channel));
50
+ subscription.current = null;
51
+ }
52
+ };
53
+ }, [channel]);
54
+ return subscription.current;
55
+ }
package/es/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import api from './api';
2
1
  import CheckoutDonate from './checkout/donate';
3
2
  import CheckoutForm from './checkout/form';
4
3
  import CheckoutTable from './checkout/table';
@@ -11,10 +10,11 @@ import PricingTable from './components/pricing-table';
11
10
  import SafeGuard from './components/safe-guard';
12
11
  import Status from './components/status';
13
12
  import Switch from './components/switch-button';
14
- import dayjs from './dayjs';
15
13
  import CustomerInvoiceList from './history/invoice/list';
16
14
  import MiniInvoiceList from './history/mini-invoice/list';
17
15
  import CustomerPaymentList from './history/payment/list';
16
+ import api from './libs/api';
17
+ import dayjs from './libs/dayjs';
18
18
  import Amount from './payment/amount';
19
19
  import AddressForm from './payment/form/address';
20
20
  import CurrencySelector from './payment/form/currency';
@@ -23,7 +23,8 @@ import StripeForm from './payment/form/stripe';
23
23
  import Payment from './payment/index';
24
24
  import ProductSkeleton from './payment/product-skeleton';
25
25
  import PaymentSummary from './payment/summary';
26
- export * from './util';
26
+ export * from './libs/util';
27
27
  export * from './contexts/payment';
28
+ export * from './hooks/subscription';
28
29
  export { translations, createTranslator } from './locales';
29
30
  export { api, dayjs, FormInput, PhoneInput, AddressForm, StripeForm, Status, Livemode, Switch, ConfirmDialog, CheckoutForm, CheckoutTable, CheckoutDonate, CurrencySelector, Payment, PaymentSummary, PricingTable, ProductSkeleton, Amount, CustomerInvoiceList, CustomerPaymentList, MiniInvoiceList, TxLink, TxGas, SafeGuard, };
package/es/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import api from "./api.js";
2
1
  import CheckoutDonate from "./checkout/donate.js";
3
2
  import CheckoutForm from "./checkout/form.js";
4
3
  import CheckoutTable from "./checkout/table.js";
@@ -11,10 +10,11 @@ import PricingTable from "./components/pricing-table.js";
11
10
  import SafeGuard from "./components/safe-guard.js";
12
11
  import Status from "./components/status.js";
13
12
  import Switch from "./components/switch-button.js";
14
- import dayjs from "./dayjs.js";
15
13
  import CustomerInvoiceList from "./history/invoice/list.js";
16
14
  import MiniInvoiceList from "./history/mini-invoice/list.js";
17
15
  import CustomerPaymentList from "./history/payment/list.js";
16
+ import api from "./libs/api.js";
17
+ import dayjs from "./libs/dayjs.js";
18
18
  import Amount from "./payment/amount.js";
19
19
  import AddressForm from "./payment/form/address.js";
20
20
  import CurrencySelector from "./payment/form/currency.js";
@@ -23,8 +23,9 @@ import StripeForm from "./payment/form/stripe.js";
23
23
  import Payment from "./payment/index.js";
24
24
  import ProductSkeleton from "./payment/product-skeleton.js";
25
25
  import PaymentSummary from "./payment/summary.js";
26
- export * from "./util.js";
26
+ export * from "./libs/util.js";
27
27
  export * from "./contexts/payment.js";
28
+ export * from "./hooks/subscription.js";
28
29
  export { translations, createTranslator } from "./locales/index.js";
29
30
  export {
30
31
  api,
@@ -7,9 +7,13 @@ api.interceptors.request.use(
7
7
  (config) => {
8
8
  const prefix = getPrefix();
9
9
  config.baseURL = prefix || "";
10
- const livemode = localStorage.getItem("livemode");
11
10
  const locale = getLocale(window.blocklet?.languages);
12
- config.params = { ...config.params || {}, livemode: isNull(livemode) ? true : JSON.parse(livemode), locale };
11
+ const query = new URLSearchParams(config.url?.split("?").pop());
12
+ config.params = { ...config.params || {}, locale };
13
+ if (typeof config.params.livemode === "undefined" && query.has("livemode") === false) {
14
+ const livemode = localStorage.getItem("livemode");
15
+ config.params.livemode = isNull(livemode) ? true : JSON.parse(livemode);
16
+ }
13
17
  return config;
14
18
  },
15
19
  (err) => Promise.reject(err)
@@ -0,0 +1,10 @@
1
+ export interface DIDConnectCustomQuery {
2
+ forceConnected: string;
3
+ sourceAppPid?: string;
4
+ switchBehavior?: 'auto' | 'disabled' | 'required';
5
+ showClose?: boolean;
6
+ }
7
+ declare function getDidConnectQueryParams(params: DIDConnectCustomQuery): {
8
+ '__did-connect__': string;
9
+ };
10
+ export { getDidConnectQueryParams };
@@ -0,0 +1,11 @@
1
+ function getDidConnectQueryParams(params) {
2
+ const didConnectQueryParams = {
3
+ switchBehavior: "auto",
4
+ showClose: false,
5
+ ...params
6
+ };
7
+ return {
8
+ "__did-connect__": Buffer.from(JSON.stringify(didConnectQueryParams), "utf8").toString("base64")
9
+ };
10
+ }
11
+ export { getDidConnectQueryParams };
@@ -2,7 +2,7 @@
2
2
  import type { PaymentDetails, PriceCurrency, PriceRecurring, TLineItemExpanded, TPaymentCurrency, TPaymentCurrencyExpanded, TPaymentMethod, TPaymentMethodExpanded, TPrice, TSubscriptionExpanded, TSubscriptionItemExpanded } from '@blocklet/payment-types';
3
3
  export declare const PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
4
4
  export declare const isPaymentKitMounted: () => any;
5
- export declare const getPrefix: () => any;
5
+ export declare const getPrefix: () => string;
6
6
  export declare function formatToDate(date: Date | string | number, locale?: string, format?: string): any;
7
7
  export declare function formatToDatetime(date: Date | string | number, locale?: string): any;
8
8
  export declare function formatTime(date: Date | string | number, format?: string, locale?: string): any;
@@ -4,8 +4,8 @@ import trimEnd from "lodash/trimEnd";
4
4
  import numbro from "numbro";
5
5
  import { defaultCountries } from "react-international-phone";
6
6
  import { joinURL } from "ufo";
7
+ import { t } from "../locales/index.js";
7
8
  import dayjs from "./dayjs.js";
8
- import { t } from "./locales/index.js";
9
9
  export const PAYMENT_KIT_DID = "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk";
10
10
  export const isPaymentKitMounted = () => {
11
11
  return (window.blocklet?.componentMountPoints || []).some((x) => x.did === PAYMENT_KIT_DID);
package/es/locales/en.js CHANGED
@@ -263,6 +263,7 @@ export default flat({
263
263
  title: "Manage subscriptions",
264
264
  view: "View Subscription",
265
265
  current: "Current subscription",
266
+ viewAll: "View all",
266
267
  empty: "There are no subscriptions here",
267
268
  changePayment: "Change payment method"
268
269
  }
package/es/locales/zh.js CHANGED
@@ -263,6 +263,7 @@ export default flat({
263
263
  title: "\u8BA2\u9605\u7BA1\u7406",
264
264
  view: "\u7BA1\u7406\u8BA2\u9605",
265
265
  current: "\u5F53\u524D\u8BA2\u9605",
266
+ viewAll: "\u67E5\u770B\u6240\u6709",
266
267
  empty: "\u6CA1\u6709\u4EFB\u4F55\u8BA2\u9605",
267
268
  changePayment: "\u5207\u6362\u652F\u4ED8\u65B9\u5F0F"
268
269
  }
@@ -13,11 +13,12 @@ import { Controller, useFormContext, useWatch } from "react-hook-form";
13
13
  import { joinURL } from "ufo";
14
14
  import { dispatch } from "use-bus";
15
15
  import isEmail from "validator/es/lib/isEmail";
16
- import api from "../../api.js";
17
16
  import ConfirmDialog from "../../components/confirm.js";
18
17
  import FormInput from "../../components/input.js";
19
18
  import { usePaymentContext } from "../../contexts/payment.js";
20
- import { flattenPaymentMethods, formatError, getPrefix, getStatementDescriptor } from "../../util.js";
19
+ import { useSubscription } from "../../hooks/subscription.js";
20
+ import api from "../../libs/api.js";
21
+ import { flattenPaymentMethods, formatError, getPrefix, getStatementDescriptor } from "../../libs/util.js";
21
22
  import UserButtons from "./addon.js";
22
23
  import AddressForm from "./address.js";
23
24
  import CurrencySelector from "./currency.js";
@@ -58,6 +59,7 @@ export default function PaymentForm({
58
59
  const theme = useTheme();
59
60
  const { t } = useLocaleContext();
60
61
  const { session, connect } = usePaymentContext();
62
+ const subscription = useSubscription("events");
61
63
  const { control, getValues, setValue, handleSubmit } = useFormContext();
62
64
  const [state, setState] = useSetState({
63
65
  submitting: false,
@@ -71,6 +73,22 @@ export default function PaymentForm({
71
73
  });
72
74
  const currencies = flattenPaymentMethods(paymentMethods);
73
75
  const [paymentCurrencyIndex, setPaymentCurrencyIndex] = useState(0);
76
+ const onCheckoutComplete = useMemoizedFn(async ({ response }) => {
77
+ if (response.id === checkoutSession.id && state.paid === false) {
78
+ await handleConnected();
79
+ }
80
+ });
81
+ const onInvoicePaid = useMemoizedFn(async ({ response }) => {
82
+ if (response.customer_id === customer?.id && state.customerLimited) {
83
+ await onAction();
84
+ }
85
+ });
86
+ useEffect(() => {
87
+ if (subscription) {
88
+ subscription.on("checkout.session.completed", onCheckoutComplete);
89
+ subscription.on("invoice.paid", onInvoicePaid);
90
+ }
91
+ }, [subscription]);
74
92
  useEffect(() => {
75
93
  if (session?.user) {
76
94
  const values = getValues();
@@ -126,8 +144,10 @@ export default function PaymentForm({
126
144
  const handleConnected = async () => {
127
145
  try {
128
146
  const result = await waitForCheckoutComplete(checkoutSession.id);
129
- setState({ paid: true, paying: false });
130
- onPaid(result);
147
+ if (state.paid === false) {
148
+ setState({ paid: true, paying: false });
149
+ onPaid(result);
150
+ }
131
151
  } catch (err) {
132
152
  Toast.error(formatError(err));
133
153
  } finally {
@@ -175,7 +195,8 @@ export default function PaymentForm({
175
195
  paymentIntent: result.data.paymentIntent,
176
196
  stripeContext: result.data.stripeContext,
177
197
  customer: result.data.customer,
178
- submitting: false
198
+ submitting: false,
199
+ customerLimited: false
179
200
  });
180
201
  if (["arcblock", "ethereum"].includes(method.type)) {
181
202
  setState({ paying: true });
@@ -380,7 +401,8 @@ export default function PaymentForm({
380
401
  onCancel: () => setState({ customerLimited: false }),
381
402
  confirm: t("payment.customer.pastDue.alert.confirm"),
382
403
  title: t("payment.customer.pastDue.alert.title"),
383
- message: t("payment.customer.pastDue.alert.description")
404
+ message: t("payment.customer.pastDue.alert.description"),
405
+ color: "primary"
384
406
  }
385
407
  )
386
408
  ] });
@@ -5,7 +5,7 @@ import { useEffect } from "react";
5
5
  import { useFormContext, useWatch } from "react-hook-form";
6
6
  import { FlagEmoji, defaultCountries, parseCountry, usePhoneInput } from "react-international-phone";
7
7
  import FormInput from "../../components/input.js";
8
- import { isValidCountry } from "../../util.js";
8
+ import { isValidCountry } from "../../libs/util.js";
9
9
  export default function PhoneInput({ ...props }) {
10
10
  const countryFieldName = props.countryFieldName || "billing_address.country";
11
11
  const { control, getValues, setValue } = useFormContext();