payment-kit 1.17.4 → 1.17.5

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 (58) hide show
  1. package/api/src/crons/currency.ts +1 -1
  2. package/api/src/integrations/arcblock/stake.ts +4 -3
  3. package/api/src/libs/constants.ts +3 -0
  4. package/api/src/libs/invoice.ts +6 -5
  5. package/api/src/libs/notification/template/subscription-renew-failed.ts +4 -3
  6. package/api/src/libs/notification/template/subscription-renewed.ts +4 -3
  7. package/api/src/libs/notification/template/subscription-succeeded.ts +4 -3
  8. package/api/src/libs/notification/template/subscription-trial-start.ts +11 -3
  9. package/api/src/libs/notification/template/subscription-upgraded.ts +2 -1
  10. package/api/src/libs/payment.ts +5 -4
  11. package/api/src/libs/product.ts +24 -1
  12. package/api/src/queues/payment.ts +7 -5
  13. package/api/src/queues/refund.ts +8 -6
  14. package/api/src/routes/connect/change-payment.ts +3 -2
  15. package/api/src/routes/connect/change-plan.ts +3 -2
  16. package/api/src/routes/connect/collect-batch.ts +5 -4
  17. package/api/src/routes/connect/collect.ts +6 -5
  18. package/api/src/routes/connect/pay.ts +9 -4
  19. package/api/src/routes/connect/recharge.ts +9 -4
  20. package/api/src/routes/connect/setup.ts +3 -2
  21. package/api/src/routes/connect/shared.ts +25 -7
  22. package/api/src/routes/connect/subscribe.ts +3 -2
  23. package/api/src/routes/payment-currencies.ts +11 -10
  24. package/api/src/routes/payment-methods.ts +35 -19
  25. package/api/src/routes/payment-stats.ts +9 -3
  26. package/api/src/routes/prices.ts +19 -1
  27. package/api/src/routes/products.ts +60 -28
  28. package/api/src/routes/subscriptions.ts +4 -3
  29. package/api/src/store/models/payment-method.ts +11 -8
  30. package/api/src/store/models/types.ts +27 -1
  31. package/blocklet.yml +1 -1
  32. package/package.json +19 -19
  33. package/public/methods/base.png +0 -0
  34. package/src/components/payment-method/base.tsx +79 -0
  35. package/src/components/payment-method/form.tsx +3 -0
  36. package/src/components/price/upsell-select.tsx +1 -0
  37. package/src/components/subscription/metrics.tsx +1 -1
  38. package/src/components/subscription/portal/actions.tsx +1 -1
  39. package/src/libs/util.ts +1 -1
  40. package/src/locales/en.tsx +25 -0
  41. package/src/locales/zh.tsx +24 -0
  42. package/src/pages/admin/billing/invoices/detail.tsx +1 -1
  43. package/src/pages/admin/customers/customers/detail.tsx +2 -2
  44. package/src/pages/admin/overview.tsx +15 -2
  45. package/src/pages/admin/payments/intents/detail.tsx +1 -1
  46. package/src/pages/admin/payments/payouts/detail.tsx +1 -1
  47. package/src/pages/admin/payments/refunds/detail.tsx +1 -1
  48. package/src/pages/admin/products/links/detail.tsx +1 -0
  49. package/src/pages/admin/products/prices/actions.tsx +2 -1
  50. package/src/pages/admin/products/prices/detail.tsx +1 -0
  51. package/src/pages/admin/products/products/detail.tsx +1 -0
  52. package/src/pages/admin/settings/payment-methods/create.tsx +7 -0
  53. package/src/pages/admin/settings/payment-methods/index.tsx +99 -11
  54. package/src/pages/customer/index.tsx +1 -1
  55. package/src/pages/customer/invoice/detail.tsx +1 -1
  56. package/src/pages/customer/recharge.tsx +1 -1
  57. package/src/pages/customer/refund/list.tsx +7 -3
  58. package/src/pages/customer/subscription/change-payment.tsx +1 -1
@@ -1,7 +1,15 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Switch, api, formatError } from '@blocklet/payment-react';
2
+ import { Switch, api, formatError, usePaymentContext } from '@blocklet/payment-react';
3
3
  import type { TPaymentMethodExpanded } from '@blocklet/payment-types';
