payment-kit 1.18.30 → 1.18.32

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 (51) hide show
  1. package/api/src/crons/metering-subscription-detection.ts +9 -0
  2. package/api/src/integrations/arcblock/nft.ts +1 -0
  3. package/api/src/integrations/blocklet/passport.ts +1 -1
  4. package/api/src/integrations/stripe/handlers/invoice.ts +2 -2
  5. package/api/src/integrations/stripe/handlers/setup-intent.ts +29 -1
  6. package/api/src/integrations/stripe/handlers/subscription.ts +19 -15
  7. package/api/src/integrations/stripe/resource.ts +81 -1
  8. package/api/src/libs/audit.ts +42 -0
  9. package/api/src/libs/invoice.ts +54 -7
  10. package/api/src/libs/notification/index.ts +72 -4
  11. package/api/src/libs/notification/template/base.ts +2 -0
  12. package/api/src/libs/notification/template/subscription-renew-failed.ts +1 -5
  13. package/api/src/libs/notification/template/subscription-renewed.ts +1 -5
  14. package/api/src/libs/notification/template/subscription-succeeded.ts +8 -18
  15. package/api/src/libs/notification/template/subscription-trial-start.ts +2 -10
  16. package/api/src/libs/notification/template/subscription-upgraded.ts +1 -5
  17. package/api/src/libs/payment.ts +47 -14
  18. package/api/src/libs/product.ts +1 -4
  19. package/api/src/libs/session.ts +600 -8
  20. package/api/src/libs/setting.ts +172 -0
  21. package/api/src/libs/subscription.ts +7 -69
  22. package/api/src/libs/ws.ts +5 -0
  23. package/api/src/queues/checkout-session.ts +42 -36
  24. package/api/src/queues/notification.ts +3 -2
  25. package/api/src/queues/payment.ts +33 -6
  26. package/api/src/queues/usage-record.ts +2 -10
  27. package/api/src/routes/checkout-sessions.ts +324 -187
  28. package/api/src/routes/connect/shared.ts +160 -38
  29. package/api/src/routes/connect/subscribe.ts +123 -64
  30. package/api/src/routes/payment-currencies.ts +3 -6
  31. package/api/src/routes/payment-links.ts +11 -1
  32. package/api/src/routes/payment-stats.ts +2 -2
  33. package/api/src/routes/payouts.ts +2 -1
  34. package/api/src/routes/settings.ts +45 -0
  35. package/api/src/routes/subscriptions.ts +1 -2
  36. package/api/src/store/migrations/20250408-subscription-grouping.ts +39 -0
  37. package/api/src/store/migrations/20250419-subscription-grouping.ts +69 -0
  38. package/api/src/store/models/checkout-session.ts +52 -0
  39. package/api/src/store/models/index.ts +1 -0
  40. package/api/src/store/models/payment-link.ts +6 -0
  41. package/api/src/store/models/subscription.ts +8 -6
  42. package/api/src/store/models/types.ts +31 -1
  43. package/api/tests/libs/session.spec.ts +423 -0
  44. package/api/tests/libs/subscription.spec.ts +0 -110
  45. package/blocklet.yml +3 -1
  46. package/package.json +20 -19
  47. package/scripts/sdk.js +486 -155
  48. package/src/locales/en.tsx +1 -1
  49. package/src/locales/zh.tsx +1 -1
  50. package/src/pages/admin/settings/vault-config/edit-form.tsx +1 -1
  51. package/src/pages/customer/subscription/change-payment.tsx +8 -3
@@ -5,7 +5,7 @@ import { sign } from '@arcblock/jwt';
5
5
  import { getWalletDid } from '@blocklet/sdk/lib/did';
6
6
  import type { DelegateState, TokenLimit } from '@ocap/client';
7
7
  import { toTxHash } from '@ocap/mcrypto';
8
- import { BN, fromTokenToUnit, fromUnitToToken } from '@ocap/util';
8
+ import { BN, fromUnitToToken } from '@ocap/util';
9
9
  import cloneDeep from 'lodash/cloneDeep';
10
10
  import type { LiteralUnion } from 'type-fest';
11
11
 
@@ -24,7 +24,7 @@ import type { TPaymentCurrency } from '../store/models/payment-currency';
24
24
  import { blocklet, ethWallet, wallet, getVaultAddress } from './auth';
25
25
  import logger from './logger';
26
26
  import { getBlockletJson, getUserOrAppInfo, OCAP_PAYMENT_TX_TYPE, resolveAddressChainTypes } from './util';
27
- import { CHARGE_SUPPORTED_CHAIN_TYPES, VAULT_BUFFER_THRESHOLD, EVM_CHAIN_TYPES } from './constants';
27
+ import { CHARGE_SUPPORTED_CHAIN_TYPES, EVM_CHAIN_TYPES } from './constants';
28
28
  import { getTokenByAddress } from '../integrations/arcblock/stake';
29
29
 
