payment-kit 1.13.67 → 1.13.69
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/jobs/invoice.ts +3 -0
- package/api/src/libs/notification/template/subscription-renew-failed.ts +2 -8
- package/api/src/libs/payment.ts +101 -40
- package/api/src/libs/util.ts +2 -0
- package/api/src/locales/en.ts +9 -4
- package/api/src/locales/zh.ts +4 -1
- package/api/src/routes/checkout-sessions.ts +2 -0
- package/api/src/routes/connect/setup.ts +13 -4
- package/api/src/routes/connect/subscribe.ts +13 -4
- package/blocklet.yml +1 -1
- package/package.json +3 -3
- package/src/components/checkout/form/index.tsx +6 -2
- package/src/pages/customer/invoice.tsx +3 -3
package/api/src/jobs/invoice.ts
CHANGED
|
@@ -79,6 +79,9 @@ export const handleInvoice = async (job: InvoiceJob) => {
|
|
|
79
79
|
if (invoice.payment_intent_id) {
|
|
80
80
|
logger.warn(`PaymentIntent exist: ${invoice.payment_intent_id} for invoice ${job.invoiceId}`);
|
|
81
81
|
paymentIntent = await PaymentIntent.findByPk(invoice.payment_intent_id);
|
|
82
|
+
if (paymentIntent && ['succeeded', 'canceled'].includes(paymentIntent.status) === false) {
|
|
83
|
+
await paymentIntent.update({ status: 'requires_capture' });
|
|
84
|
+
}
|
|
82
85
|
} else {
|
|
83
86
|
const descriptionMap: any = {
|
|
84
87
|
subscription_create: 'Subscription creation',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/brace-style */
|
|
2
2
|
/* eslint-disable @typescript-eslint/indent */
|
|
3
3
|
import { fromUnitToToken, toDid } from '@ocap/util';
|
|
4
|
+
import camelCase from 'lodash/camelCase';
|
|
4
5
|
import prettyMsI18n from 'pretty-ms-i18n';
|
|
5
6
|
|
|
6
7
|
import { getUserLocale } from '../../../integrations/blocklet/notification';
|
|
@@ -60,14 +61,7 @@ export class SubscriptionRenewFailedEmailTemplate
|
|
|
60
61
|
throw new Error(`SufficientForPaymentResult.sufficient should be false: ${JSON.stringify(this.options.result)}`);
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
const toCamelCase = (input: string): string => {
|
|
65
|
-
return input.toLowerCase().replace(/_([a-z])/g, (_match, group1) => {
|
|
66
|
-
return group1.toUpperCase();
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const i18nText = `notification.subscriptionRenewFailed.reason.${toCamelCase(this.options.result.reason as string)}`;
|
|
64
|
+
const i18nText = `notification.subscriptionRenewFailed.reason.${camelCase(this.options.result.reason as string)}`;
|
|
71
65
|
|
|
72
66
|
const paymentDetail = await getPaymentDetail(userDid, invoice);
|
|
73
67
|
const reason = translate(i18nText, locale, {
|
package/api/src/libs/payment.ts
CHANGED
|
@@ -2,26 +2,35 @@
|
|
|
2
2
|
import { toDelegateAddress } from '@arcblock/did-util';
|
|
3
3
|
import { sign } from '@arcblock/jwt';
|
|
4
4
|
import { getWalletDid } from '@blocklet/sdk/lib/did';
|
|
5
|
-
import type { DelegateState } from '@ocap/client';
|
|
5
|
+
import type { DelegateState, TokenLimit } from '@ocap/client';
|
|
6
6
|
import { toTxHash } from '@ocap/mcrypto';
|
|
7
7
|
import { BN, fromUnitToToken } from '@ocap/util';
|
|
8
|
+
import cloneDeep from 'lodash/cloneDeep';
|
|
9
|
+
import type { LiteralUnion } from 'type-fest';
|
|
8
10
|
|
|
9
11
|
import { Invoice, PaymentCurrency, PaymentIntent, PaymentMethod } from '../store/models';
|
|
10
12
|
import type { TPaymentCurrency } from '../store/models/payment-currency';
|
|
11
13
|
import { blocklet, wallet } from './auth';
|
|
12
14
|
import logger from './logger';
|
|
15
|
+
import { OCAP_PAYMENT_TX_TYPE } from './util';
|
|
13
16
|
|
|
14
17
|
export interface SufficientForPaymentResult {
|
|
15
18
|
sufficient: boolean;
|
|
16
|
-
reason?:
|
|
19
|
+
reason?: LiteralUnion<
|
|
17
20
|
| 'NO_DID_WALLET'
|
|
18
21
|
| 'NO_DELEGATION'
|
|
19
22
|
| 'NO_TRANSFER_PERMISSION'
|
|
23
|
+
| 'NO_TRANSFER_TO'
|
|
24
|
+
| 'NO_TOKEN_PERMISSION'
|
|
20
25
|
| 'NO_TOKEN'
|
|
26
|
+
| 'NO_ENOUGH_ALLOWANCE'
|
|
21
27
|
| 'NO_ENOUGH_TOKEN'
|
|
22
|
-
| 'NOT_SUPPORTED'
|
|
28
|
+
| 'NOT_SUPPORTED',
|
|
29
|
+
string
|
|
30
|
+
>;
|
|
23
31
|
delegator?: string;
|
|
24
32
|
state?: DelegateState;
|
|
33
|
+
token?: { address: string; balance: string };
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
export async function isDelegationSufficientForPayment(args: {
|
|
@@ -31,6 +40,8 @@ export async function isDelegationSufficientForPayment(args: {
|
|
|
31
40
|
amount: string;
|
|
32
41
|
}): Promise<SufficientForPaymentResult> {
|
|
33
42
|
const { paymentCurrency, paymentMethod, userDid, amount } = args;
|
|
43
|
+
const tokenAddress = paymentCurrency.contract as string;
|
|
44
|
+
|
|
34
45
|
if (paymentMethod.type === 'arcblock') {
|
|
35
46
|
// user have bond wallet did?
|
|
36
47
|
const { user } = await blocklet.getUser(userDid, { enableConnectedAccount: true });
|
|
@@ -48,22 +59,43 @@ export async function isDelegationSufficientForPayment(args: {
|
|
|
48
59
|
return { sufficient: false, reason: 'NO_DELEGATION' };
|
|
49
60
|
}
|
|
50
61
|
|
|
51
|
-
// have
|
|
52
|
-
|
|
62
|
+
// have transfer permissions?
|
|
63
|
+
const grant = (state as DelegateState).ops.find((x: any) => x.key === OCAP_PAYMENT_TX_TYPE)?.value;
|
|
64
|
+
if (!grant) {
|
|
53
65
|
return { sufficient: false, reason: 'NO_TRANSFER_PERMISSION' };
|
|
54
66
|
}
|
|
55
67
|
|
|
68
|
+
// check token limits
|
|
69
|
+
if (grant.limit) {
|
|
70
|
+
const tokenLimit = grant.limit.tokens.find((x: any) => x.address === tokenAddress);
|
|
71
|
+
if (!tokenLimit) {
|
|
72
|
+
return { sufficient: false, reason: 'NO_TOKEN_PERMISSION' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// FIXME: @wangshijun check other conditions in the token limit: txCount, totalAllowance, validUntil, rateLimit
|
|
76
|
+
|
|
77
|
+
if (Array.isArray(tokenLimit.to) && tokenLimit.to.length && tokenLimit.to.includes(wallet.address) === false) {
|
|
78
|
+
return { sufficient: false, reason: 'NO_TRANSFER_TO' };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const requested = new BN(amount);
|
|
82
|
+
const allowance = new BN(tokenLimit.txAllowance);
|
|
83
|
+
if (requested.gt(allowance)) {
|
|
84
|
+
return { sufficient: false, reason: 'NO_ENOUGH_ALLOWANCE' };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
56
88
|
// balance enough token for payment?
|
|
57
|
-
const { tokens } = await client.getAccountTokens({ address: delegator, token:
|
|
89
|
+
const { tokens } = await client.getAccountTokens({ address: delegator, token: tokenAddress });
|
|
58
90
|
const [token] = tokens;
|
|
59
91
|
if (!token) {
|
|
60
92
|
return { sufficient: false, reason: 'NO_TOKEN' };
|
|
61
93
|
}
|
|
62
94
|
if (new BN(token.balance).lt(new BN(amount))) {
|
|
63
|
-
return { sufficient: false, reason: 'NO_ENOUGH_TOKEN' };
|
|
95
|
+
return { sufficient: false, reason: 'NO_ENOUGH_TOKEN', token };
|
|
64
96
|
}
|
|
65
97
|
|
|
66
|
-
return { sufficient: true, delegator, state };
|
|
98
|
+
return { sufficient: true, delegator, state, token };
|
|
67
99
|
}
|
|
68
100
|
|
|
69
101
|
if (paymentMethod.type === 'stripe') {
|
|
@@ -114,53 +146,82 @@ export async function getPaymentDetail(userDid: string, invoice: Invoice): Promi
|
|
|
114
146
|
}
|
|
115
147
|
|
|
116
148
|
if (paymentMethod.type === 'arcblock') {
|
|
117
|
-
//
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const client = paymentMethod.getOcapClient();
|
|
126
|
-
|
|
127
|
-
// have delegated before?
|
|
128
|
-
const address = toDelegateAddress(delegator, wallet.address);
|
|
129
|
-
const { state } = await client.getDelegateState({ address });
|
|
130
|
-
if (!state) {
|
|
131
|
-
logger.error('getPayment.error', { reason: 'NO_DELEGATION' });
|
|
132
|
-
return defaultResult;
|
|
133
|
-
}
|
|
149
|
+
// balance enough token for payment?
|
|
150
|
+
const result = await isDelegationSufficientForPayment({
|
|
151
|
+
paymentMethod,
|
|
152
|
+
paymentCurrency,
|
|
153
|
+
userDid,
|
|
154
|
+
amount: paymentIntent.amount,
|
|
155
|
+
});
|
|
134
156
|
|
|
135
|
-
// have enough
|
|
136
|
-
if (
|
|
137
|
-
logger.error('getPayment.error', { reason:
|
|
157
|
+
// Do not have enough permission
|
|
158
|
+
if (!result.token) {
|
|
159
|
+
logger.error('getPayment.error', { reason: result.reason });
|
|
138
160
|
return defaultResult;
|
|
139
161
|
}
|
|
140
162
|
|
|
141
|
-
//
|
|
163
|
+
// Do not have enough token
|
|
142
164
|
const amount: number = +fromUnitToToken(paymentIntent.amount, paymentCurrency.decimal);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const { tokens } = await client.getAccountTokens({
|
|
146
|
-
address: delegator,
|
|
147
|
-
token: paymentCurrency.contract as string,
|
|
148
|
-
});
|
|
149
|
-
const [token] = tokens;
|
|
150
|
-
if (!token) {
|
|
165
|
+
if (!result.delegator) {
|
|
151
166
|
return {
|
|
152
167
|
balance: 0,
|
|
153
168
|
price: amount,
|
|
154
|
-
symbol,
|
|
169
|
+
symbol: paymentCurrency.symbol,
|
|
155
170
|
};
|
|
156
171
|
}
|
|
157
172
|
|
|
158
173
|
return {
|
|
159
|
-
balance: +fromUnitToToken(token.balance, paymentCurrency.decimal),
|
|
174
|
+
balance: +fromUnitToToken(result.token.balance, paymentCurrency.decimal),
|
|
160
175
|
price: amount,
|
|
161
|
-
symbol,
|
|
176
|
+
symbol: paymentCurrency.symbol,
|
|
162
177
|
};
|
|
163
178
|
}
|
|
164
179
|
|
|
165
180
|
return defaultResult;
|
|
166
181
|
}
|
|
182
|
+
|
|
183
|
+
export async function getTokenLimitsForDelegation(
|
|
184
|
+
paymentMethod: PaymentMethod,
|
|
185
|
+
paymentCurrency: PaymentCurrency,
|
|
186
|
+
address: string,
|
|
187
|
+
amount: string
|
|
188
|
+
): Promise<TokenLimit[]> {
|
|
189
|
+
const client = paymentMethod.getOcapClient();
|
|
190
|
+
const { state } = await client.getDelegateState({ address });
|
|
191
|
+
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
const entry: TokenLimit = {
|
|
194
|
+
address: paymentCurrency.contract as string,
|
|
195
|
+
to: [wallet.address], // FIXME: may broken if we have vault, migrated
|
|
196
|
+
txAllowance: amount,
|
|
197
|
+
totalAllowance: '0',
|
|
198
|
+
txCount: 0,
|
|
199
|
+
validUntil: 0,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// If we never delegated before
|
|
203
|
+
if (!state) {
|
|
204
|
+
return [entry];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const op = (state as DelegateState).ops.find((x) => x.key === OCAP_PAYMENT_TX_TYPE);
|
|
208
|
+
if (op && Array.isArray(op.value.limit?.tokens) && op.value.limit.tokens.length > 0) {
|
|
209
|
+
const tokenLimits = cloneDeep(op.value.limit.tokens);
|
|
210
|
+
const index = op.value.limit.tokens.findIndex((x) => x.address === paymentCurrency.contract);
|
|
211
|
+
// we are updating an existing token limit
|
|
212
|
+
if (index > -1) {
|
|
213
|
+
const limit = op.value.limit.tokens[index] as TokenLimit;
|
|
214
|
+
// If we have a previous delegation and the txAllowance is smaller than requested amount
|
|
215
|
+
if (new BN(limit.txAllowance).lt(new BN(amount))) {
|
|
216
|
+
tokenLimits[index] = entry;
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
// we are adding a new token limit
|
|
220
|
+
tokenLimits.push(entry);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return tokenLimits;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return [entry];
|
|
227
|
+
}
|
package/api/src/libs/util.ts
CHANGED
|
@@ -7,6 +7,8 @@ import type { LiteralUnion } from 'type-fest';
|
|
|
7
7
|
|
|
8
8
|
import dayjs from './dayjs';
|
|
9
9
|
|
|
10
|
+
export const OCAP_PAYMENT_TX_TYPE = 'fg:t:transfer_v2';
|
|
11
|
+
|
|
10
12
|
export const MAX_RETRY_COUNT = 18; // 2^18 seconds ~~ 3 days, total retry time: 6 days
|
|
11
13
|
export const STRIPE_API_VERSION = '2023-08-16';
|
|
12
14
|
export const STRIPE_ENDPOINT: string = getUrl('/api/integrations/stripe/webhook');
|
package/api/src/locales/en.ts
CHANGED
|
@@ -47,9 +47,9 @@ export default flat({
|
|
|
47
47
|
|
|
48
48
|
subscriptionWillRenew: {
|
|
49
49
|
title: '{productName} will be auto-renewed soon',
|
|
50
|
-
body: 'Your subscription to {productName}
|
|
50
|
+
body: 'Your subscription to {productName} expires in {willRenewDuration}. Please make sure you have enough balance in your account to auto-renew your subscription when it expires ({at}). We wish you all the best!',
|
|
51
51
|
unableToPayBody:
|
|
52
|
-
'Your subscription to {productName}
|
|
52
|
+
'Your subscription to {productName} expires in {willRenewDuration}. <span style="color: red;">Your current balance is {balance}, which is less than {price}</span>, so please make sure you have enough balance in your account to automatically renew your subscription when it expires ({at}). We wish you all the best!',
|
|
53
53
|
renewAmount: 'Amount',
|
|
54
54
|
},
|
|
55
55
|
|
|
@@ -65,9 +65,14 @@ export default flat({
|
|
|
65
65
|
reason: {
|
|
66
66
|
noDidWallet:
|
|
67
67
|
'You have not yet bound the DID Wallet, please bind the DID Wallet, make sure the balance is sufficient and then renew it',
|
|
68
|
-
noDelegation: '
|
|
68
|
+
noDelegation: 'No delegation found from your DID Wallet, please renew it after completing the authorization',
|
|
69
69
|
noTransferPermission:
|
|
70
|
-
'
|
|
70
|
+
'Transfer permission not granted to app, please update the authorization and renew it again',
|
|
71
|
+
noTokenPermission:
|
|
72
|
+
'Token transfer permission not granted to app, please update the authorization and renew it again',
|
|
73
|
+
noTransferTo:
|
|
74
|
+
'App not in whitelist of the transfer permission, please update the authorization and renew it again',
|
|
75
|
+
noEnoughAllowance: 'Transfer amount exceeds tx allowance, please update the authorization and renew it again',
|
|
71
76
|
noToken: "You don't have any tokens in your account, please replenish your tokens and renew your account",
|
|
72
77
|
noEnoughToken:
|
|
73
78
|
'Your account token balance is {balance}, not enough for {price}, please replenish your tokens and renew your account',
|
package/api/src/locales/zh.ts
CHANGED
|
@@ -65,7 +65,10 @@ export default flat({
|
|
|
65
65
|
reason: {
|
|
66
66
|
noDidWallet: '您尚未绑定 DID Wallet,请绑定 DID Wallet,确保余额充足后重新续费',
|
|
67
67
|
noDelegation: '您的 DID Wallet 尚未授权,请完成授权后重新续费',
|
|
68
|
-
noTransferPermission: '您的 DID Wallet
|
|
68
|
+
noTransferPermission: '您的 DID Wallet 未授予应用转账权限,请更新授权后重新续费',
|
|
69
|
+
noTokenPermission: '您的 DID Wallet 未授予应用对应通证的转账权限,请更新授权后重新续费',
|
|
70
|
+
noTransferTo: '您的 DID Wallet 未授予应用扣款权限,请更新授权后重新续费',
|
|
71
|
+
noEnoughAllowance: '扣款金额超出单笔转账限额,请更新授权后重新续费',
|
|
69
72
|
noToken: '您的账户没有任何代币,请充值代币后重新续费',
|
|
70
73
|
noEnoughToken: '您的账户代币余额为 {balance},不足 {price},请充值代币后重新续费',
|
|
71
74
|
noSupported: '不支持使用代币续费,请检查您的套餐',
|
|
@@ -657,6 +657,7 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
|
|
|
657
657
|
subscription: subscription.id,
|
|
658
658
|
});
|
|
659
659
|
|
|
660
|
+
// FIXME: @wangshijun what if we have have changed subscription items when resubmit
|
|
660
661
|
// create subscription items
|
|
661
662
|
const items = await Promise.all(
|
|
662
663
|
lineItems
|
|
@@ -753,6 +754,7 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
|
|
|
753
754
|
id: stripeIntent.id,
|
|
754
755
|
client_secret: stripeIntent.client_secret,
|
|
755
756
|
status: stripeIntent.status,
|
|
757
|
+
intent_type: 'payment_intent',
|
|
756
758
|
};
|
|
757
759
|
}
|
|
758
760
|
|
|
@@ -6,8 +6,10 @@ import { fromPublicKey } from '@ocap/wallet';
|
|
|
6
6
|
import { subscriptionQueue } from '../../jobs/subscription';
|
|
7
7
|
import type { CallbackArgs } from '../../libs/auth';
|
|
8
8
|
import { wallet } from '../../libs/auth';
|
|
9
|
-
import { getGasPayerExtra } from '../../libs/payment';
|
|
10
|
-
import {
|
|
9
|
+
import { getGasPayerExtra, getTokenLimitsForDelegation } from '../../libs/payment';
|
|
10
|
+
import { getFastCheckoutAmount } from '../../libs/session';
|
|
11
|
+
import { OCAP_PAYMENT_TX_TYPE, getTxMetadata } from '../../libs/util';
|
|
12
|
+
import type { TLineItemExpanded } from '../../store/models';
|
|
11
13
|
import { ensureSetupIntent, getAuthPrincipalClaim, getTokenRequirements } from './shared';
|
|
12
14
|
|
|
13
15
|
export default {
|
|
@@ -30,6 +32,13 @@ export default {
|
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
if (paymentMethod.type === 'arcblock') {
|
|
35
|
+
const address = toDelegateAddress(userDid, wallet.address);
|
|
36
|
+
const amount = getFastCheckoutAmount(
|
|
37
|
+
checkoutSession.line_items as TLineItemExpanded[],
|
|
38
|
+
checkoutSession.mode,
|
|
39
|
+
paymentCurrency
|
|
40
|
+
);
|
|
41
|
+
const tokenLimits = await getTokenLimitsForDelegation(paymentMethod, paymentCurrency, address, amount);
|
|
33
42
|
const tokenRequirements = await getTokenRequirements(checkoutSession, paymentMethod, paymentCurrency);
|
|
34
43
|
|
|
35
44
|
return {
|
|
@@ -39,9 +48,9 @@ export default {
|
|
|
39
48
|
wallet: fromPublicKey(userPk, toTypeInfo(userDid)),
|
|
40
49
|
data: {
|
|
41
50
|
itx: {
|
|
42
|
-
address
|
|
51
|
+
address,
|
|
43
52
|
to: wallet.address,
|
|
44
|
-
ops: [{ typeUrl:
|
|
53
|
+
ops: [{ typeUrl: OCAP_PAYMENT_TX_TYPE, limit: { tokens: tokenLimits, assets: [] } }],
|
|
45
54
|
data: getTxMetadata({
|
|
46
55
|
subscriptionId: subscription.id,
|
|
47
56
|
checkoutSessionId,
|
|
@@ -8,8 +8,10 @@ import { invoiceQueue } from '../../jobs/invoice';
|
|
|
8
8
|
import { subscriptionQueue } from '../../jobs/subscription';
|
|
9
9
|
import type { CallbackArgs } from '../../libs/auth';
|
|
10
10
|
import { wallet } from '../../libs/auth';
|
|
11
|
-
import { getGasPayerExtra } from '../../libs/payment';
|
|
12
|
-
import {
|
|
11
|
+
import { getGasPayerExtra, getTokenLimitsForDelegation } from '../../libs/payment';
|
|
12
|
+
import { getFastCheckoutAmount } from '../../libs/session';
|
|
13
|
+
import { OCAP_PAYMENT_TX_TYPE, getTxMetadata } from '../../libs/util';
|
|
14
|
+
import type { TLineItemExpanded } from '../../store/models';
|
|
13
15
|
import { ensureInvoiceForCheckout, ensurePaymentIntent, getAuthPrincipalClaim, getTokenRequirements } from './shared';
|
|
14
16
|
|
|
15
17
|
export default {
|
|
@@ -32,6 +34,13 @@ export default {
|
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
if (paymentMethod.type === 'arcblock') {
|
|
37
|
+
const address = toDelegateAddress(userDid, wallet.address);
|
|
38
|
+
const amount = getFastCheckoutAmount(
|
|
39
|
+
checkoutSession.line_items as TLineItemExpanded[],
|
|
40
|
+
checkoutSession.mode,
|
|
41
|
+
paymentCurrency
|
|
42
|
+
);
|
|
43
|
+
const tokenLimits = await getTokenLimitsForDelegation(paymentMethod, paymentCurrency, address, amount);
|
|
35
44
|
const tokenRequirements = await getTokenRequirements(checkoutSession, paymentMethod, paymentCurrency);
|
|
36
45
|
|
|
37
46
|
return {
|
|
@@ -41,9 +50,9 @@ export default {
|
|
|
41
50
|
wallet: fromPublicKey(userPk, toTypeInfo(userDid)),
|
|
42
51
|
data: {
|
|
43
52
|
itx: {
|
|
44
|
-
address
|
|
53
|
+
address,
|
|
45
54
|
to: wallet.address,
|
|
46
|
-
ops: [{ typeUrl:
|
|
55
|
+
ops: [{ typeUrl: OCAP_PAYMENT_TX_TYPE, limit: { tokens: tokenLimits, assets: [] } }],
|
|
47
56
|
data: getTxMetadata({
|
|
48
57
|
subscriptionId: subscription.id,
|
|
49
58
|
checkoutSessionId,
|
package/blocklet.yml
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.69",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "COMPONENT_STORE_URL=https://test.store.blocklet.dev blocklet dev",
|
|
6
6
|
"eject": "vite eject",
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"@abtnode/types": "^1.16.19",
|
|
107
107
|
"@arcblock/eslint-config": "^0.2.4",
|
|
108
108
|
"@arcblock/eslint-config-ts": "^0.2.4",
|
|
109
|
-
"@did-pay/types": "1.13.
|
|
109
|
+
"@did-pay/types": "1.13.69",
|
|
110
110
|
"@types/cookie-parser": "^1.4.6",
|
|
111
111
|
"@types/cors": "^2.8.17",
|
|
112
112
|
"@types/dotenv-flow": "^3.3.3",
|
|
@@ -143,5 +143,5 @@
|
|
|
143
143
|
"parser": "typescript"
|
|
144
144
|
}
|
|
145
145
|
},
|
|
146
|
-
"gitHead": "
|
|
146
|
+
"gitHead": "fd169e0529e664ecf8257e684029f21629d39113"
|
|
147
147
|
}
|
|
@@ -82,7 +82,11 @@ export default function PaymentForm({
|
|
|
82
82
|
paying: boolean;
|
|
83
83
|
paid: boolean;
|
|
84
84
|
paymentIntent?: TPaymentIntent;
|
|
85
|
-
stripeContext?:
|
|
85
|
+
stripeContext?: {
|
|
86
|
+
client_secret: string;
|
|
87
|
+
intent_type: string;
|
|
88
|
+
status: string;
|
|
89
|
+
};
|
|
86
90
|
customer?: TCustomer;
|
|
87
91
|
stripePaying: boolean;
|
|
88
92
|
}>({
|
|
@@ -90,7 +94,7 @@ export default function PaymentForm({
|
|
|
90
94
|
paying: false,
|
|
91
95
|
paid: false,
|
|
92
96
|
paymentIntent,
|
|
93
|
-
stripeContext:
|
|
97
|
+
stripeContext: undefined,
|
|
94
98
|
customer,
|
|
95
99
|
stripePaying: false,
|
|
96
100
|
});
|
|
@@ -3,9 +3,9 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
|
3
3
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
4
4
|
import type { TInvoiceExpanded } from '@did-pay/types';
|
|
5
5
|
import { ArrowBackOutlined } from '@mui/icons-material';
|
|
6
|
-
import { Alert, Box, Button, CircularProgress, Grid,
|
|
6
|
+
import { Alert, Box, Button, CircularProgress, Grid, Stack, Typography } from '@mui/material';
|
|
7
7
|
import { useRequest, useSetState } from 'ahooks';
|
|
8
|
-
import { useParams } from 'react-router-dom';
|
|
8
|
+
import { Link, useParams } from 'react-router-dom';
|
|
9
9
|
|
|
10
10
|
import TxLink from '../../components/blockchain/tx';
|
|
11
11
|
import Currency from '../../components/currency';
|
|
@@ -73,7 +73,7 @@ export default function CustomerHome() {
|
|
|
73
73
|
<Layout>
|
|
74
74
|
<Grid container spacing={3} sx={{ mt: 1 }}>
|
|
75
75
|
<Grid item xs={12} md={12}>
|
|
76
|
-
<Link
|
|
76
|
+
<Link to="/customer">
|
|
77
77
|
<Stack direction="row" alignItems="center" sx={{ fontWeight: 'normal' }}>
|
|
78
78
|
<ArrowBackOutlined fontSize="small" sx={{ mr: 0.5, color: 'text.secondary' }} />
|
|
79
79
|
<Typography variant="h6" sx={{ color: 'text.secondary', fontWeight: 'normal' }}>
|