payment-kit 1.13.72 → 1.13.73

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.
@@ -2,7 +2,7 @@ import { mintNftForCheckoutSession } from '../integrations/blockchain/nft';
2
2
  import { ensurePassportIssued, ensurePassportRevoked } from '../integrations/blocklet/passport';
3
3
  import { events } from '../libs/event';
4
4
  import logger from '../libs/logger';
5
- import type { CheckoutSession, Subscription } from '../store/models';
5
+ import { CheckoutSession, Price, Subscription } from '../store/models';
6
6
 
7
7
  // eslint-disable-next-line require-await
8
8
  export async function startCheckoutSessionQueue() {
@@ -13,6 +13,17 @@ export async function startCheckoutSessionQueue() {
13
13
  mintNftForCheckoutSession(checkoutSession.id).catch((err) => {
14
14
  logger.error('mintNftForCheckoutSession failed', { error: err, checkoutSession: checkoutSession.id });
15
15
  });
16
+
17
+ // lock prices used
18
+ Price.update(
19
+ { locked: true },
20
+ { where: { id: checkoutSession.line_items.map((x) => x.upsell_price_id || x.price_id) } }
21
+ ).catch((err) => {
22
+ logger.error('lock price on checkout session complete failed', {
23
+ error: err,
24
+ checkoutSession: checkoutSession.id,
25
+ });
26
+ });
16
27
  });
17
28
 