30
30
  export interface SufficientForPaymentResult {
@@ -44,6 +44,7 @@ export interface SufficientForPaymentResult {
44
44
  delegator?: string;
45
45
  state?: DelegateState;
46
46
  token?: { address: string; balance: string };
47
+ requestedAmount?: string;
47
48
  }
48
49
 
49
50
  export async function isDelegationSufficientForPayment(args: {
@@ -51,10 +52,17 @@ export async function isDelegationSufficientForPayment(args: {
51
52
  paymentCurrency: TPaymentCurrency;
52
53
  userDid: string;
53
54
  amount: string;
55
+ delegatorAmounts?: string[];
54
56
  }): Promise<SufficientForPaymentResult> {
55
- const { paymentCurrency, paymentMethod, userDid, amount } = args;
57
+ const { paymentCurrency, paymentMethod, userDid, amount, delegatorAmounts } = args;
56
58
  const tokenAddress = paymentCurrency.contract as string;
57
59
 
60
+ let totalAmount = new BN(amount);
61
+ const hasDelegatorAmounts = delegatorAmounts && delegatorAmounts.length > 0;
62
+ if (hasDelegatorAmounts) {
63
+ totalAmount = delegatorAmounts.reduce((sum, amt) => sum.add(new BN(amt)), new BN('0'));
64
+ }
65
+
58
66
  if (paymentMethod.type === 'arcblock') {
59
67
  // user have bond wallet did?
60
68
  const { user } = await blocklet.getUser(userDid, { enableConnectedAccount: true });
@@ -95,10 +103,25 @@ export async function isDelegationSufficientForPayment(args: {
95
103
  return { sufficient: false, reason: 'NO_TRANSFER_TO' };
96
104
  }
97
105
 
98
- const requested = new BN(amount);
99
- const allowance = new BN(tokenLimit.txAllowance);
100
- if (tokenLimit.txAllowance !== '0' && requested.gt(allowance)) {
101
- return { sufficient: false, reason: 'NO_ENOUGH_ALLOWANCE' };
106
+ // check allowance
107
+ if (tokenLimit.txAllowance !== '0') {
108
+ const allowance = new BN(tokenLimit.txAllowance);
109
+ if (hasDelegatorAmounts) {
110
+ // check each delegator amount
111
+ const invalidAmount = delegatorAmounts.find((amt) => new BN(amt).gt(allowance));
112
+
113
+ if (invalidAmount) {
114
+ return {
115
+ sufficient: false,
116
+ reason: 'NO_ENOUGH_ALLOWANCE',
117
+ };
118
+ }
119
+ } else if (totalAmount.gt(allowance)) {
120
+ return {
121
+ sufficient: false,
122
+ reason: 'NO_ENOUGH_ALLOWANCE',
123
+ };
124
+ }
102
125
  }
103
126
  }
104
127
 
@@ -108,11 +131,23 @@ export async function isDelegationSufficientForPayment(args: {
108
131
  if (!token) {
109
132
  return { sufficient: false, reason: 'NO_TOKEN' };
110
133
  }
111
- if (new BN(token.balance).lt(new BN(amount))) {
112
- return { sufficient: false, reason: 'NO_ENOUGH_TOKEN', token };
134
+
135
+ if (new BN(token.balance).lt(totalAmount)) {
136
+ return {
137
+ sufficient: false,
138
+ reason: 'NO_ENOUGH_TOKEN',
139
+ token,
140
+ requestedAmount: totalAmount.toString(),
141
+ };
113
142
  }
114
143
 
115
- return { sufficient: true, delegator, state, token };
144
+ return {
145
+ sufficient: true,
146
+ delegator,
147
+ state,
148
+ token,
149
+ requestedAmount: totalAmount.toString(),
150
+ };
116
151
  }
117
152
 
118
153
  if (paymentMethod.type === 'stripe') {
@@ -459,10 +494,8 @@ export async function checkDepositVaultAmount(paymentCurrencyId: string): Promis
459
494
  return { depositAmount: '0', message: 'No amount available to deposit after calculations' };
460
495
  }
461
496
 
462
- const bufferThreshold =
463
- paymentCurrency?.vault_config?.buffer_threshold ||
464
- fromTokenToUnit(VAULT_BUFFER_THRESHOLD, paymentCurrency.decimal).toString();
465
- if (new BN(amountToDeposit).lt(new BN(bufferThreshold))) {
497
+ const bufferThreshold = paymentCurrency?.vault_config?.buffer_threshold;
498
+ if (bufferThreshold && bufferThreshold !== '0' && new BN(amountToDeposit).lt(new BN(bufferThreshold))) {
466
499
  return { depositAmount: '0', message: 'Amount to deposit is less than the buffer threshold' };
467
500
  }
468
501
 
@@ -12,10 +12,7 @@ export async function getMainProductName(subscriptionId: string): Promise<string
12
12
  return subscription.description!;
13
13
  }
14
14
 
15
- const checkoutSession = await CheckoutSession.findOne({
16
- where: {
17
- subscription_id: subscriptionId,
18
- },
15
+ const checkoutSession = await CheckoutSession.findBySubscriptionId(subscriptionId, {
19
16
  attributes: ['line_items'],
20
17
  });
21
18
  const priceId: string = checkoutSession?.line_items.find((x) => !x.cross_sell)?.price_id as string;