payment-kit 1.21.16 → 1.22.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.
- package/api/src/index.ts +3 -1
- package/api/src/integrations/blocklet/user.ts +2 -2
- package/api/src/integrations/ethereum/token.ts +4 -5
- package/api/src/integrations/stripe/handlers/invoice.ts +31 -26
- package/api/src/integrations/stripe/handlers/payment-intent.ts +1 -1
- package/api/src/integrations/stripe/handlers/setup-intent.ts +231 -0
- package/api/src/integrations/stripe/handlers/subscription.ts +31 -9
- package/api/src/integrations/stripe/resource.ts +30 -1
- package/api/src/integrations/stripe/setup.ts +1 -1
- package/api/src/libs/auth.ts +7 -6
- package/api/src/libs/env.ts +1 -1
- package/api/src/libs/notification/template/subscription-trial-will-end.ts +1 -0
- package/api/src/libs/notification/template/subscription-will-renew.ts +1 -1
- package/api/src/libs/payment.ts +11 -6
- package/api/src/libs/refund.ts +1 -1
- package/api/src/libs/remote-signer.ts +93 -0
- package/api/src/libs/security.ts +1 -1
- package/api/src/libs/subscription.ts +4 -7
- package/api/src/libs/util.ts +18 -1
- package/api/src/libs/vendor-util/adapters/didnames-adapter.ts +17 -9
- package/api/src/libs/vendor-util/adapters/launcher-adapter.ts +11 -6
- package/api/src/queues/payment.ts +2 -2
- package/api/src/queues/payout.ts +1 -1
- package/api/src/queues/refund.ts +2 -2
- package/api/src/queues/subscription.ts +1 -1
- package/api/src/queues/usage-record.ts +1 -1
- package/api/src/queues/vendors/status-check.ts +1 -1
- package/api/src/queues/webhook.ts +1 -1
- package/api/src/routes/auto-recharge-configs.ts +1 -1
- package/api/src/routes/checkout-sessions.ts +4 -6
- package/api/src/routes/connect/change-payer.ts +148 -0
- package/api/src/routes/connect/collect-batch.ts +1 -1
- package/api/src/routes/connect/collect.ts +1 -1
- package/api/src/routes/connect/pay.ts +1 -1
- package/api/src/routes/connect/recharge-account.ts +1 -1
- package/api/src/routes/connect/recharge.ts +1 -1
- package/api/src/routes/connect/shared.ts +62 -23
- package/api/src/routes/customers.ts +1 -1
- package/api/src/routes/integrations/stripe.ts +1 -1
- package/api/src/routes/invoices.ts +141 -2
- package/api/src/routes/meter-events.ts +9 -12
- package/api/src/routes/payment-currencies.ts +1 -1
- package/api/src/routes/payment-intents.ts +2 -2
- package/api/src/routes/payment-links.ts +2 -1
- package/api/src/routes/payouts.ts +1 -1
- package/api/src/routes/products.ts +1 -0
- package/api/src/routes/subscriptions.ts +130 -3
- package/api/src/store/models/types.ts +1 -1
- package/api/tests/setup.ts +11 -0
- package/api/third.d.ts +0 -2
- package/blocklet.yml +1 -1
- package/jest.config.js +2 -2
- package/package.json +26 -26
- package/src/components/invoice/table.tsx +2 -2
- package/src/components/invoice-pdf/template.tsx +30 -0
- package/src/components/subscription/payment-method-info.tsx +222 -0
- package/src/global.css +4 -0
- package/src/libs/util.ts +1 -1
- package/src/locales/en.tsx +13 -0
- package/src/locales/zh.tsx +13 -0
- package/src/pages/admin/billing/invoices/detail.tsx +5 -3
- package/src/pages/admin/billing/subscriptions/detail.tsx +16 -0
- package/src/pages/admin/overview.tsx +14 -14
- package/src/pages/customer/invoice/detail.tsx +59 -17
- package/src/pages/customer/subscription/detail.tsx +21 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "blocklet dev --open",
|
|
6
6
|
"lint": "tsc --noEmit && eslint src api/src --ext .mjs,.js,.jsx,.ts,.tsx",
|
|
@@ -44,34 +44,34 @@
|
|
|
44
44
|
]
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@abtnode/cron": "^1.16.
|
|
48
|
-
"@arcblock/did": "^1.
|
|
49
|
-
"@arcblock/did-connect-react": "^3.1.
|
|
47
|
+
"@abtnode/cron": "^1.16.54-beta-20251028-092308-569763e6",
|
|
48
|
+
"@arcblock/did": "^1.26.3",
|
|
49
|
+
"@arcblock/did-connect-react": "^3.1.52",
|
|
50
50
|
"@arcblock/did-connect-storage-nedb": "^1.8.0",
|
|
51
|
-
"@arcblock/did-util": "^1.
|
|
52
|
-
"@arcblock/jwt": "^1.
|
|
53
|
-
"@arcblock/ux": "^3.1.
|
|
54
|
-
"@arcblock/validator": "^1.
|
|
55
|
-
"@blocklet/did-space-js": "^1.1.
|
|
51
|
+
"@arcblock/did-util": "^1.26.3",
|
|
52
|
+
"@arcblock/jwt": "^1.26.3",
|
|
53
|
+
"@arcblock/ux": "^3.1.52",
|
|
54
|
+
"@arcblock/validator": "^1.26.3",
|
|
55
|
+
"@blocklet/did-space-js": "^1.1.35",
|
|
56
56
|
"@blocklet/error": "^0.2.5",
|
|
57
|
-
"@blocklet/js-sdk": "^1.16.
|
|
58
|
-
"@blocklet/logger": "^1.16.
|
|
59
|
-
"@blocklet/payment-broker-client": "1.
|
|
60
|
-
"@blocklet/payment-react": "1.
|
|
61
|
-
"@blocklet/payment-vendor": "1.
|
|
62
|
-
"@blocklet/sdk": "^1.16.
|
|
63
|
-
"@blocklet/ui-react": "^3.1.
|
|
64
|
-
"@blocklet/uploader": "^0.
|
|
65
|
-
"@blocklet/xss": "^0.
|
|
57
|
+
"@blocklet/js-sdk": "^1.16.54-beta-20251028-092308-569763e6",
|
|
58
|
+
"@blocklet/logger": "^1.16.54-beta-20251028-092308-569763e6",
|
|
59
|
+
"@blocklet/payment-broker-client": "1.22.0",
|
|
60
|
+
"@blocklet/payment-react": "1.22.0",
|
|
61
|
+
"@blocklet/payment-vendor": "1.22.0",
|
|
62
|
+
"@blocklet/sdk": "^1.16.54-beta-20251028-092308-569763e6",
|
|
63
|
+
"@blocklet/ui-react": "^3.1.52",
|
|
64
|
+
"@blocklet/uploader": "^0.3.1",
|
|
65
|
+
"@blocklet/xss": "^0.3.1",
|
|
66
66
|
"@mui/icons-material": "^7.1.2",
|
|
67
67
|
"@mui/lab": "7.0.0-beta.14",
|
|
68
68
|
"@mui/material": "^7.1.2",
|
|
69
69
|
"@mui/system": "^7.1.1",
|
|
70
|
-
"@ocap/asset": "^1.
|
|
71
|
-
"@ocap/client": "^1.
|
|
72
|
-
"@ocap/mcrypto": "^1.
|
|
73
|
-
"@ocap/util": "^1.
|
|
74
|
-
"@ocap/wallet": "^1.
|
|
70
|
+
"@ocap/asset": "^1.26.3",
|
|
71
|
+
"@ocap/client": "^1.26.3",
|
|
72
|
+
"@ocap/mcrypto": "^1.26.3",
|
|
73
|
+
"@ocap/util": "^1.26.3",
|
|
74
|
+
"@ocap/wallet": "^1.26.3",
|
|
75
75
|
"@stripe/react-stripe-js": "^2.9.0",
|
|
76
76
|
"@stripe/stripe-js": "^2.4.0",
|
|
77
77
|
"ahooks": "^3.8.5",
|
|
@@ -126,9 +126,9 @@
|
|
|
126
126
|
"web3": "^4.16.0"
|
|
127
127
|
},
|
|
128
128
|
"devDependencies": {
|
|
129
|
-
"@abtnode/types": "^1.16.
|
|
129
|
+
"@abtnode/types": "^1.16.54-beta-20251028-092308-569763e6",
|
|
130
130
|
"@arcblock/eslint-config-ts": "^0.3.3",
|
|
131
|
-
"@blocklet/payment-types": "1.
|
|
131
|
+
"@blocklet/payment-types": "1.22.0",
|
|
132
132
|
"@types/cookie-parser": "^1.4.9",
|
|
133
133
|
"@types/cors": "^2.8.19",
|
|
134
134
|
"@types/debug": "^4.1.12",
|
|
@@ -175,5 +175,5 @@
|
|
|
175
175
|
"parser": "typescript"
|
|
176
176
|
}
|
|
177
177
|
},
|
|
178
|
-
"gitHead": "
|
|
178
|
+
"gitHead": "d69619c7d669bc6de8620273ff0f3f7b5d56383f"
|
|
179
179
|
}
|
|
@@ -56,9 +56,9 @@ export function getAppliedBalance(invoice: TInvoiceExpanded) {
|
|
|
56
56
|
invoice.ending_token_balance &&
|
|
57
57
|
invoice.ending_token_balance[invoice.paymentCurrency.id]
|
|
58
58
|
) {
|
|
59
|
-
const starting = toBN(invoice.starting_token_balance[invoice.paymentCurrency.id]);
|
|
59
|
+
const starting = toBN(invoice.starting_token_balance[invoice.paymentCurrency.id] || '0');
|
|
60
60
|
|
|
61
|
-
const ending = toBN(invoice.ending_token_balance[invoice.paymentCurrency.id]);
|
|
61
|
+
const ending = toBN(invoice.ending_token_balance[invoice.paymentCurrency.id] || '0');
|
|
62
62
|
return ending.sub(starting).toString();
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -65,6 +65,16 @@ export function InvoiceTemplate({ data, t }: InvoicePDFProps) {
|
|
|
65
65
|
<span style={composeStyles('gray')}>{formatTime(data.period_end * 1000)}</span>
|
|
66
66
|
</div>
|
|
67
67
|
</div>
|
|
68
|
+
<div style={composeStyles('flex mb-5')}>
|
|
69
|
+
<div style={composeStyles('w-40')}>
|
|
70
|
+
<span style={composeStyles('bold')}>{t('admin.paymentCurrency.name')}</span>
|
|
71
|
+
</div>
|
|
72
|
+
<div style={composeStyles('w-60')}>
|
|
73
|
+
<span style={composeStyles('gray')}>
|
|
74
|
+
{data.paymentCurrency.symbol} ({data.paymentMethod.name})
|
|
75
|
+
</span>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
68
78
|
</div>
|
|
69
79
|
</div>
|
|
70
80
|
|
|
@@ -137,6 +147,26 @@ export function InvoiceTemplate({ data, t }: InvoicePDFProps) {
|
|
|
137
147
|
);
|
|
138
148
|
})}
|
|
139
149
|
|
|
150
|
+
{detail.length === 0 && (
|
|
151
|
+
<div style={composeStyles('row flex')}>
|
|
152
|
+
<div style={composeStyles('w-38 p-4-8 pb-15')}>
|
|
153
|
+
<span style={composeStyles('gray')}>-</span>
|
|
154
|
+
</div>
|
|
155
|
+
<div style={composeStyles('w-15 p-4-8 pb-15')}>
|
|
156
|
+
<span style={composeStyles('gray right')}>-</span>
|
|
157
|
+
</div>
|
|
158
|
+
<div style={composeStyles('w-15 p-4-8 pb-15')}>
|
|
159
|
+
<span style={composeStyles('gray right')}>-</span>
|
|
160
|
+
</div>
|
|
161
|
+
<div style={composeStyles('w-15 p-4-8 pb-15')}>
|
|
162
|
+
<span style={composeStyles('gray right')}>-</span>
|
|
163
|
+
</div>
|
|
164
|
+
<div style={composeStyles('w-17 p-4-8 pb-15')}>
|
|
165
|
+
<span style={composeStyles('gray right')}>-</span>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
)}
|
|
169
|
+
|
|
140
170
|
{/* Summary */}
|
|
141
171
|
<div
|
|
142
172
|
style={{
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { Button } from '@arcblock/ux';
|
|
2
|
+
import DID from '@arcblock/ux/lib/DID';
|
|
3
|
+
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
4
|
+
import Toast from '@arcblock/ux/lib/Toast';
|
|
5
|
+
import { StripeForm, api, formatError, usePaymentContext } from '@blocklet/payment-react';
|
|
6
|
+
import type { TCustomer } from '@blocklet/payment-types';
|
|
7
|
+
import { CreditCard, Email, AccountBalance } from '@mui/icons-material';
|
|
8
|
+
import { Box, Stack, Typography } from '@mui/material';
|
|
9
|
+
import { useSetState } from 'ahooks';
|
|
10
|
+
import { useEffect } from 'react';
|
|
11
|
+
|
|
12
|
+
interface PaymentMethodData {
|
|
13
|
+
id?: string;
|
|
14
|
+
type: string;
|
|
15
|
+
// Stripe payment methods
|
|
16
|
+
card?: {
|
|
17
|
+
brand: string;
|
|
18
|
+
last4: string;
|
|
19
|
+
exp_month: number;
|
|
20
|
+
exp_year: number;
|
|
21
|
+
};
|
|
22
|
+
link?: {
|
|
23
|
+
email: string;
|
|
24
|
+
};
|
|
25
|
+
us_bank_account?: {
|
|
26
|
+
account_type: string;
|
|
27
|
+
bank_name: string;
|
|
28
|
+
last4: string;
|
|
29
|
+
};
|
|
30
|
+
billing_details?: {
|
|
31
|
+
name?: string;
|
|
32
|
+
email?: string;
|
|
33
|
+
phone?: string;
|
|
34
|
+
};
|
|
35
|
+
// On-chain payment methods (arcblock/ethereum/base)
|
|
36
|
+
payer?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface Props {
|
|
40
|
+
subscriptionId: string;
|
|
41
|
+
customer: TCustomer;
|
|
42
|
+
paymentMethodDetails: PaymentMethodData | null;
|
|
43
|
+
editable?: boolean;
|
|
44
|
+
paymentMethodType: string;
|
|
45
|
+
onUpdate?: () => void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default function PaymentMethodInfo({
|
|
49
|
+
subscriptionId,
|
|
50
|
+
customer,
|
|
51
|
+
paymentMethodDetails,
|
|
52
|
+
editable = false,
|
|
53
|
+
onUpdate = () => {},
|
|
54
|
+
paymentMethodType,
|
|
55
|
+
}: Props) {
|
|
56
|
+
const { t, locale } = useLocaleContext();
|
|
57
|
+
const { connect } = usePaymentContext();
|
|
58
|
+
|
|
59
|
+
const [state, setState] = useSetState<{
|
|
60
|
+
editing: boolean;
|
|
61
|
+
submitting: boolean;
|
|
62
|
+
setupIntentId: string | null;
|
|
63
|
+
clientSecret: string | null;
|
|
64
|
+
publishableKey: string | null;
|
|
65
|
+
}>({
|
|
66
|
+
editing: false,
|
|
67
|
+
submitting: false,
|
|
68
|
+
setupIntentId: null,
|
|
69
|
+
clientSecret: null,
|
|
70
|
+
publishableKey: null,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (!state.editing) {
|
|
75
|
+
setState({ clientSecret: null, publishableKey: null, setupIntentId: null });
|
|
76
|
+
}
|
|
77
|
+
}, [state.editing, setState]);
|
|
78
|
+
|
|
79
|
+
const handleEdit = async () => {
|
|
80
|
+
if (paymentMethodType === 'stripe') {
|
|
81
|
+
try {
|
|
82
|
+
setState({ submitting: true });
|
|
83
|
+
const { data } = await api.post(`/api/subscriptions/${subscriptionId}/update-stripe-payment-method`);
|
|
84
|
+
setState({
|
|
85
|
+
editing: true,
|
|
86
|
+
clientSecret: data.client_secret,
|
|
87
|
+
publishableKey: data.publishable_key,
|
|
88
|
+
setupIntentId: data.setup_intent_id,
|
|
89
|
+
submitting: false,
|
|
90
|
+
});
|
|
91
|
+
} catch (err) {
|
|
92
|
+
Toast.error(formatError(err));
|
|
93
|
+
setState({ submitting: false });
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
connect.open({
|
|
97
|
+
action: 'change-payer',
|
|
98
|
+
saveConnect: false,
|
|
99
|
+
locale: locale as 'en' | 'zh',
|
|
100
|
+
useSocket: true,
|
|
101
|
+
messages: {
|
|
102
|
+
scan: '',
|
|
103
|
+
title: t('admin.subscription.changePayer.connect.title'),
|
|
104
|
+
success: t('admin.subscription.changePayer.connect.success'),
|
|
105
|
+
error: t('admin.subscription.changePayer.connect.error'),
|
|
106
|
+
confirm: '',
|
|
107
|
+
} as any,
|
|
108
|
+
extraParams: { subscriptionId },
|
|
109
|
+
onSuccess: () => {
|
|
110
|
+
connect.close();
|
|
111
|
+
Toast.success(t('admin.subscription.changePayer.connect.success'));
|
|
112
|
+
onUpdate?.();
|
|
113
|
+
},
|
|
114
|
+
onClose: () => {
|
|
115
|
+
connect.close();
|
|
116
|
+
},
|
|
117
|
+
onError: (err: any) => {
|
|
118
|
+
Toast.error(formatError(err));
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const handleConfirm = () => {
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
Toast.success(t('admin.subscription.changePayer.connect.success'));
|
|
127
|
+
setState({ editing: false, submitting: false });
|
|
128
|
+
onUpdate?.();
|
|
129
|
+
}, 2000);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const handleCancel = () => {
|
|
133
|
+
setState({ editing: false, clientSecret: null, publishableKey: null, setupIntentId: null });
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
if (!paymentMethodDetails) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const { card, link, us_bank_account: usBankAccount, payer, type } = paymentMethodDetails;
|
|
141
|
+
|
|
142
|
+
if (state.editing && state.clientSecret && state.publishableKey) {
|
|
143
|
+
return (
|
|
144
|
+
<Box>
|
|
145
|
+
<StripeForm
|
|
146
|
+
clientSecret={state.clientSecret}
|
|
147
|
+
intentType="setup_intent"
|
|
148
|
+
publicKey={state.publishableKey}
|
|
149
|
+
customer={customer}
|
|
150
|
+
mode="setup"
|
|
151
|
+
onConfirm={handleConfirm}
|
|
152
|
+
onCancel={handleCancel}
|
|
153
|
+
returnUrl={window.location.href}
|
|
154
|
+
/>
|
|
155
|
+
</Box>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const renderPaymentMethodInfo = () => {
|
|
160
|
+
if (type === 'card' && card) {
|
|
161
|
+
return (
|
|
162
|
+
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
|
163
|
+
<CreditCard sx={{ fontSize: 16, color: 'text.secondary' }} />
|
|
164
|
+
<Typography variant="body2">
|
|
165
|
+
{card.brand.toUpperCase()} •••• {card.last4}
|
|
166
|
+
</Typography>
|
|
167
|
+
</Stack>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (type === 'link' && link) {
|
|
172
|
+
return (
|
|
173
|
+
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
|
174
|
+
<Email sx={{ fontSize: 16, color: 'text.secondary' }} />
|
|
175
|
+
<Typography variant="body2">
|
|
176
|
+
{t('admin.subscription.changePayer.stripe.linkType')} ({link.email})
|
|
177
|
+
</Typography>
|
|
178
|
+
</Stack>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (type === 'us_bank_account' && usBankAccount) {
|
|
183
|
+
return (
|
|
184
|
+
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
|
185
|
+
<AccountBalance sx={{ fontSize: 16, color: 'text.secondary' }} />
|
|
186
|
+
<Typography variant="body2">
|
|
187
|
+
{usBankAccount.bank_name || t('admin.subscription.changePayer.stripe.bankAccount')} ••••{' '}
|
|
188
|
+
{usBankAccount.last4}
|
|
189
|
+
</Typography>
|
|
190
|
+
</Stack>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (['arcblock', 'ethereum', 'base'].includes(type) && payer) {
|
|
195
|
+
return <DID did={payer} responsive={false} compact copyable={false} />;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
|
|
200
|
+
{type || '-'}
|
|
201
|
+
</Typography>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<Stack direction="row" spacing={1} sx={{ alignItems: 'center', flex: 1 }}>
|
|
207
|
+
{renderPaymentMethodInfo()}
|
|
208
|
+
{editable && (
|
|
209
|
+
<Button
|
|
210
|
+
variant="text"
|
|
211
|
+
size="small"
|
|
212
|
+
sx={{
|
|
213
|
+
color: 'text.link',
|
|
214
|
+
}}
|
|
215
|
+
loading={state.submitting}
|
|
216
|
+
onClick={handleEdit}>
|
|
217
|
+
{t('admin.subscription.changePayer.btn')}
|
|
218
|
+
</Button>
|
|
219
|
+
)}
|
|
220
|
+
</Stack>
|
|
221
|
+
);
|
|
222
|
+
}
|
package/src/global.css
CHANGED
package/src/libs/util.ts
CHANGED
package/src/locales/en.tsx
CHANGED
|
@@ -1421,6 +1421,19 @@ export default flat({
|
|
|
1421
1421
|
batchPay: {
|
|
1422
1422
|
button: 'Pay due invoices',
|
|
1423
1423
|
},
|
|
1424
|
+
payerAddress: 'Payment Address',
|
|
1425
|
+
changePayer: {
|
|
1426
|
+
btn: 'Change',
|
|
1427
|
+
stripe: {
|
|
1428
|
+
linkType: 'Stripe Link',
|
|
1429
|
+
bankAccount: 'Bank Account',
|
|
1430
|
+
},
|
|
1431
|
+
connect: {
|
|
1432
|
+
title: 'Change Payment Address',
|
|
1433
|
+
success: 'Payment Address changed successfully',
|
|
1434
|
+
error: 'Failed to change payment Address',
|
|
1435
|
+
},
|
|
1436
|
+
},
|
|
1424
1437
|
},
|
|
1425
1438
|
customer: {
|
|
1426
1439
|
view: 'View customer',
|
package/src/locales/zh.tsx
CHANGED
|
@@ -1387,6 +1387,19 @@ export default flat({
|
|
|
1387
1387
|
batchPay: {
|
|
1388
1388
|
button: '批量付款',
|
|
1389
1389
|
},
|
|
1390
|
+
payerAddress: '扣费地址',
|
|
1391
|
+
changePayer: {
|
|
1392
|
+
btn: '变更',
|
|
1393
|
+
stripe: {
|
|
1394
|
+
linkType: 'Stripe Link',
|
|
1395
|
+
bankAccount: '银行账户',
|
|
1396
|
+
},
|
|
1397
|
+
connect: {
|
|
1398
|
+
title: '变更扣费地址',
|
|
1399
|
+
success: '扣费地址变更成功',
|
|
1400
|
+
error: '扣费地址变更失败',
|
|
1401
|
+
},
|
|
1402
|
+
},
|
|
1390
1403
|
},
|
|
1391
1404
|
customer: {
|
|
1392
1405
|
view: '查看客户',
|
|
@@ -55,7 +55,7 @@ const fetchData = (
|
|
|
55
55
|
relatedCreditGrants?: TCreditGrantExpanded[];
|
|
56
56
|
}
|
|
57
57
|
> => {
|
|
58
|
-
return api.get(`/api/invoices/${id}`).then((res) => res.data);
|
|
58
|
+
return api.get(`/api/invoices/${id}?sync=true`).then((res: any) => res.data);
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const InfoDirection = 'column';
|
|
@@ -92,7 +92,7 @@ export default function InvoiceDetail(props: { id: string }) {
|
|
|
92
92
|
const createUpdater = (key: string) => async (updates: TInvoice) => {
|
|
93
93
|
try {
|
|
94
94
|
setState((prev) => ({ loading: { ...prev.loading, [key]: true } }));
|
|
95
|
-
await api.put(`/api/invoices/${props.id}`, updates).then((res) => res.data);
|
|
95
|
+
await api.put(`/api/invoices/${props.id}`, updates).then((res: any) => res.data);
|
|
96
96
|
Toast.success(t('common.saved'));
|
|
97
97
|
runAsync();
|
|
98
98
|
} catch (err) {
|
|
@@ -120,6 +120,8 @@ export default function InvoiceDetail(props: { id: string }) {
|
|
|
120
120
|
};
|
|
121
121
|
// @ts-ignore
|
|
122
122
|
const isDonation = data?.checkoutSession?.submit_type === 'donate';
|
|
123
|
+
const showDownloadButton =
|
|
124
|
+
['open', 'paid', 'uncollectible'].includes(data.status) && !isDonation && !isEmpty(data.lines);
|
|
123
125
|
return (
|
|
124
126
|
<Root direction="column" spacing={2.5} sx={{ mb: 4 }}>
|
|
125
127
|
<Box>
|
|
@@ -144,7 +146,7 @@ export default function InvoiceDetail(props: { id: string }) {
|
|
|
144
146
|
</Typography>
|
|
145
147
|
</Stack>
|
|
146
148
|
<Box style={{ display: 'flex', gap: '10px' }}>
|
|
147
|
-
<Download data={data} />
|
|
149
|
+
{showDownloadButton && <Download data={data} />}
|
|
148
150
|
<InvoiceActions data={data} onChange={runAsync} variant="normal" />
|
|
149
151
|
</Box>
|
|
150
152
|
</Stack>
|
|
@@ -35,6 +35,7 @@ import { goBackOrFallback } from '../../../../libs/util';
|
|
|
35
35
|
import InfoRowGroup from '../../../../components/info-row-group';
|
|
36
36
|
import VendorServiceList from '../../../../components/subscription/vendor-service-list';
|
|
37
37
|
import { useSessionContext } from '../../../../contexts/session';
|
|
38
|
+
import PaymentMethodInfo from '../../../../components/subscription/payment-method-info';
|
|
38
39
|
|
|
39
40
|
const fetchData = (id: string): Promise<TSubscriptionExpanded> => {
|
|
40
41
|
return api.get(`/api/subscriptions/${id}`).then((res) => res.data);
|
|
@@ -285,6 +286,21 @@ export default function SubscriptionDetail(props: { id: string }) {
|
|
|
285
286
|
/>
|
|
286
287
|
}
|
|
287
288
|
/>
|
|
289
|
+
|
|
290
|
+
{(data as any).paymentMethodDetails && (
|
|
291
|
+
<InfoRow
|
|
292
|
+
label={t('admin.subscription.payerAddress')}
|
|
293
|
+
value={
|
|
294
|
+
<PaymentMethodInfo
|
|
295
|
+
subscriptionId={data.id}
|
|
296
|
+
customer={data.customer}
|
|
297
|
+
paymentMethodDetails={(data as any).paymentMethodDetails}
|
|
298
|
+
editable={false}
|
|
299
|
+
paymentMethodType={data.paymentMethod?.type}
|
|
300
|
+
/>
|
|
301
|
+
}
|
|
302
|
+
/>
|
|
303
|
+
)}
|
|
288
304
|
{data.payment_details && hasDelegateTxHash(data.payment_details, data.paymentMethod) && (
|
|
289
305
|
<InfoRow
|
|
290
306
|
label={t('common.delegateTxHash')}
|
|
@@ -3,7 +3,7 @@ import DID from '@arcblock/ux/lib/DID';
|
|
|
3
3
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
4
4
|
import { api, formatBNStr, formatToDate, usePaymentContext } from '@blocklet/payment-react';
|
|
5
5
|
import { BN } from '@ocap/util';
|
|
6
|
-
import type { GroupedBN, TPaymentMethod, TPaymentStat } from '@blocklet/payment-types';
|
|
6
|
+
import type { GroupedBN, TPaymentCurrency, TPaymentMethod, TPaymentStat } from '@blocklet/payment-types';
|
|
7
7
|
import {
|
|
8
8
|
Avatar,
|
|
9
9
|
Box,
|
|
@@ -175,8 +175,8 @@ export default function Overview() {
|
|
|
175
175
|
|
|
176
176
|
const currencies: TCurrencyMap = useMemo(() => {
|
|
177
177
|
const map: TCurrencyMap = {};
|
|
178
|
-
(settings.paymentMethods || []).forEach((method) => {
|
|
179
|
-
(method.payment_currencies || []).forEach((currency) => {
|
|
178
|
+
(settings.paymentMethods || []).forEach((method: { payment_currencies: TPaymentCurrency[] }) => {
|
|
179
|
+
(method.payment_currencies || []).forEach((currency: TPaymentCurrency) => {
|
|
180
180
|
if (!map[currency.id]) {
|
|
181
181
|
map[currency.id] = {
|
|
182
182
|
...currency,
|
|
@@ -1105,10 +1105,12 @@ export default function Overview() {
|
|
|
1105
1105
|
sx={{
|
|
1106
1106
|
p: 1.5,
|
|
1107
1107
|
flex: '1 1 calc(50% - 8px)',
|
|
1108
|
+
minWidth: 0,
|
|
1108
1109
|
borderRadius: 1,
|
|
1109
1110
|
backgroundColor: theme.mode === 'dark' ? 'grey.100' : 'grey.50',
|
|
1110
1111
|
border: 'none',
|
|
1111
1112
|
boxShadow: 'none',
|
|
1113
|
+
containerType: 'inline-size',
|
|
1112
1114
|
}}>
|
|
1113
1115
|
<Box>
|
|
1114
1116
|
<Typography
|
|
@@ -1124,13 +1126,11 @@ export default function Overview() {
|
|
|
1124
1126
|
sx={{
|
|
1125
1127
|
gap: 1.5,
|
|
1126
1128
|
flexWrap: 'wrap',
|
|
1127
|
-
flexDirection:
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
xs: 'flex-start',
|
|
1133
|
-
md: 'baseline',
|
|
1129
|
+
flexDirection: 'row',
|
|
1130
|
+
alignItems: 'baseline',
|
|
1131
|
+
'@container (max-width: 220px)': {
|
|
1132
|
+
flexDirection: 'column',
|
|
1133
|
+
alignItems: 'flex-start',
|
|
1134
1134
|
},
|
|
1135
1135
|
}}>
|
|
1136
1136
|
<Typography
|
|
@@ -1239,14 +1239,14 @@ export default function Overview() {
|
|
|
1239
1239
|
|
|
1240
1240
|
<Grid
|
|
1241
1241
|
container
|
|
1242
|
+
spacing={{ xs: 3, lg: 6 }}
|
|
1242
1243
|
sx={{
|
|
1243
|
-
gap: { xs: 3, md: 6 },
|
|
1244
1244
|
mb: 4,
|
|
1245
1245
|
}}>
|
|
1246
1246
|
<Grid
|
|
1247
1247
|
size={{
|
|
1248
1248
|
xs: 12,
|
|
1249
|
-
|
|
1249
|
+
lg: 8,
|
|
1250
1250
|
}}>
|
|
1251
1251
|
{renderFinancialSection()}
|
|
1252
1252
|
</Grid>
|
|
@@ -1254,7 +1254,7 @@ export default function Overview() {
|
|
|
1254
1254
|
<Grid
|
|
1255
1255
|
size={{
|
|
1256
1256
|
xs: 12,
|
|
1257
|
-
|
|
1257
|
+
lg: 4,
|
|
1258
1258
|
}}>
|
|
1259
1259
|
{renderBusinessMonitoringSection()}
|
|
1260
1260
|
</Grid>
|
|
@@ -1265,7 +1265,7 @@ export default function Overview() {
|
|
|
1265
1265
|
open={open}
|
|
1266
1266
|
anchorEl={state.anchorEl}
|
|
1267
1267
|
onClose={() => setState({ anchorEl: null })}
|
|
1268
|
-
anchorOrigin={{ vertical: 'bottom', horizontal: '
|
|
1268
|
+
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}>
|
|
1269
1269
|
<DateRangePicker
|
|
1270
1270
|
open
|
|
1271
1271
|
toggle={onTogglePicker as any}
|