18
29
  events.on('customer.subscription.deleted', (subscription: Subscription) => {
@@ -8,7 +8,14 @@ import { BN, fromUnitToToken } from '@ocap/util';
8
8
  import cloneDeep from 'lodash/cloneDeep';
9
9
  import type { LiteralUnion } from 'type-fest';
10
10
 
11
- import { Invoice, PaymentCurrency, PaymentIntent, PaymentMethod } from '../store/models';
11
+ import {
12
+ CheckoutSession,
13
+ Invoice,
14
+ PaymentCurrency,
15
+ PaymentIntent,
16
+ PaymentMethod,
17
+ TLineItemExpanded,
18
+ } from '../store/models';
12
19
  import type { TPaymentCurrency } from '../store/models/payment-currency';
13
20
  import { blocklet, wallet } from './auth';
14
21
  import logger from './logger';
@@ -80,7 +87,7 @@ export async function isDelegationSufficientForPayment(args: {
80
87
 
81
88
  const requested = new BN(amount);
82
89
  const allowance = new BN(tokenLimit.txAllowance);
83
- if (requested.gt(allowance)) {
90
+ if (tokenLimit.txAllowance !== '0' && requested.gt(allowance)) {
84
91
  return { sufficient: false, reason: 'NO_ENOUGH_ALLOWANCE' };
85
92
  }
86
93
  }
@@ -181,6 +188,7 @@ export async function getPaymentDetail(userDid: string, invoice: Invoice): Promi
181
188
  }
182
189
 
183
190
  export async function getTokenLimitsForDelegation(
191
+ checkoutSession: CheckoutSession,
184
192
  paymentMethod: PaymentMethod,
185
193
  paymentCurrency: PaymentCurrency,
186
194
  address: string,
@@ -189,11 +197,15 @@ export async function getTokenLimitsForDelegation(
189
197
  const client = paymentMethod.getOcapClient();
190
198
  const { state } = await client.getDelegateState({ address });
191
199
 
200
+ const items = checkoutSession.line_items as TLineItemExpanded[];
201
+ const hasMetered = items.some((x) => x.price.recurring?.usage_type === 'metered');
202
+ const allowance = hasMetered ? '0' : amount;
203
+
192
204
  // @ts-ignore
193
205
  const entry: TokenLimit = {
194
206
  address: paymentCurrency.contract as string,
195
207
  to: [wallet.address], // FIXME: may broken if we have vault, migrated
196
- txAllowance: amount,
208
+ txAllowance: allowance,
197
209
  totalAllowance: '0',
198
210
  txCount: 0,
199
211
  validUntil: 0,
@@ -204,6 +216,11 @@ export async function getTokenLimitsForDelegation(
204
216
  return [entry];
205
217
  }
206
218
 
219
+ // If we have metered items, we should not limit tx allowance(set to 0)
220
+ if (hasMetered) {
221
+ return [entry];
222
+ }
223
+
207
224
  const op = (state as DelegateState).ops.find((x) => x.key === OCAP_PAYMENT_TX_TYPE);
208
225
  if (op && Array.isArray(op.value.limit?.tokens) && op.value.limit.tokens.length > 0) {
209
226
  const tokenLimits = cloneDeep(op.value.limit.tokens);
@@ -212,7 +229,8 @@ export async function getTokenLimitsForDelegation(
212
229
  if (index > -1) {
213
230
  const limit = op.value.limit.tokens[index] as TokenLimit;
214
231
  // If we have a previous delegation and the txAllowance is smaller than requested amount
215
- if (new BN(limit.txAllowance).lt(new BN(amount))) {
232
+ // If txAllowance is 0 (unlimited), we should not update it
233
+ if (limit.txAllowance !== '0' && new BN(limit.txAllowance).lt(new BN(amount))) {
216
234
  tokenLimits[index] = entry;
217
235
  }
218
236
  } else {
@@ -581,7 +581,7 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
581
581
  payment_method_id: paymentMethod.id,
582
582
  last_setup_error: null,
583
583
  });
584
- logger.info('setup intent for checkout session reset', {
584
+ logger.info('setupIntent reset on checkout session submit', {
585
585
  session: checkoutSession.id,
586
586
  intent: setupIntent.id,
587
587
  });
@@ -599,13 +599,13 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
599
599
  usage: 'off_session',
600
600
  metadata: checkoutSession.metadata,
601
601
  });
602
+
603
+ // persist setup intent id
604
+ await checkoutSession.update({ setup_intent_id: setupIntent.id });
602
605
  logger.info('setupIntent created on checkout session submit', {
603
606
  session: checkoutSession.id,
604
607
  intent: setupIntent.id,
605
608
  });
606
-
607
- // persist setup intent id
608
- await checkoutSession.update({ setup_intent_id: setupIntent.id });
609
609
  }
610
610
  }
611
611
 
@@ -678,9 +678,6 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
678
678
  items: items.map((x) => x.id),
679
679
  });
680
680
 
681
- // lock prices used by this subscription
682
- await Price.update({ locked: true }, { where: { id: lineItems.map((x) => x.upsell_price_id || x.price_id) } });
683
-
684
681
  // persist subscription id
685
682
  await checkoutSession.update({ subscription_id: subscription.id });
686
683
  }
@@ -38,7 +38,14 @@ export default {
38
38
  checkoutSession.mode,
39
39
  paymentCurrency
40
40
  );
41
- const tokenLimits = await getTokenLimitsForDelegation(paymentMethod, paymentCurrency, address, amount);
41
+
42
+ const tokenLimits = await getTokenLimitsForDelegation(
43
+ checkoutSession,
44
+ paymentMethod,
45
+ paymentCurrency,
46
+ address,
47
+ amount
48
+ );
42
49
  const tokenRequirements = await getTokenRequirements(checkoutSession, paymentMethod, paymentCurrency);
43
50
 
44
51
  return {
@@ -135,16 +135,16 @@ export async function ensureSetupIntent(checkoutSessionId: string, userDid?: str
135
135
  if (checkoutSession.setup_intent_id) {
136
136
  setupIntent = await SetupIntent.findByPk(checkoutSession.setup_intent_id);
137
137
  if (!setupIntent) {
138
- throw new Error('Payment intent not found');
138
+ throw new Error('Setup intent not found');
139
139
  }
140
140
  if (setupIntent.status === 'succeeded') {
141
- throw new Error('Payment intent completed');
141
+ throw new Error('Setup intent completed');
142
142
  }
143
143
  if (setupIntent.status === 'canceled') {
144
- throw new Error('Payment intent canceled');
144
+ throw new Error('Setup intent canceled');
145
145
  }
146
146
  if (setupIntent.status === 'processing') {
147
- throw new Error('Payment intent processing');
147
+ throw new Error('Setup intent processing');
148
148
  }
149
149
 
150
150
  customerId = setupIntent.customer_id;
@@ -40,7 +40,13 @@ export default {
40
40
  checkoutSession.mode,
41
41
  paymentCurrency
42
42
  );
43
- const tokenLimits = await getTokenLimitsForDelegation(paymentMethod, paymentCurrency, address, amount);
43
+ const tokenLimits = await getTokenLimitsForDelegation(
44
+ checkoutSession,
45
+ paymentMethod,
46
+ paymentCurrency,
47
+ address,
48
+ amount
49
+ );
44
50
  const tokenRequirements = await getTokenRequirements(checkoutSession, paymentMethod, paymentCurrency);
45
51
 
46
52
  return {
@@ -0,0 +1,22 @@
1
+ /* eslint-disable no-await-in-loop */
2
+ import { DataTypes } from 'sequelize';
3
+
4
+ import { Migration, safeApplyColumnChanges } from '../migrate';
5
+
6
+ export const up: Migration = async ({ context }) => {
7
+ await safeApplyColumnChanges(context, {
8
+ checkout_sessions: [
9
+ {
10
+ name: 'setup_intent_id',
11
+ field: {
12
+ type: DataTypes.STRING(30),
13
+ allowNull: true,
14
+ },
15
+ },
16
+ ],
17
+ });
18
+ };
19
+
20
+ export const down: Migration = async ({ context }) => {
21
+ await context.removeColumn('checkout_sessions', 'setup_intent_id');
22
+ };
@@ -413,6 +413,10 @@ export class CheckoutSession extends Model<InferAttributes<CheckoutSession>, Inf
413
413
  type: DataTypes.ENUM('auto', 'required'),
414
414
  defaultValue: 'auto',
415
415
  },
416
+ setup_intent_id: {
417
+ type: DataTypes.STRING(30),
418
+ allowNull: true,
419
+ },
416
420
  },
417
421
  {
418
422
  sequelize,
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.72
17
+ version: 1.13.73
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.13.72",
3
+ "version": "1.13.73",
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.72",
109
+ "@did-pay/types": "1.13.73",
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": "bbd67e67e0e6154506b12d7ce30b314e895382c0"
146
+ "gitHead": "544382d01feaed289ddaf2066b701a6ecf253370"
147
147
  }