4
- import { AddOutlined, Check, Close, DeleteOutlined, EditOutlined } from '@mui/icons-material';
4
+ import {
5
+ AddOutlined,
6
+ Check,
7
+ Close,
8
+ DeleteOutlined,
9
+ EditOutlined,
10
+ InfoOutlined,
11
+ QrCodeOutlined,
12
+ } from '@mui/icons-material';
5
13
  import {
6
14
  Alert,
7
15
  Avatar,
@@ -15,6 +23,7 @@ import {
15
23
  ListItemText,
16
24
  Stack,
17
25
  TextField,
26
+ Tooltip,
18
27
  Typography,
19
28
  } from '@mui/material';
20
29
  import { useRequest, useSetState } from 'ahooks';
@@ -22,12 +31,15 @@ import useBus from 'use-bus';
22
31
 
23
32
  import { useState } from 'react';
24
33
  import Toast from '@arcblock/ux/lib/Toast';
34
+ import { DIDDialog } from '@arcblock/ux/lib/DID';
25
35
  import IconCollapse from '../../../../components/collapse';
26
36
  import InfoCard from '../../../../components/info-card';
27
37
  import InfoRow from '../../../../components/info-row';
28
38
  import PaymentCurrencyAdd from '../../../../components/payment-currency/add';
29
39
 
30
- const getMethods = (params: Record<string, any> = {}): Promise<TPaymentMethodExpanded[]> => {
40
+ const getMethods = (
41
+ params: Record<string, any> = {}
42
+ ): Promise<{ list: TPaymentMethodExpanded[]; addresses: { arcblock: string; ethereum: string } }> => {
31
43
  const search = new URLSearchParams();
32
44
  Object.keys(params).forEach((key) => {
33
45
  search.set(key, String(params[key]));
@@ -132,29 +144,97 @@ const groupByType = (methods: TPaymentMethodExpanded[]) => {
132
144
 
133
145
  export default function PaymentMethods() {
134
146
  const { t } = useLocaleContext();
135
- const { loading, error, data, runAsync } = useRequest(() => getMethods({}));
147
+ const {
148
+ loading,
149
+ error,
150
+ data = { list: [], addresses: {} } as any,
151
+ runAsync,
152
+ } = useRequest(() =>
153
+ getMethods({
154
+ addresses: true,
155
+ })
156
+ );
136
157
  const [state, setState] = useSetState({ method: '' });
158
+ const [didDialog, setDidDialog] = useSetState({ open: false, chainId: '', did: '' });
159
+ const { refresh } = usePaymentContext();
137
160
 
138
- useBus('paymentMethod.created', runAsync, []);
139
- useBus('paymentCurrency.added', () => runAsync().then(() => setState({ method: '' })), []);
161
+ const { list: methods, addresses } = data;
162
+ useBus(
163
+ 'paymentMethod.created',
164
+ () => {
165
+ runAsync();
166
+ refresh(true);
167
+ },
168
+ []
169
+ );
170
+ useBus(
171
+ 'paymentCurrency.added',
172
+ () => {
173
+ runAsync().then(() => setState({ method: '' }));
174
+ refresh(true);
175
+ },
176
+ []
177
+ );
140
178
 
141
179
  if (error) {
142
180
  return <Alert severity="error">{error.message}</Alert>;
143
181
  }
144
182
 
145
- if (loading || !data) {
183
+ if (loading || !data || methods?.length === 0) {
146
184
  return <CircularProgress />;
147
185
  }
148
186
 
149
- const groups = groupByType(data);
187
+ const groups = groupByType(methods);
150
188
 
189
+ const getAddress = (type: string) => {
190
+ if (['ethereum', 'base'].includes(type)) {
191
+ return addresses?.ethereum || '';
192
+ }
193
+ return addresses?.arcblock || '';
194
+ };
151
195
  return (
152
196
  <>
153
197
  {Object.keys(groups).map((x) => (
154
198
  <Box key={x} mt={3}>
155
- <Typography variant="h6" sx={{ mb: 1, textTransform: 'uppercase' }}>
156
- {x}
157
- </Typography>
199
+ <Stack direction="row" alignItems="center" mb={1}>
200
+ <Typography variant="h6" sx={{ textTransform: 'uppercase' }}>
201
+ {x}
202
+ </Typography>
203
+ {['ethereum', 'base'].includes(x) && (
204
+ <Stack
205
+ direction="row"
206
+ alignItems="center"
207
+ spacing={0.5}
208
+ sx={{
209
+ ml: 1,
210
+ px: 0.5,
211
+ color: 'text.secondary',
212
+ }}>
213
+ <InfoOutlined sx={{ fontSize: 16 }} color="warning" />
214
+ <Typography variant="body2">
215
+ {t('admin.paymentMethod.gasTip', {
216
+ method: x,
217
+ address: '222',
218
+ chain: groups[x]?.[0]?.name || x,
219
+ })}
220
+ </Typography>
221
+ <Tooltip title={t('admin.paymentMethod.showQR')}>
222
+ <IconButton
223
+ size="small"
224
+ onClick={() =>
225
+ setDidDialog({
226
+ open: true,
227
+ chainId: groups[x]?.[0]?.id || '',
228
+ did: getAddress(x),
229
+ })
230
+ }
231
+ sx={{ p: 0.5 }}>
232
+ <QrCodeOutlined sx={{ fontSize: 16 }} />
233
+ </IconButton>
234
+ </Tooltip>
235
+ </Stack>
236
+ )}
237
+ </Stack>
158
238
  {(groups[x] as TPaymentMethodExpanded[]).map((method) => (
159
239
  <IconCollapse
160
240
  key={method.id}
@@ -231,6 +311,14 @@ export default function PaymentMethods() {
231
311
  ))}
232
312
  </Box>
233
313
  ))}
314
+ {didDialog.open && didDialog.did && (
315
+ <DIDDialog
316
+ open={didDialog.open}
317
+ onClose={() => setDidDialog({ open: false, chainId: '', did: '' })}
318
+ did={didDialog.did}
319
+ chainId={didDialog.chainId}
320
+ />
321
+ )}
234
322
  </>
235
323
  );
236
324
  }
@@ -360,7 +360,7 @@ export default function CustomerHome() {
360
360
  {data.name}
361
361
  </Typography>
362
362
  <Typography variant="body2" color="text.secondary">
363
- <DID did={data.did} copyable showQrcode />
363
+ <DID did={data.did} copyable showQrcode chainId={livemode ? 'main' : 'beta'} />
364
364
  </Typography>
365
365
  </Box>
366
366
  </Box>
@@ -268,7 +268,7 @@ export default function CustomerInvoiceDetail() {
268
268
  direction={InfoDirection}
269
269
  alignItems={InfoAlignItems}
270
270
  />
271
- {!!data.paymentIntent?.payment_details?.ethereum && (
271
+ {(!!data.paymentIntent?.payment_details?.ethereum || !!data.paymentIntent?.payment_details?.base) && (
272
272
  <InfoRow
273
273
  label={t('common.txGas')}
274
274
  value={<TxGas details={data.paymentIntent.payment_details as any} method={data.paymentMethod} />}
@@ -217,7 +217,7 @@ export default function RechargePage() {
217
217
  }
218
218
  const currentBalance = formatBNStr(payerValue?.token || '0', paymentCurrency?.decimal, 6, false);
219
219
 
220
- const supportRecharge = ['arcblock', 'ethereum'].includes(paymentMethod?.type || '');
220
+ const supportRecharge = ['arcblock', 'ethereum', 'base'].includes(paymentMethod?.type || '');
221
221
 
222
222
  const formatEstimatedDuration = (cycles: number) => {
223
223
  const { interval, interval_count: intervalCount } = subscription.pending_invoice_item_interval;
@@ -142,14 +142,16 @@ const RefundTable = memo(({ invoice_id }: Props) => {
142
142
  options: {
143
143
  customBodyRenderLite: (_: string, index: number) => {
144
144
  const item = data.list[index] as TRefundExpanded;
145
- return item.payment_details?.arcblock?.tx_hash || item.payment_details?.ethereum?.tx_hash ? (
145
+ const paymentDetails = item.payment_details as Record<string, { tx_hash?: string }>;
146
+ const txHash = ['arcblock', 'ethereum', 'base'].map((key) => !!paymentDetails?.[key]?.tx_hash).find(Boolean);
147
+ return txHash ? (
146
148
  <Box
147
149
  sx={{
148
150
  '.MuiTypography-root': {
149
151
  color: 'text.link',
150
152
  },
151
153
  }}>
152
- <TxLink details={item.payment_details} method={item.paymentMethod} mode="customer" />
154
+ <TxLink details={paymentDetails} method={item.paymentMethod} mode="customer" />
153
155
  </Box>
154
156
  ) : (
155
157
  t('common.none')
@@ -271,7 +273,9 @@ const RefundList = memo(({ invoice_id }: Props) => {
271
273
  </Typography>
272
274
  </Box>
273
275
  <Box flex={3} sx={{ minWidth: '220px' }}>
274
- {(item.payment_details?.arcblock?.tx_hash || item.payment_details?.ethereum?.tx_hash) && (
276
+ {(item.payment_details?.arcblock?.tx_hash ||
277
+ item.payment_details?.ethereum?.tx_hash ||
278
+ item.payment_details?.base?.tx_hash) && (
275
279
  <TxLink details={item.payment_details} method={item.paymentMethod} mode="customer" />
276
280
  )}
277
281
  </Box>
@@ -153,7 +153,7 @@ function CustomerSubscriptionChangePayment({ subscription, customer, onComplete
153
153
  submitting: false,
154
154
  });
155
155
 
156
- if (['arcblock', 'ethereum'].includes(method.type)) {
156
+ if (['arcblock', 'ethereum', 'base'].includes(method.type)) {
157
157
  setState({ paying: true });
158
158
  if (result.data.delegation?.sufficient) {
159
159
  await handleConnected();