payment-kit 1.20.15 → 1.20.16

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.
@@ -1,10 +1,19 @@
1
- import { BN } from '@ocap/util';
1
+ import { BN, fromUnitToToken } from '@ocap/util';
2
2
 
3
3
  import pick from 'lodash/pick';
4
- import { Coupon, Customer, Discount, PromotionCode, Subscription } from '../../store/models';
5
- import type { CheckoutSession, TLineItemExpanded } from '../../store/models';
4
+ import {
5
+ Coupon,
6
+ Customer,
7
+ Discount,
8
+ PromotionCode,
9
+ Subscription,
10
+ CheckoutSession,
11
+ PaymentCurrency,
12
+ } from '../../store/models';
13
+ import type { TLineItemExpanded } from '../../store/models';
6
14
  import logger from '../logger';
7
15
  import { emitAsync } from '../event';
16
+ import { formatNumber } from '../util';
8
17
 
9
18
  export function validCoupon(coupon: Coupon, lineItems?: TLineItemExpanded[]) {
10
19
  if (!coupon.valid) {
@@ -75,13 +84,20 @@ export async function validPromotionCode(
75
84
  ? promotionCode.restrictions?.minimum_amount
76
85
  : promotionCode.restrictions?.currency_options?.[currencyId]?.minimum_amount;
77
86
 
87
+ const currency = await PaymentCurrency.findByPk(currencyId);
78
88
  if (minimumAmount) {
79
89
  const amountBN = new BN(amount);
80
90
  const minimumBN = new BN(minimumAmount);
81
91
  if (amountBN.lt(minimumBN)) {
92
+ if (!currency) {
93
+ return {
94
+ valid: false,
95
+ reason: 'This promotion requires a minimum purchase amount. Please add more items to your cart.',
96
+ };
97
+ }
82
98
  return {
83
99
  valid: false,
84
- reason: 'This promotion requires a minimum purchase amount. Please add more items to your cart.',
100
+ reason: `This promotion requires a minimum purchase amount of ${formatNumber(fromUnitToToken(minimumBN, currency?.decimal || 2))} ${currency?.symbol}. Please add more items to your cart.`,
85
101
  };
86
102
  }
87
103
  }
@@ -296,7 +312,7 @@ async function processSubscriptionDiscount({
296
312
  baseDiscountData: any;
297
313
  existingDiscountMap: Map<string, any>;
298
314
  checkoutSessionId: string;
299
- }): Promise<{ discountRecord: any; shouldUpdateUsage: boolean }> {
315
+ }): Promise<{ discountRecord: Discount; shouldUpdateUsage: boolean }> {
300
316
  try {
301
317
  const existingDiscount = existingDiscountMap.get(subscriptionId);
302
318
 
@@ -342,6 +358,7 @@ async function processSubscriptionDiscount({
342
358
  const newDiscount = await Discount.create({
343
359
  ...baseDiscountData,
344
360
  subscription_id: subscriptionId,
361
+ confirmed: false,
345
362
  metadata: {
346
363
  ...baseDiscountData.metadata,
347
364
  subscription_id: subscriptionId,
@@ -375,7 +392,7 @@ async function processNonSubscriptionDiscount(
375
392
  baseDiscountData: any,
376
393
  existingDiscountMap: Map<string, any>,
377
394
  checkoutSessionId: string
378
- ): Promise<{ discountRecord: any; shouldUpdateUsage: boolean }> {
395
+ ): Promise<{ discountRecord: Discount; shouldUpdateUsage: boolean }> {
379
396
  try {
380
397
  const existingDiscount = existingDiscountMap.get('no_subscription');
381
398
 
@@ -412,7 +429,10 @@ async function processNonSubscriptionDiscount(
412
429
  }
413
430
 
414
431
  // Create new discount record
415
- const newDiscount = await Discount.create(baseDiscountData);
432
+ const newDiscount = await Discount.create({
433
+ ...baseDiscountData,
434
+ confirmed: false,
435
+ });
416
436
 
417
437
  // Lock coupon and promotion code when discount is created
418
438
  await lockDiscountResources(baseDiscountData.coupon_id, baseDiscountData.promotion_code_id);
@@ -710,6 +730,13 @@ export async function createDiscountRecordsForCheckout({
710
730
  updatedPromotionCodes,
711
731
  checkoutSessionId: checkoutSession.id,
712
732
  });
733
+ await Promise.all(
734
+ discountRecords.map(async (discountRecord) => {
735
+ await discountRecord.update({
736
+ confirmed: true,
737
+ });
738
+ })
739
+ );
713
740
  } catch (error) {
714
741
  logger.error('Failed to update usage counts, but continuing', {
715
742
  couponId: coupon.id,
@@ -1,8 +1,9 @@
1
1
  import { BN } from '@ocap/util';
2
- import { Coupon, Discount, PaymentCurrency, PromotionCode } from '../../store/models';
2
+ import { Coupon, Discount, PaymentCurrency, PromotionCode, CheckoutSession } from '../../store/models';
3
3
  import type { TLineItemExpanded } from '../../store/models';
4
4
  import { getPriceUintAmountByCurrency } from '../price';
5
5
  import { validCoupon, checkPromotionCodeEligibility, calculateDiscountAmount } from './coupon';
6
+ import { emitAsync } from '../event';
6
7
  import logger from '../logger';
7
8
 
8
9
  const getItemsTotalAmount = (lineItems: TLineItemExpanded[], currencyId: string, options?: { trialing?: boolean }) => {
@@ -347,3 +348,84 @@ export async function applySubscriptionDiscount({
347
348
 
348
349
  return result;
349
350
  }
351
+
352
+ async function rollbackUsageForResource<T extends Coupon | PromotionCode>(
353
+ resource: T,
354
+ resourceType: 'coupon' | 'promotion-code'
355
+ ): Promise<void> {
356
+ const currentUsage = resource.times_redeemed || 0;
357
+ if (currentUsage <= 0) return;
358
+
359
+ if (resourceType === 'coupon') {
360
+ await (resource as Coupon).update({
361
+ times_redeemed: currentUsage - 1,
362
+ valid: true,
363
+ });
364
+ } else {
365
+ await (resource as PromotionCode).update({
366
+ times_redeemed: currentUsage - 1,
367
+ active: true,
368
+ });
369
+ }
370
+
371
+ logger.info('Updated usage for resource', {
372
+ resourceId: resource.id,
373
+ resourceType,
374
+ currentUsage: currentUsage - 1,
375
+ });
376
+
377
+ emitAsync('discount-status.queued', resource, resourceType, true);
378
+ }
379
+
380
+ export async function rollbackDiscountUsageForCheckoutSession(checkoutSessionId: string): Promise<void> {
381
+ try {
382
+ const checkoutSession = await CheckoutSession.findByPk(checkoutSessionId);
383
+ if (!checkoutSession) {
384
+ logger.error('Checkout session not found', { checkoutSessionId });
385
+ return;
386
+ }
387
+
388
+ if (checkoutSession.status === 'complete') {
389
+ logger.error('Cannot rollback completed session', { checkoutSessionId });
390
+ return;
391
+ }
392
+
393
+ const discounts = (await Discount.findAll({
394
+ where: { checkout_session_id: checkoutSessionId },
395
+ include: [
396
+ { model: Coupon, as: 'coupon' },
397
+ { model: PromotionCode, as: 'promotionCode', required: false },
398
+ ],
399
+ })) as (Discount & { coupon: Coupon; promotionCode?: PromotionCode })[];
400
+
401
+ if (discounts.length === 0) {
402
+ logger.info('No discounts found for checkout session', { checkoutSessionId });
403
+ return;
404
+ }
405
+
406
+ const uniqueCoupons = new Map<string, Coupon>();
407
+ const uniquePromotionCodes = new Map<string, PromotionCode>();
408
+
409
+ discounts.forEach((discount) => {
410
+ if (discount.confirmed) {
411
+ if (discount.coupon?.id && !uniqueCoupons.has(discount.coupon.id)) {
412
+ uniqueCoupons.set(discount.coupon.id, discount.coupon);
413
+ }
414
+ if (discount.promotionCode?.id && !uniquePromotionCodes.has(discount.promotionCode.id)) {
415
+ uniquePromotionCodes.set(discount.promotionCode.id, discount.promotionCode);
416
+ }
417
+ }
418
+ });
419
+
420
+ const rollbackPromises = [
421
+ ...Array.from(uniquePromotionCodes.values()).map((pc) => rollbackUsageForResource(pc, 'promotion-code')),
422
+ ...Array.from(uniqueCoupons.values()).map((c) => rollbackUsageForResource(c, 'coupon')),
423
+ ];
424
+
425
+ await Promise.all(rollbackPromises);
426
+
427
+ await Promise.all(discounts.map((discount) => discount.destroy()));
428
+ } catch (error) {
429
+ logger.error('Discount rollback failed', { checkoutSessionId, error: error.message });
430
+ }
431
+ }
@@ -21,6 +21,7 @@ export const vendorTimeoutMinutes: number = process.env.VENDOR_TIMEOUT_MINUTES
21
21
  : 10; // 默认 10 分钟超时
22
22
 
23
23
  export const shortUrlApiKey: string = process.env.SHORT_URL_API_KEY || '';
24
+ export const shortUrlDomain: string = process.env.SHORT_URL_DOMAIN || 's.abtnet.io';
24
25
 
25
26
  // sequelize 配置相关
26
27
  export const sequelizeOptionsPoolMin: number = process.env.SEQUELIZE_OPTIONS_POOL_MIN
@@ -368,7 +368,7 @@ export function isCreditSufficientForPayment(args: {
368
368
  const balance = tokens[paymentCurrency.id] || '0';
369
369
 
370
370
  if (amount === '0') {
371
- return { sufficient: false, balance, reason: 'NO_REQUIREMENT' };
371
+ return { sufficient: true, balance };
372
372
  }
373
373
 
374
374
  if (new BN(balance).lt(new BN(amount))) {
@@ -1,5 +1,5 @@
1
1
  import logger from './logger';
2
- import { shortUrlApiKey } from './env';
2
+ import { shortUrlApiKey, shortUrlDomain } from './env';
3
3
 
4
4
  interface ShortUrlResponse {
5
5
  shortUrl: string;
@@ -43,14 +43,14 @@ export async function formatToShortUrl({
43
43
  maxVisits,
44
44
  tags: [],
45
45
  shortCodeLength: 8,
46
- domain: 's.abtnet.io',
46
+ domain: shortUrlDomain,
47
47
  findIfExists: true,
48
48
  validateUrl: true,
49
49
  forwardQuery: true,
50
50
  crawlable: true,
51
51
  };
52
52
 
53
- const response = await fetch('https://s.abtnet.io/rest/v3/short-urls', {
53
+ const response = await fetch(`https://${shortUrlDomain}/rest/v3/short-urls`, {
54
54
  method: 'POST',
55
55
  headers: {
56
56
  'Content-Type': 'application/json',
@@ -21,6 +21,7 @@ import {
21
21
  SubscriptionItem,
22
22
  } from '../store/models';
23
23
  import { getCheckoutSessionSubscriptionIds } from '../libs/session';
24
+ import { rollbackDiscountUsageForCheckoutSession } from '../libs/discount/discount';
24
25
 
25
26
  type CheckoutSessionJob = {
26
27
  id: string;
@@ -240,6 +241,8 @@ events.on('checkout.session.expired', async (checkoutSession: CheckoutSession) =
240
241
  );
241
242
  }
242
243
 
244
+ await rollbackDiscountUsageForCheckoutSession(checkoutSession.id);
245
+
243
246
  // update price lock status
244
247
  for (const item of checkoutSession.line_items) {
245
248
  const price = await Price.findByPk(item.price_id);
@@ -914,6 +914,11 @@ export const handlePayment = async (job: PaymentJob) => {
914
914
  return;
915
915
  }
916
916
 
917
+ if (paymentIntent.amount === '0') {
918
+ await handlePaymentSucceed(paymentIntent);
919
+ return;
920
+ }
921
+
917
922
  await paymentIntent.update({ status: 'processing', last_payment_error: null });
918
923
 
919
924
  if (paymentMethod.type === 'arcblock') {
@@ -105,8 +105,8 @@ import {
105
105
  createDiscountRecordsForCheckout,
106
106
  updateSubscriptionDiscountReferences,
107
107
  } from '../libs/discount/coupon';
108
+ import { rollbackDiscountUsageForCheckoutSession, applyDiscountsToLineItems } from '../libs/discount/discount';
108
109
  import { formatToShortUrl } from '../libs/url';
109
- import { applyDiscountsToLineItems } from '../libs/discount/discount';
110
110
 
111
111
  const router = Router();
112
112
 
@@ -2785,6 +2785,7 @@ router.delete('/:id/remove-promotion', user, ensureCheckoutSessionOpen, async (r
2785
2785
  const trialSetup = getSubscriptionTrialSetup(checkoutSession.subscription_data as any, currency.id);
2786
2786
  const isTrialing = trialSetup.trialInDays > 0 || trialSetup.trialEnd > now;
2787
2787
 
2788
+ await rollbackDiscountUsageForCheckoutSession(checkoutSession.id);
2788
2789
  // Calculate original amounts without any discounts
2789
2790
  const originalResult = await applyDiscountsToLineItems({
2790
2791
  lineItems: originalItems,
@@ -52,7 +52,9 @@ export default {
52
52
  amount: fastCheckoutAmount,
53
53
  });
54
54
 
55
- if (delegation.sufficient === false) {
55
+ const requiredStake = !subscription!.billing_thresholds?.no_stake;
56
+
57
+ if (delegation.sufficient === false || !requiredStake) {
56
58
  claimsList.push({
57
59
  signature: await getDelegationTxClaim({
58
60
  mode: 'subscription',
@@ -69,16 +71,22 @@ export default {
69
71
  });
70
72
  }
71
73
 
72
- claimsList.push({
73
- prepareTx: await getStakeTxClaim({
74
- userDid,
75
- userPk,
76
- paymentCurrency,
77
- paymentMethod,
78
- items,
79
- subscription: subscription!,
80
- }),
81
- });
74
+ if (requiredStake) {
75
+ claimsList.push({
76
+ prepareTx: await getStakeTxClaim({
77
+ userDid,
78
+ userPk,
79
+ paymentCurrency,
80
+ paymentMethod,
81
+ items,
82
+ subscription: subscription!,
83
+ }),
84
+ });
85
+ }
86
+
87
+ if (claimsList.length === 0) {
88
+ throw new Error('No available claims for your subscription at this time.');
89
+ }
82
90
 
83
91
  return claimsList;
84
92
  }
@@ -123,9 +131,12 @@ export default {
123
131
  },
124
132
  });
125
133
 
134
+ const requiredStake = !subscription!.billing_thresholds?.no_stake;
135
+
126
136
  // 判断是否为最后一步
127
137
  const staking = result.find((x: any) => x.claim?.type === 'prepareTx' && x.claim?.meta?.purpose === 'staking');
128
- const isFinalStep = (paymentMethod.type === 'arcblock' && staking) || paymentMethod.type !== 'arcblock';
138
+ const isFinalStep =
139
+ (paymentMethod.type === 'arcblock' && (staking || !requiredStake)) || paymentMethod.type !== 'arcblock';
129
140
 
130
141
  if (!isFinalStep) {
131
142
  await updateSession({
@@ -68,6 +68,7 @@ export default {
68
68
  paymentCurrency,
69
69
  paymentMethod,
70
70
  items,
71
+ requiredStake: false,
71
72
  });
72
73
  }
73
74
 
@@ -42,6 +42,7 @@ export default {
42
42
  trialing: true,
43
43
  billingThreshold,
44
44
  items: subscription!.items as TLineItemExpanded[],
45
+ requiredStake: false,
45
46
  }),
46
47
  ],
47
48
  };
@@ -774,6 +774,7 @@ export async function getDelegationTxClaim({
774
774
  paymentCurrency,
775
775
  requiredStake,
776
776
  });
777
+
777
778
  if (mode === 'delegation') {
778
779
  tokenRequirements = [];
779
780
  }
@@ -1080,9 +1081,15 @@ export async function getTokenRequirements({
1080
1081
  billingThreshold = 0,
1081
1082
  requiredStake,
1082
1083
  }: TokenRequirementArgs) {
1083
- const tokenRequirements = [];
1084
+ const tokenRequirements: { address: string; value: string }[] = [];
1084
1085
  let amount = await getFastCheckoutAmount({ items, mode, currencyId: paymentCurrency.id, trialing: !!trialing });
1085
1086
 
1087
+ const addStakeRequired = requiredStake && ((paymentMethod.type === 'arcblock' && mode !== 'delegation') || mode === 'setup');
1088
+
1089
+ if (!addStakeRequired && amount === '0') {
1090
+ return tokenRequirements;
1091
+ }
1092
+
1086
1093
  // If the app has not staked, we need to add the gas fee to the amount
1087
1094
  if ((await hasStakedForGas(paymentMethod)) === false) {
1088
1095
  const maxGas = await estimateMaxGasForTx(paymentMethod);
@@ -1106,7 +1113,7 @@ export async function getTokenRequirements({
1106
1113
  }
1107
1114
 
1108
1115
  // Add stake requirement to token requirement
1109
- if (requiredStake && ((paymentMethod.type === 'arcblock' && mode !== 'delegation') || mode === 'setup')) {
1116
+ if (addStakeRequired) {
1110
1117
  const staking = getSubscriptionStakeSetup(
1111
1118
  items,
1112
1119
  paymentCurrency.id,
@@ -1115,6 +1122,8 @@ export async function getTokenRequirements({
1115
1122
  const exist = tokenRequirements.find((x) => x.address === paymentCurrency.contract);
1116
1123
  if (exist) {
1117
1124
  exist.value = new BN(exist.value).add(staking.licensed).add(staking.metered).toString();
1125
+ } else {
1126
+ tokenRequirements.push({ address: paymentCurrency.contract as string, value: staking.licensed.add(staking.metered).toString() });
1118
1127
  }
1119
1128
  }
1120
1129
 
@@ -320,7 +320,14 @@ router.get('/pending-amount', authMine, async (req, res) => {
320
320
  where['payload.subscription_id'] = req.query.subscription_id;
321
321
  }
322
322
  if (req.query.customer_id) {
323
- where['payload.customer_id'] = req.query.customer_id;
323
+ if (typeof req.query.customer_id !== 'string') {
324
+ return res.status(400).json({ error: 'Customer ID must be a string' });
325
+ }
326
+ const customer = await Customer.findByPkOrDid(req.query.customer_id);
327
+ if (!customer) {
328
+ return res.status(404).json({ error: 'Customer not found' });
329
+ }
330
+ where['payload.customer_id'] = customer.id;
324
331
  }
325
332
  const [summary] = await MeterEvent.getPendingAmounts({
326
333
  subscriptionId: req.query.subscription_id as string,
@@ -44,6 +44,7 @@ const ProductAndPriceSchema = Joi.object({
44
44
  'string.pattern.base':
45
45
  'statement_descriptor should be at least one letter and cannot include Chinese characters and special characters such as <, >、"、’ or \\',
46
46
  })
47
+ .allow(null, '')
47
48
  .empty('')
48
49
  .optional(),
49
50
  unit_label: Joi.string().max(12).empty('').optional(),
@@ -0,0 +1,21 @@
1
+ import { DataTypes } from 'sequelize';
2
+ import { Migration, safeApplyColumnChanges } from '../migrate';
3
+
4
+ export const up: Migration = async ({ context }) => {
5
+ await safeApplyColumnChanges(context, {
6
+ discounts: [
7
+ {
8
+ name: 'confirmed',
9
+ field: {
10
+ type: DataTypes.BOOLEAN,
11
+ defaultValue: true,
12
+ allowNull: false,
13
+ },
14
+ },
15
+ ],
16
+ });
17
+ };
18
+
19
+ export const down: Migration = async ({ context }) => {
20
+ await context.removeColumn('discounts', 'confirmed');
21
+ };
@@ -18,6 +18,7 @@ export class Discount extends Model<InferAttributes<Discount>, InferCreationAttr
18
18
  declare checkout_session_id?: string;
19
19
  declare invoice_id?: string;
20
20
  declare invoice_item_id?: string;
21
+ declare confirmed?: boolean;
21
22
 
22
23
  declare start: number;
23
24
  declare end: number | null;
@@ -101,13 +102,23 @@ export class Discount extends Model<InferAttributes<Discount>, InferCreationAttr
101
102
  };
102
103
 
103
104
  public static initialize(sequelize: any) {
104
- this.init(Discount.GENESIS_ATTRIBUTES, {
105
- sequelize,
106
- modelName: 'Discount',
107
- tableName: 'discounts',
108
- createdAt: 'created_at',
109
- updatedAt: 'updated_at',
110
- });
105
+ this.init(
106
+ {
107
+ ...Discount.GENESIS_ATTRIBUTES,
108
+ confirmed: {
109
+ type: DataTypes.BOOLEAN,
110
+ defaultValue: true,
111
+ allowNull: false,
112
+ },
113
+ },
114
+ {
115
+ sequelize,
116
+ modelName: 'Discount',
117
+ tableName: 'discounts',
118
+ createdAt: 'created_at',
119
+ updatedAt: 'updated_at',
120
+ }
121
+ );
111
122
  }
112
123
 
113
124
  public static associate(models: any) {
@@ -1,7 +1,7 @@
1
1
  import { CheckoutSession, TCheckoutSession } from './checkout-session';
2
2
  import { Coupon, TCoupon } from './coupon';
3
3
  import { Customer, TCustomer } from './customer';
4
- import { Discount } from './discount';
4
+ import { Discount, TDiscount } from './discount';
5
5
  import { Event, TEvent } from './event';
6
6
  import { Invoice, TInvoice } from './invoice';
7
7
  import { InvoiceItem, TInvoiceItem } from './invoice-item';
@@ -326,9 +326,16 @@ export type TCouponExpanded = TCoupon & {
326
326
  object: 'coupon';
327
327
  applied_products?: TProduct[];
328
328
  promotion_codes?: TPromotionCode[];
329
+ currency?: TPaymentCurrency;
329
330
  };
330
331
 
331
332
  export type TPromotionCodeExpanded = TPromotionCode & {
332
333
  object: 'promotion_code';
333
334
  coupon?: TCoupon;
334
335
  };
336
+
337
+ export type TDiscountExpanded = TDiscount & {
338
+ object: 'discount';
339
+ coupon?: TCouponExpanded;
340
+ promotionCode?: TPromotionCodeExpanded;
341
+ };
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.20.15
17
+ version: 1.20.16
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
@@ -73,6 +73,12 @@ environments:
73
73
  default: ''
74
74
  secure: true
75
75
  shared: false
76
+ - name: SHORT_URL_DOMAIN
77
+ description: Short URL service domain
78
+ required: false
79
+ default: s.abtnet.io
80
+ secure: false
81
+ shared: false
76
82
  capabilities:
77
83
  navigation: true
78
84
  clusterMode: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.20.15",
3
+ "version": "1.20.16",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "lint": "tsc --noEmit && eslint src api/src --ext .mjs,.js,.jsx,.ts,.tsx",
@@ -45,32 +45,32 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@abtnode/cron": "^1.16.52-beta-20250912-112002-e3499e9c",
48
- "@arcblock/did": "^1.25.1",
48
+ "@arcblock/did": "^1.25.3",
49
49
  "@arcblock/did-connect-react": "^3.1.41",
50
50
  "@arcblock/did-connect-storage-nedb": "^1.8.0",
51
- "@arcblock/did-util": "^1.25.1",
52
- "@arcblock/jwt": "^1.25.1",
51
+ "@arcblock/did-util": "^1.25.3",
52
+ "@arcblock/jwt": "^1.25.3",
53
53
  "@arcblock/ux": "^3.1.41",
54
- "@arcblock/validator": "^1.25.1",
55
- "@blocklet/did-space-js": "^1.1.24",
54
+ "@arcblock/validator": "^1.25.3",
55
+ "@blocklet/did-space-js": "^1.1.26",
56
56
  "@blocklet/error": "^0.2.5",
57
57
  "@blocklet/js-sdk": "^1.16.52-beta-20250912-112002-e3499e9c",
58
58
  "@blocklet/logger": "^1.16.52-beta-20250912-112002-e3499e9c",
59
- "@blocklet/payment-react": "1.20.15",
60
- "@blocklet/payment-vendor": "1.20.15",
59
+ "@blocklet/payment-react": "1.20.16",
60
+ "@blocklet/payment-vendor": "1.20.16",
61
61
  "@blocklet/sdk": "^1.16.52-beta-20250912-112002-e3499e9c",
62
62
  "@blocklet/ui-react": "^3.1.41",
63
- "@blocklet/uploader": "^0.2.11",
63
+ "@blocklet/uploader": "^0.2.12",
64
64
  "@blocklet/xss": "^0.2.7",
65
65
  "@mui/icons-material": "^7.1.2",
66
66
  "@mui/lab": "7.0.0-beta.14",
67
67
  "@mui/material": "^7.1.2",
68
68
  "@mui/system": "^7.1.1",
69
- "@ocap/asset": "^1.25.1",
70
- "@ocap/client": "^1.25.1",
71
- "@ocap/mcrypto": "^1.25.1",
72
- "@ocap/util": "^1.25.1",
73
- "@ocap/wallet": "^1.25.1",
69
+ "@ocap/asset": "^1.25.3",
70
+ "@ocap/client": "^1.25.3",
71
+ "@ocap/mcrypto": "^1.25.3",
72
+ "@ocap/util": "^1.25.3",
73
+ "@ocap/wallet": "^1.25.3",
74
74
  "@stripe/react-stripe-js": "^2.9.0",
75
75
  "@stripe/stripe-js": "^2.4.0",
76
76
  "ahooks": "^3.8.5",
@@ -126,7 +126,7 @@
126
126
  "devDependencies": {
127
127
  "@abtnode/types": "^1.16.52-beta-20250912-112002-e3499e9c",
128
128
  "@arcblock/eslint-config-ts": "^0.3.3",
129
- "@blocklet/payment-types": "1.20.15",
129
+ "@blocklet/payment-types": "1.20.16",
130
130
  "@types/cookie-parser": "^1.4.9",
131
131
  "@types/cors": "^2.8.19",
132
132
  "@types/debug": "^4.1.12",
@@ -157,7 +157,7 @@
157
157
  "vite": "^7.0.0",
158
158
  "vite-node": "^3.2.4",
159
159
  "vite-plugin-babel-import": "^2.0.5",
160
- "vite-plugin-blocklet": "^0.11.0",
160
+ "vite-plugin-blocklet": "^0.11.1",
161
161
  "vite-plugin-node-polyfills": "^0.23.0",
162
162
  "vite-plugin-svgr": "^4.3.0",
163
163
  "vite-tsconfig-paths": "^5.1.4",
@@ -173,5 +173,5 @@
173
173
  "parser": "typescript"
174
174
  }
175
175
  },
176
- "gitHead": "d205c3b1ec7d2b819e375ed2eb8b70c9d48f0bcb"
176
+ "gitHead": "ebf0677dd4414d4abc4129d6663a7e9ddb415281"
177
177
  }