payment-kit 1.13.162 → 1.13.164
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 +2 -0
- package/api/src/locales/zh.ts +1 -1
- package/api/src/queues/payment.ts +1 -1
- package/api/src/routes/connect/collect-batch.ts +125 -0
- package/api/src/routes/connect/shared.ts +32 -0
- package/api/src/routes/products.ts +13 -3
- package/api/src/routes/subscriptions.ts +20 -0
- package/api/src/store/models/customer.ts +4 -4
- package/api/src/store/models/invoice.ts +38 -22
- package/api/src/store/models/subscription.ts +1 -1
- package/api/src/store/models/types.ts +1 -0
- package/api/tests/libs/util.spec.ts +4 -9
- package/blocklet.yml +2 -2
- package/package.json +4 -4
- package/src/components/filter-toolbar.tsx +130 -79
- package/src/components/invoice/list.tsx +14 -9
- package/src/components/payment-intent/list.tsx +24 -7
- package/src/components/refund/list.tsx +5 -2
- package/src/components/subscription/list.tsx +5 -2
- package/src/components/subscription/portal/actions.tsx +46 -11
- package/src/locales/en.tsx +4 -0
- package/src/locales/zh.tsx +27 -23
- package/src/pages/admin/billing/invoices/index.tsx +1 -1
- package/src/pages/admin/payments/index.tsx +1 -1
- package/src/pages/admin/products/products/index.tsx +47 -27
- package/src/pages/customer/invoice/past-due.tsx +25 -6
- package/src/pages/customer/subscription/detail.tsx +1 -1
package/api/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ import routes from './routes';
|
|
|
27
27
|
import changePaymentHandlers from './routes/connect/change-payment';
|
|
28
28
|
import changePlanHandlers from './routes/connect/change-plan';
|
|
29
29
|
import collectHandlers from './routes/connect/collect';
|
|
30
|
+
import collectBatchHandlers from './routes/connect/collect-batch';
|
|
30
31
|
import payHandlers from './routes/connect/pay';
|
|
31
32
|
import setupHandlers from './routes/connect/setup';
|
|
32
33
|
import subscribeHandlers from './routes/connect/subscribe';
|
|
@@ -54,6 +55,7 @@ app.use(ensureI18n());
|
|
|
54
55
|
|
|
55
56
|
const router = express.Router();
|
|
56
57
|
handlers.attach(Object.assign({ app: router }, collectHandlers));
|
|
58
|
+
handlers.attach(Object.assign({ app: router }, collectBatchHandlers));
|
|
57
59
|
handlers.attach(Object.assign({ app: router }, payHandlers));
|
|
58
60
|
handlers.attach(Object.assign({ app: router }, setupHandlers));
|
|
59
61
|
handlers.attach(Object.assign({ app: router }, subscribeHandlers));
|
package/api/src/locales/zh.ts
CHANGED
|
@@ -77,7 +77,7 @@ export const handlePaymentSucceed = async (paymentIntent: PaymentIntent) => {
|
|
|
77
77
|
logger.info(`Subscription ${subscription.id} updated on payment done ${invoice.id}`);
|
|
78
78
|
} else if (subscription.status === 'past_due' && subscription.cancelation_details?.reason === 'payment_failed') {
|
|
79
79
|
// ensure no uncollectible amount before recovering from payment failed
|
|
80
|
-
const result = await Invoice.
|
|
80
|
+
const [result] = await Invoice.getUncollectibleAmount({ subscriptionId: subscription.id });
|
|
81
81
|
if (isEmpty(result)) {
|
|
82
82
|
// reset billing cycle anchor and cancel_* if we are recovering from payment failed
|
|
83
83
|
if (subscription.cancel_at && subscription.cancel_at !== subscription.current_period_end) {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/* eslint-disable no-await-in-loop */
|
|
2
|
+
import type { Transaction } from '@ocap/client';
|
|
3
|
+
import { fromAddress } from '@ocap/wallet';
|
|
4
|
+
|
|
5
|
+
import type { CallbackArgs } from '../../libs/auth';
|
|
6
|
+
import { wallet } from '../../libs/auth';
|
|
7
|
+
import { getGasPayerExtra } from '../../libs/payment';
|
|
8
|
+
import { getTxMetadata } from '../../libs/util';
|
|
9
|
+
import { invoiceQueue } from '../../queues/invoice';
|
|
10
|
+
import { handlePaymentSucceed, paymentQueue } from '../../queues/payment';
|
|
11
|
+
import { PaymentIntent } from '../../store/models';
|
|
12
|
+
import { ensureSubscriptionForCollectBatch, getAuthPrincipalClaim } from './shared';
|
|
13
|
+
|
|
14
|
+
// Used to collect uncollectible invoices for a subscription and currency
|
|
15
|
+
export default {
|
|
16
|
+
action: 'collect-batch',
|
|
17
|
+
authPrincipal: false,
|
|
18
|
+
claims: {
|
|
19
|
+
authPrincipal: async ({ extraParams }: CallbackArgs) => {
|
|
20
|
+
const { paymentMethod } = await ensureSubscriptionForCollectBatch(
|
|
21
|
+
extraParams.subscriptionId,
|
|
22
|
+
extraParams.currencyId
|
|
23
|
+
);
|
|
24
|
+
return getAuthPrincipalClaim(paymentMethod, 'pay');
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
onConnect: async ({ userDid, userPk, extraParams }: CallbackArgs) => {
|
|
28
|
+
const { subscriptionId, currencyId } = extraParams;
|
|
29
|
+
const { amount, invoices, paymentCurrency, paymentMethod } = await ensureSubscriptionForCollectBatch(
|
|
30
|
+
subscriptionId,
|
|
31
|
+
currencyId
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (paymentMethod.type === 'arcblock') {
|
|
35
|
+
const tokens = [{ address: paymentCurrency.contract as string, value: amount }];
|
|
36
|
+
// @ts-ignore
|
|
37
|
+
const itx: TransferV3Tx = {
|
|
38
|
+
outputs: [{ owner: wallet.address, tokens, assets: [] }],
|
|
39
|
+
data: getTxMetadata({
|
|
40
|
+
subscriptionId,
|
|
41
|
+
currencyId,
|
|
42
|
+
invoices,
|
|
43
|
+
}),
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const claims: { [key: string]: object } = {
|
|
47
|
+
prepareTx: {
|
|
48
|
+
type: 'TransferV3Tx',
|
|
49
|
+
description: `Pay all past due invoices for ${subscriptionId}`,
|
|
50
|
+
partialTx: { from: userDid, pk: userPk, itx },
|
|
51
|
+
requirement: { tokens },
|
|
52
|
+
chainInfo: {
|
|
53
|
+
host: paymentMethod.settings?.arcblock?.api_host as string,
|
|
54
|
+
id: paymentMethod.settings?.arcblock?.chain_id as string,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return claims;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
63
|
+
},
|
|
64
|
+
onAuth: async ({ userDid, claims, extraParams }: CallbackArgs) => {
|
|
65
|
+
const { subscriptionId, currencyId } = extraParams;
|
|
66
|
+
const { invoices, paymentMethod } = await ensureSubscriptionForCollectBatch(subscriptionId, currencyId);
|
|
67
|
+
|
|
68
|
+
if (paymentMethod.type === 'arcblock') {
|
|
69
|
+
const client = paymentMethod.getOcapClient();
|
|
70
|
+
const claim = claims.find((x) => x.type === 'prepareTx');
|
|
71
|
+
|
|
72
|
+
const tx: Partial<Transaction> = client.decodeTx(claim.finalTx);
|
|
73
|
+
if (claim.delegator && claim.from) {
|
|
74
|
+
tx.delegator = claim.delegator;
|
|
75
|
+
tx.from = claim.from;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
const { buffer } = await client.encodeTransferV3Tx({ tx });
|
|
80
|
+
const txHash = await client.sendTransferV3Tx(
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
{ tx, wallet: fromAddress(userDid) },
|
|
83
|
+
getGasPayerExtra(buffer)
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const paymentIntents = await PaymentIntent.findAll({
|
|
87
|
+
where: {
|
|
88
|
+
invoice_id: invoices,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
for (const paymentIntent of paymentIntents) {
|
|
92
|
+
await paymentIntent.update({
|
|
93
|
+
status: 'succeeded',
|
|
94
|
+
amount_received: paymentIntent.amount,
|
|
95
|
+
capture_method: 'manual',
|
|
96
|
+
last_payment_error: null,
|
|
97
|
+
payment_details: {
|
|
98
|
+
arcblock: {
|
|
99
|
+
tx_hash: txHash,
|
|
100
|
+
payer: userDid,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await handlePaymentSucceed(paymentIntent);
|
|
106
|
+
|
|
107
|
+
// cleanup the queue
|
|
108
|
+
let exist = await paymentQueue.get(paymentIntent.id);
|
|
109
|
+
if (exist) {
|
|
110
|
+
await paymentQueue.delete(paymentIntent.id);
|
|
111
|
+
}
|
|
112
|
+
if (paymentIntent.invoice_id) {
|
|
113
|
+
exist = await invoiceQueue.get(paymentIntent.invoice_id);
|
|
114
|
+
if (exist) {
|
|
115
|
+
await invoiceQueue.delete(paymentIntent.invoice_id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return { hash: txHash };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
throw new Error(`Payment method ${paymentMethod.type} not supported`);
|
|
124
|
+
},
|
|
125
|
+
};
|
|
@@ -4,6 +4,7 @@ import { toTypeInfo } from '@arcblock/did';
|
|
|
4
4
|
import { toDelegateAddress } from '@arcblock/did-util';
|
|
5
5
|
import { BN } from '@ocap/util';
|
|
6
6
|
import { fromPublicKey } from '@ocap/wallet';
|
|
7
|
+
import isEmpty from 'lodash/isEmpty';
|
|
7
8
|
|
|
8
9
|
import { estimateMaxGasForTx, hasStakedForGas } from '../../integrations/blockchain/stake';
|
|
9
10
|
import { blocklet, wallet } from '../../libs/auth';
|
|
@@ -768,3 +769,34 @@ export async function ensureChangePaymentContext(subscriptionId: string) {
|
|
|
768
769
|
paymentCurrency,
|
|
769
770
|
};
|
|
770
771
|
}
|
|
772
|
+
|
|
773
|
+
export async function ensureSubscriptionForCollectBatch(subscriptionId: string, currencyId: string) {
|
|
774
|
+
const subscription = await Subscription.findByPk(subscriptionId);
|
|
775
|
+
if (!subscription) {
|
|
776
|
+
throw new Error(`Subscription ${subscriptionId} not found when prepare batch collect`);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const paymentCurrency = await PaymentCurrency.findByPk(currencyId);
|
|
780
|
+
if (!paymentCurrency) {
|
|
781
|
+
throw new Error(`PaymentCurrency ${currencyId} not found when prepare batch collect`);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
const [summary, detail] = await Invoice.getUncollectibleAmount({
|
|
785
|
+
subscriptionId: subscription.id,
|
|
786
|
+
customerId: subscription.customer_id,
|
|
787
|
+
currencyId,
|
|
788
|
+
});
|
|
789
|
+
if (isEmpty(summary) || !summary[currencyId] || summary[currencyId] === '0') {
|
|
790
|
+
throw new Error(`No uncollectible invoice found for subscription ${subscriptionId} to batch collect`);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
const paymentMethod = await PaymentMethod.findByPk(paymentCurrency.payment_method_id);
|
|
794
|
+
|
|
795
|
+
return {
|
|
796
|
+
subscription,
|
|
797
|
+
paymentCurrency: paymentCurrency as PaymentCurrency,
|
|
798
|
+
paymentMethod: paymentMethod as PaymentMethod,
|
|
799
|
+
amount: summary[currencyId],
|
|
800
|
+
invoices: detail[currencyId],
|
|
801
|
+
};
|
|
802
|
+
}
|
|
@@ -2,7 +2,6 @@ import { fromTokenToUnit } from '@ocap/util';
|
|
|
2
2
|
import { Router } from 'express';
|
|
3
3
|
import Joi from 'joi';
|
|
4
4
|
import pick from 'lodash/pick';
|
|
5
|
-
import type { WhereOptions } from 'sequelize';
|
|
6
5
|
|
|
7
6
|
import { getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
|
|
8
7
|
import logger from '../libs/logger';
|
|
@@ -112,22 +111,33 @@ const paginationSchema = Joi.object<{
|
|
|
112
111
|
pageSize: number;
|
|
113
112
|
livemode?: boolean;
|
|
114
113
|
active?: boolean;
|
|
114
|
+
status?: string;
|
|
115
115
|
name?: string;
|
|
116
116
|
description?: string;
|
|
117
|
+
q?: string;
|
|
118
|
+
o?: string;
|
|
117
119
|
}>({
|
|
118
120
|
page: Joi.number().integer().min(1).default(1),
|
|
119
121
|
pageSize: Joi.number().integer().min(1).max(100).default(20),
|
|
120
122
|
livemode: Joi.boolean().empty(''),
|
|
121
123
|
active: Joi.boolean().empty(''),
|
|
124
|
+
status: Joi.string().empty(''),
|
|
122
125
|
name: Joi.string().empty(''),
|
|
123
126
|
description: Joi.string().empty(''),
|
|
127
|
+
q: Joi.string().empty(''), // query
|
|
128
|
+
o: Joi.string().empty(''), // order
|
|
124
129
|
});
|
|
125
130
|
router.get('/', auth, async (req, res) => {
|
|
126
131
|
const { page, pageSize, active, livemode, name, description, ...query } = await paginationSchema.validateAsync(
|
|
127
132
|
req.query,
|
|
128
133
|
{ stripUnknown: false, allowUnknown: true }
|
|
129
134
|
);
|
|
130
|
-
const where
|
|
135
|
+
const where = getWhereFromKvQuery(query.q);
|
|
136
|
+
|
|
137
|
+
if (query.status) {
|
|
138
|
+
// 兼容处理,支持 status
|
|
139
|
+
where.active = query.status === 'active';
|
|
140
|
+
}
|
|
131
141
|
|
|
132
142
|
if (typeof active === 'boolean') {
|
|
133
143
|
where.active = active;
|
|
@@ -151,7 +161,7 @@ router.get('/', auth, async (req, res) => {
|
|
|
151
161
|
|
|
152
162
|
const { rows: list, count } = await Product.findAndCountAll({
|
|
153
163
|
where,
|
|
154
|
-
order: [['created_at', 'DESC']],
|
|
164
|
+
order: [['created_at', query.o === 'asc' ? 'ASC' : 'DESC']],
|
|
155
165
|
offset: (page - 1) * pageSize,
|
|
156
166
|
limit: pageSize,
|
|
157
167
|
include: [{ model: Price, as: 'prices' }],
|
|
@@ -1375,4 +1375,24 @@ router.get('/:id/usage-records', authPortal, (req, res) => {
|
|
|
1375
1375
|
createUsageRecordQueryFn(req.doc)(req, res);
|
|
1376
1376
|
});
|
|
1377
1377
|
|
|
1378
|
+
// Get invoice summary
|
|
1379
|
+
router.get('/:id/summary', authPortal, async (req, res) => {
|
|
1380
|
+
try {
|
|
1381
|
+
const subscription = await Subscription.findByPk(req.params.id);
|
|
1382
|
+
if (!subscription) {
|
|
1383
|
+
return res.status(404).json({ error: 'Subscription not found' });
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
const [summary] = await Invoice.getUncollectibleAmount({
|
|
1387
|
+
subscriptionId: subscription.id,
|
|
1388
|
+
currencyId: subscription.currency_id,
|
|
1389
|
+
customerId: subscription.customer_id,
|
|
1390
|
+
});
|
|
1391
|
+
return res.json(summary);
|
|
1392
|
+
} catch (err) {
|
|
1393
|
+
console.error(err);
|
|
1394
|
+
return res.status(400).json({ error: err.message });
|
|
1395
|
+
}
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1378
1398
|
export default router;
|
|
@@ -161,11 +161,11 @@ export class Customer extends Model<InferAttributes<Customer>, InferCreationAttr
|
|
|
161
161
|
|
|
162
162
|
public async getSummary() {
|
|
163
163
|
const { PaymentIntent, Refund, Invoice } = this.sequelize.models;
|
|
164
|
-
const [paid, due, refunded] = await Promise.all([
|
|
164
|
+
const [paid, [due], refunded] = await Promise.all([
|
|
165
165
|
// @ts-ignore
|
|
166
166
|
PaymentIntent!.getPaidAmountByCustomer(this.id),
|
|
167
167
|
// @ts-ignore
|
|
168
|
-
Invoice!.
|
|
168
|
+
Invoice!.getUncollectibleAmount({ customerId: this.id }),
|
|
169
169
|
// @ts-ignore
|
|
170
170
|
Refund!.getRefundAmountByCustomer(this.id),
|
|
171
171
|
]);
|
|
@@ -176,8 +176,8 @@ export class Customer extends Model<InferAttributes<Customer>, InferCreationAttr
|
|
|
176
176
|
public async canMakeNewPurchase(excludedInvoiceId: string = '') {
|
|
177
177
|
const { Invoice } = this.sequelize.models;
|
|
178
178
|
// @ts-ignore
|
|
179
|
-
const
|
|
180
|
-
return Object.entries(
|
|
179
|
+
const [summary] = await Invoice!.getUncollectibleAmount({ customerId: this.id, excludedInvoiceId });
|
|
180
|
+
return Object.entries(summary).every(([, amount]) => new BN(amount).lte(new BN(0)));
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
public getBalanceToApply(currencyId: string, amount: string) {
|
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
CustomerShipping,
|
|
20
20
|
DiscountAmount,
|
|
21
21
|
GroupedBN,
|
|
22
|
+
GroupedStrList,
|
|
22
23
|
PaymentError,
|
|
23
24
|
PaymentSettings,
|
|
24
25
|
SimpleCustomField,
|
|
@@ -523,44 +524,59 @@ export class Invoice extends Model<InferAttributes<Invoice>, InferCreationAttrib
|
|
|
523
524
|
return ['paid', 'void'].includes(this.status);
|
|
524
525
|
}
|
|
525
526
|
|
|
526
|
-
|
|
527
|
+
private static async _getUncollectibleAmount(where: WhereOptions<Invoice>): Promise<[GroupedBN, GroupedStrList]> {
|
|
527
528
|
const invoices = await Invoice.findAll({ where });
|
|
528
|
-
|
|
529
|
+
const summary: GroupedBN = {};
|
|
530
|
+
const detail: GroupedStrList = {};
|
|
531
|
+
|
|
532
|
+
invoices.forEach((invoice) => {
|
|
529
533
|
const key = invoice.currency_id;
|
|
530
|
-
if (!
|
|
531
|
-
|
|
534
|
+
if (!summary[key]) {
|
|
535
|
+
summary[key] = '0';
|
|
536
|
+
}
|
|
537
|
+
if (!detail[key]) {
|
|
538
|
+
detail[key] = [];
|
|
532
539
|
}
|
|
533
540
|
|
|
534
|
-
|
|
541
|
+
summary[key] = new BN(summary[key]).add(new BN(invoice.amount_remaining)).toString();
|
|
542
|
+
detail[key]!.push(invoice.id);
|
|
543
|
+
});
|
|
535
544
|
|
|
536
|
-
|
|
537
|
-
}, {});
|
|
545
|
+
return [summary, detail];
|
|
538
546
|
}
|
|
539
547
|
|
|
540
|
-
public static
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
+
public static getUncollectibleAmount({
|
|
549
|
+
customerId,
|
|
550
|
+
subscriptionId,
|
|
551
|
+
currencyId,
|
|
552
|
+
excludedInvoiceId,
|
|
553
|
+
}: {
|
|
554
|
+
customerId?: string;
|
|
555
|
+
subscriptionId?: string;
|
|
556
|
+
currencyId?: string;
|
|
557
|
+
excludedInvoiceId?: string;
|
|
558
|
+
}) {
|
|
559
|
+
if (!customerId && !subscriptionId) {
|
|
560
|
+
throw new Error('customerId or subscriptionId is required for getUncollectibleAmount');
|
|
548
561
|
}
|
|
549
|
-
|
|
550
|
-
return Invoice.getUncollectibleAmount(where);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
public static getUncollectibleAmountBySubscription(subscriptionId: string, excludedInvoiceId?: string) {
|
|
554
562
|
const where: WhereOptions<Invoice> = {
|
|
555
563
|
status: ['uncollectible'],
|
|
556
|
-
subscription_id: subscriptionId,
|
|
557
564
|
amount_remaining: { [Op.gt]: '0' },
|
|
558
565
|
};
|
|
566
|
+
if (currencyId) {
|
|
567
|
+
where.currency_id = currencyId;
|
|
568
|
+
}
|
|
569
|
+
if (customerId) {
|
|
570
|
+
where.customer_id = customerId;
|
|
571
|
+
}
|
|
572
|
+
if (subscriptionId) {
|
|
573
|
+
where.subscription_id = subscriptionId;
|
|
574
|
+
}
|
|
559
575
|
if (excludedInvoiceId) {
|
|
560
576
|
where.id = { [Op.not]: excludedInvoiceId };
|
|
561
577
|
}
|
|
562
578
|
|
|
563
|
-
return
|
|
579
|
+
return this._getUncollectibleAmount(where);
|
|
564
580
|
}
|
|
565
581
|
}
|
|
566
582
|
|
|
@@ -322,7 +322,7 @@ export class Subscription extends Model<InferAttributes<Subscription>, InferCrea
|
|
|
322
322
|
},
|
|
323
323
|
});
|
|
324
324
|
if (count === 2) {
|
|
325
|
-
// 当且仅当 有试用期的订阅更新了 && 恰好有 2
|
|
325
|
+
// 当且仅当 有试用期的订阅更新了 && 恰好有 2 次账单,此时订阅的试用期刚好结束
|
|
326
326
|
createEvent('Subscription', 'customer.subscription.trial_end', model, options).catch(console.error);
|
|
327
327
|
}
|
|
328
328
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { Op } from 'sequelize';
|
|
2
|
+
|
|
3
|
+
import { getWhereFromKvQuery } from '../../src/libs/api';
|
|
2
4
|
import dayjs from '../../src/libs/dayjs';
|
|
3
5
|
import {
|
|
4
6
|
createCodeGenerator,
|
|
5
7
|
createIdGenerator,
|
|
6
8
|
formatMetadata,
|
|
7
9
|
getDataObjectFromQuery,
|
|
8
|
-
|
|
9
10
|
getNextRetry,
|
|
10
11
|
tryWithTimeout,
|
|
11
12
|
} from '../../src/libs/util';
|
|
12
13
|
|
|
13
|
-
import { getWhereFromKvQuery } from '../../src/libs/api'
|
|
14
|
-
|
|
15
14
|
describe('createIdGenerator', () => {
|
|
16
15
|
it('should return a function that generates an ID with the specified prefix and size', () => {
|
|
17
16
|
const generateId = createIdGenerator('test', 10);
|
|
@@ -199,11 +198,7 @@ describe('getWhereFromKvQuery', () => {
|
|
|
199
198
|
const q = 'like-status:succ like-number:1533';
|
|
200
199
|
const result = getWhereFromKvQuery(q);
|
|
201
200
|
expect(result).toEqual({
|
|
202
|
-
[Op.or]: [
|
|
203
|
-
{ status: { [Op.like]: `%succ%` } },
|
|
204
|
-
{ number: { [Op.like]: `%1533%` } }
|
|
205
|
-
],
|
|
201
|
+
[Op.or]: [{ status: { [Op.like]: '%succ%' } }, { number: { [Op.like]: '%1533%' } }],
|
|
206
202
|
});
|
|
207
203
|
});
|
|
208
|
-
|
|
209
|
-
});
|
|
204
|
+
});
|
package/blocklet.yml
CHANGED
|
@@ -14,7 +14,7 @@ repository:
|
|
|
14
14
|
type: git
|
|
15
15
|
url: git+https://github.com/blocklet/payment-kit.git
|
|
16
16
|
specVersion: 1.2.8
|
|
17
|
-
version: 1.13.
|
|
17
|
+
version: 1.13.164
|
|
18
18
|
logo: logo.png
|
|
19
19
|
files:
|
|
20
20
|
- dist
|
|
@@ -93,7 +93,7 @@ navigation:
|
|
|
93
93
|
- id: billing
|
|
94
94
|
title:
|
|
95
95
|
en: Billing
|
|
96
|
-
zh:
|
|
96
|
+
zh: 我的账单
|
|
97
97
|
icon: ion:receipt-outline
|
|
98
98
|
link: /customer
|
|
99
99
|
section:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.164",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "cross-env COMPONENT_STORE_URL=https://test.store.blocklet.dev blocklet dev --open",
|
|
6
6
|
"eject": "vite eject",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@arcblock/jwt": "^1.18.110",
|
|
51
51
|
"@arcblock/ux": "^2.9.39",
|
|
52
52
|
"@blocklet/logger": "1.16.23",
|
|
53
|
-
"@blocklet/payment-react": "1.13.
|
|
53
|
+
"@blocklet/payment-react": "1.13.164",
|
|
54
54
|
"@blocklet/sdk": "1.16.23",
|
|
55
55
|
"@blocklet/ui-react": "^2.9.39",
|
|
56
56
|
"@blocklet/uploader": "^0.0.74",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@abtnode/types": "1.16.23",
|
|
112
112
|
"@arcblock/eslint-config-ts": "^0.2.4",
|
|
113
|
-
"@blocklet/payment-types": "1.13.
|
|
113
|
+
"@blocklet/payment-types": "1.13.164",
|
|
114
114
|
"@types/cookie-parser": "^1.4.6",
|
|
115
115
|
"@types/cors": "^2.8.17",
|
|
116
116
|
"@types/dotenv-flow": "^3.3.3",
|
|
@@ -149,5 +149,5 @@
|
|
|
149
149
|
"parser": "typescript"
|
|
150
150
|
}
|
|
151
151
|
},
|
|
152
|
-
"gitHead": "
|
|
152
|
+
"gitHead": "3172c382ed27451d90ea78ebd99087658fe7362c"
|
|
153
153
|
}
|