payment-kit 1.13.174 → 1.13.176

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 (40) hide show
  1. package/api/src/crons/index.ts +20 -1
  2. package/api/src/integrations/blockchain/stake.ts +99 -1
  3. package/api/src/integrations/stripe/handlers/invoice.ts +4 -0
  4. package/api/src/integrations/stripe/handlers/payment-intent.ts +1 -1
  5. package/api/src/integrations/stripe/resource.ts +63 -12
  6. package/api/src/libs/audit.ts +3 -3
  7. package/api/src/libs/env.ts +2 -0
  8. package/api/src/libs/notification/template/subscription-will-renew.ts +1 -1
  9. package/api/src/libs/subscription.ts +35 -2
  10. package/api/src/queues/checkout-session.ts +98 -94
  11. package/api/src/queues/invoice.ts +23 -13
  12. package/api/src/queues/notification.ts +13 -11
  13. package/api/src/queues/payment.ts +27 -21
  14. package/api/src/queues/refund.ts +5 -5
  15. package/api/src/queues/subscription.ts +210 -49
  16. package/api/src/routes/checkout-sessions.ts +8 -40
  17. package/api/src/routes/connect/change-payment.ts +52 -38
  18. package/api/src/routes/connect/change-plan.ts +51 -39
  19. package/api/src/routes/connect/collect-batch.ts +1 -0
  20. package/api/src/routes/connect/collect.ts +2 -1
  21. package/api/src/routes/connect/pay.ts +1 -0
  22. package/api/src/routes/connect/setup.ts +70 -56
  23. package/api/src/routes/connect/shared.ts +162 -17
  24. package/api/src/routes/connect/subscribe.ts +60 -54
  25. package/api/src/routes/invoices.ts +5 -0
  26. package/api/src/routes/payment-intents.ts +6 -2
  27. package/api/src/store/models/subscription.ts +1 -6
  28. package/api/src/store/models/types.ts +5 -1
  29. package/api/tests/libs/subscription.spec.ts +85 -3
  30. package/blocklet.yml +1 -1
  31. package/package.json +4 -4
  32. package/src/app.tsx +2 -1
  33. package/src/components/customer/link.tsx +22 -8
  34. package/src/components/event/list.tsx +1 -3
  35. package/src/pages/admin/billing/subscriptions/detail.tsx +12 -1
  36. package/src/pages/admin/payments/intents/detail.tsx +1 -1
  37. package/src/pages/admin/products/products/index.tsx +3 -0
  38. package/src/pages/customer/invoice/detail.tsx +7 -3
  39. package/src/pages/customer/subscription/detail.tsx +14 -5
  40. /package/api/src/libs/notification/template/{subscription-cacceled.ts → subscription-canceled.ts} +0 -0
@@ -41,7 +41,6 @@ import {
41
41
  import { CHECKOUT_SESSION_TTL, createCodeGenerator, formatMetadata, getDataObjectFromQuery } from '../libs/util';
42
42
  import { invoiceQueue } from '../queues/invoice';
43
43
  import { paymentQueue } from '../queues/payment';
44
- import { addSubscriptionJob } from '../queues/subscription';
45
44
  import type { TPriceExpanded, TProductExpanded } from '../store/models';
46
45
  import { CheckoutSession } from '../store/models/checkout-session';
47
46
  import { Customer } from '../store/models/customer';
@@ -54,7 +53,7 @@ import { Product } from '../store/models/product';
54
53
  import { SetupIntent } from '../store/models/setup-intent';
55
54
  import { Subscription } from '../store/models/subscription';
56
55
  import { SubscriptionItem } from '../store/models/subscription-item';
57
- import { ensureInvoiceForCheckout, ensureSetupIntent } from './connect/shared';
56
+ import { ensureInvoiceForCheckout } from './connect/shared';
58
57
 
59
58
  const getInvoicePrefix = createCodeGenerator('', 8);
60
59
 
@@ -464,6 +463,7 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
464
463
  const lineItems = await Price.expand(checkoutSession.line_items, { product: true, upsell: true });
465
464
  const trialInDays = Number(checkoutSession.subscription_data?.trial_period_days || 0);
466
465
  const trialEnds = Number(checkoutSession.subscription_data?.trial_end || 0);
466
+ const billingThreshold = Number(checkoutSession.subscription_data?.billing_threshold_amount || 0);
467
467
  const amount = getCheckoutAmount(lineItems, paymentCurrency.id, !!trialInDays);
468
468
  await checkoutSession.update({
469
469
  amount_subtotal: amount.subtotal,
@@ -675,8 +675,8 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
675
675
  },
676
676
  },
677
677
  // @ts-ignore
678
- billing_thresholds: checkoutSession.subscription_data?.billing_threshold_amount
679
- ? { amount_gte: checkoutSession.subscription_data.billing_threshold_amount, reset_billing_cycle_anchor: false } // prettier-ignore
678
+ billing_thresholds: billingThreshold
679
+ ? { amount_gte: billingThreshold, reset_billing_cycle_anchor: false } // prettier-ignore
680
680
  : null,
681
681
  pending_invoice_item_interval: setup.recurring,
682
682
  pending_setup_intent: setupIntent?.id,
@@ -688,9 +688,9 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
688
688
  formatSubscriptionProduct(lineItems.filter((x) => x.price.type === 'recurring')),
689
689
  proration_behavior: checkoutSession.subscription_data?.proration_behavior || 'none',
690
690
  payment_behavior: 'default_incomplete',
691
- days_until_due: checkoutSession.subscription_data?.days_until_due || checkoutSession.metadata?.days_until_due,
691
+ days_until_due: checkoutSession.subscription_data?.days_until_due ?? checkoutSession.metadata?.days_until_due,
692
692
  days_until_cancel:
693
- checkoutSession.subscription_data?.days_until_cancel || checkoutSession.metadata?.days_until_cancel,
693
+ checkoutSession.subscription_data?.days_until_cancel ?? checkoutSession.metadata?.days_until_cancel,
694
694
  metadata: checkoutSession.metadata as any,
695
695
  });
696
696
 
@@ -775,38 +775,6 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
775
775
  }
776
776
  }
777
777
 
778
- // all subscription payments are done after delegation
779
- if (checkoutSession.mode === 'subscription' && subscription) {
780
- if (
781
- delegation.sufficient || // we can pay from delegation
782
- (balance.sufficient && ['NO_TOKEN', 'NO_ENOUGH_TOKEN'].includes(delegation.reason as string)) // we can pay from balance
783
- ) {
784
- await subscription.update({ payment_settings: paymentSettings });
785
-
786
- const { invoice } = await ensureInvoiceForCheckout({ checkoutSession, customer, subscription });
787
- if (invoice) {
788
- invoiceQueue.push({ id: invoice.id, job: { invoiceId: invoice.id, retryOnError: false } });
789
- }
790
- addSubscriptionJob(subscription, 'cycle', false, subscription.trial_end);
791
- }
792
- }
793
-
794
- if (checkoutSession.mode === 'setup' && setupIntent && subscription) {
795
- if (delegation.sufficient) {
796
- const { invoice } = await ensureSetupIntent(checkoutSession.id, customer.did);
797
- if (invoice) {
798
- await invoiceQueue.pushAndWait({ id: invoice.id, job: { invoiceId: invoice.id, retryOnError: false } });
799
- }
800
- await setupIntent.update({ status: 'succeeded', ...paymentSettings });
801
- await subscription.update({
802
- status: subscription.trial_end ? 'trialing' : 'active',
803
- payment_settings: paymentSettings,
804
- });
805
- await checkoutSession.update({ status: 'complete', payment_status: 'no_payment_required' });
806
- logger.info(`CheckoutSession ${checkoutSession.id} updated on setup done ${setupIntent.id}`);
807
- }
808
- }
809
-
810
778
  let stripeContext: any = null;
811
779
  if (paymentMethod.type === 'stripe') {
812
780
  if (paymentIntent) {
@@ -858,8 +826,8 @@ router.put('/:id/submit', user, ensureCheckoutSessionOpen, async (req, res) => {
858
826
  subscription,
859
827
  checkoutSession,
860
828
  customer,
861
- delegation,
862
- balance,
829
+ delegation: checkoutSession.mode === 'payment' ? delegation : null,
830
+ balance: checkoutSession.mode === 'payment' ? balance : null,
863
831
  });
864
832
  } catch (err) {
865
833
  console.error(err);
@@ -1,12 +1,15 @@
1
- import { toTypeInfo } from '@arcblock/did';
2
- import type { Transaction } from '@ocap/client';
3
- import { fromPublicKey } from '@ocap/wallet';
4
-
5
1
  import type { CallbackArgs } from '../../libs/auth';
6
- import { getGasPayerExtra } from '../../libs/payment';
2
+ import { isDelegationSufficientForPayment } from '../../libs/payment';
3
+ import { getFastCheckoutAmount } from '../../libs/session';
7
4
  import { getTxMetadata } from '../../libs/util';
8
5
  import type { TLineItemExpanded } from '../../store/models';
9
- import { ensureChangePaymentContext, getAuthPrincipalClaim, getDelegationTxClaim } from './shared';
6
+ import {
7
+ ensureChangePaymentContext,
8
+ executeOcapTransactions,
9
+ getAuthPrincipalClaim,
10
+ getDelegationTxClaim,
11
+ getStakeTxClaim,
12
+ } from './shared';
10
13
 
11
14
  export default {
12
15
  action: 'change-payment',
@@ -19,25 +22,56 @@ export default {
19
22
  },
20
23
  onConnect: async ({ userDid, userPk, extraParams }: CallbackArgs) => {
21
24
  const { subscriptionId } = extraParams;
22
- const { subscription, paymentMethod, paymentCurrency } = await ensureChangePaymentContext(subscriptionId);
25
+ const { subscription, customer, paymentMethod, paymentCurrency } = await ensureChangePaymentContext(subscriptionId);
23
26
 
24
27
  if (paymentMethod.type === 'arcblock') {
28
+ const claims: { [type: string]: [string, object] } = {};
29
+
25
30
  // @ts-ignore
26
31
  const items = subscription!.items as TLineItemExpanded[];
32
+ const trialInDays = 0;
33
+ const billingThreshold = Number(subscription.billing_thresholds?.amount_gte || 0);
34
+ const fastCheckoutAmount = getFastCheckoutAmount(items, 'setup', paymentCurrency.id, !!trialInDays);
35
+ const delegation = await isDelegationSufficientForPayment({
36
+ paymentMethod,
37
+ paymentCurrency,
38
+ userDid: customer!.did,
39
+ amount: fastCheckoutAmount,
40
+ });
41
+
42
+ // if we can complete purchase without any wallet interaction
43
+ if (delegation.sufficient === false) {
44
+ claims.delegation = [
45
+ 'signature',
46
+ await getDelegationTxClaim({
47
+ mode: 'setup',
48
+ userDid,
49
+ userPk,
50
+ nonce: `change-method-${subscription.id}`,
51
+ data: getTxMetadata({ subscriptionId: subscription.id }),
52
+ paymentCurrency,
53
+ paymentMethod,
54
+ trialInDays,
55
+ billingThreshold,
56
+ items,
57
+ }),
58
+ ];
59
+ }
27
60
 
28
- return {
29
- signature: await getDelegationTxClaim({
30
- mode: 'setup',
61
+ // we always need to stake for the subscription
62
+ claims.staking = [
63
+ 'prepareTx',
64
+ await getStakeTxClaim({
31
65
  userDid,
32
66
  userPk,
33
- nonce: subscription!.id,
34
- data: getTxMetadata({ subscriptionId: subscription!.id }),
35
67
  paymentCurrency,
36
68
  paymentMethod,
37
- trial: false,
38
69
  items,
70
+ subscription,
39
71
  }),
40
- };
72
+ ];
73
+
74
+ return claims;
41
75
  }
42
76
 
43
77
  throw new Error(`Payment method ${paymentMethod.type} not supported`);
@@ -52,27 +86,14 @@ export default {
52
86
  if (paymentMethod.type === 'arcblock') {
53
87
  await subscription?.update({
54
88
  payment_settings: {
55
- payment_method_types: ['arcblock'],
89
+ payment_method_types: [paymentMethod.type],
56
90
  payment_method_options: {
57
91
  arcblock: { payer: userDid },
58
92
  },
59
93
  },
60
94
  });
61
95
 
62
- const client = paymentMethod.getOcapClient();
63
- const claim = claims.find((x) => x.type === 'signature');
64
-
65
- // execute the delegate tx
66
- const tx: Partial<Transaction> = client.decodeTx(claim.origin);
67
- tx.signature = claim.sig;
68
-
69
- // @ts-ignore
70
- const { buffer } = await client.encodeDelegateTx({ tx });
71
- const txHash = await client.sendDelegateTx(
72
- // @ts-ignore
73
- { tx, wallet: fromPublicKey(userPk, toTypeInfo(userDid)) },
74
- getGasPayerExtra(buffer)
75
- );
96
+ const paymentDetails = await executeOcapTransactions(userDid, userPk, claims, paymentMethod);
76
97
 
77
98
  await setupIntent.update({
78
99
  status: 'succeeded',
@@ -82,23 +103,16 @@ export default {
82
103
  arcblock: { payer: userDid },
83
104
  },
84
105
  setup_details: {
85
- arcblock: {
86
- tx_hash: txHash,
87
- payer: userDid,
88
- },
106
+ arcblock: paymentDetails,
89
107
  },
90
108
  });
91
109
 
92
110
  await subscription?.update({
93
111
  currency_id: paymentCurrency.id,
94
112
  default_payment_method_id: paymentMethod.id,
95
- payment_settings: {
96
- payment_method_types: [paymentMethod.type],
97
- payment_method_options: {},
98
- },
99
113
  });
100
114
 
101
- return { hash: txHash };
115
+ return { hash: paymentDetails.tx_hash };
102
116
  }
103
117
 
104
118
  throw new Error(`Payment method ${paymentMethod.type} not supported`);
@@ -1,14 +1,17 @@
1
- import { toTypeInfo } from '@arcblock/did';
2
- import type { Transaction } from '@ocap/client';
3
- import { fromPublicKey } from '@ocap/wallet';
4
-
5
1
  import type { CallbackArgs } from '../../libs/auth';
6
- import { getGasPayerExtra } from '../../libs/payment';
2
+ import { isDelegationSufficientForPayment } from '../../libs/payment';
3
+ import { getFastCheckoutAmount } from '../../libs/session';
7
4
  import { getTxMetadata } from '../../libs/util';
8
5
  import { invoiceQueue } from '../../queues/invoice';
9
6
  import { addSubscriptionJob } from '../../queues/subscription';
10
7
  import type { TLineItemExpanded } from '../../store/models';
11
- import { ensureSubscription, getAuthPrincipalClaim, getDelegationTxClaim } from './shared';
8
+ import {
9
+ ensureSubscription,
10
+ executeOcapTransactions,
11
+ getAuthPrincipalClaim,
12
+ getDelegationTxClaim,
13
+ getStakeTxClaim,
14
+ } from './shared';
12
15
 
13
16
  export default {
14
17
  action: 'change-plan',
@@ -21,25 +24,56 @@ export default {
21
24
  },
22
25
  onConnect: async ({ userDid, userPk, extraParams }: CallbackArgs) => {
23
26
  const { subscriptionId } = extraParams;
24
- const { paymentMethod, paymentCurrency, subscription } = await ensureSubscription(subscriptionId);
27
+ const { paymentMethod, paymentCurrency, subscription, customer } = await ensureSubscription(subscriptionId);
25
28
 
26
29
  if (paymentMethod.type === 'arcblock') {
30
+ const claims: { [type: string]: [string, object] } = {};
31
+
27
32
  // @ts-ignore
28
33
  const items = subscription!.items as TLineItemExpanded[];
34
+ const trialInDays = 0;
35
+ const billingThreshold = Number(subscription!.billing_thresholds?.amount_gte || 0);
36
+ const fastCheckoutAmount = getFastCheckoutAmount(items, 'subscription', paymentCurrency.id, !!trialInDays);
37
+ const delegation = await isDelegationSufficientForPayment({
38
+ paymentMethod,
39
+ paymentCurrency,
40
+ userDid: customer!.did,
41
+ amount: fastCheckoutAmount,
42
+ });
43
+
44
+ // if we can complete purchase without any wallet interaction
45
+ if (delegation.sufficient === false) {
46
+ claims.delegation = [
47
+ 'signature',
48
+ await getDelegationTxClaim({
49
+ mode: 'subscription',
50
+ userDid,
51
+ userPk,
52
+ nonce: `change-plan-${subscription!.id}`,
53
+ data: getTxMetadata({ subscriptionId: subscription!.id }),
54
+ paymentCurrency,
55
+ paymentMethod,
56
+ trialInDays,
57
+ billingThreshold,
58
+ items,
59
+ }),
60
+ ];
61
+ }
29
62
 
30
- return {
31
- signature: await getDelegationTxClaim({
32
- mode: 'subscription',
63
+ // we always need to stake for the subscription
64
+ claims.staking = [
65
+ 'prepareTx',
66
+ await getStakeTxClaim({
33
67
  userDid,
34
68
  userPk,
35
- nonce: subscription!.id,
36
- data: getTxMetadata({ subscriptionId: subscription!.id }),
37
69
  paymentCurrency,
38
70
  paymentMethod,
39
- trial: false,
40
71
  items,
72
+ subscription: subscription!,
41
73
  }),
42
- };
74
+ ];
75
+
76
+ return claims;
43
77
  }
44
78
 
45
79
  throw new Error(`Payment method ${paymentMethod.type} not supported`);
@@ -59,35 +93,13 @@ export default {
59
93
  },
60
94
  });
61
95
 
62
- const client = paymentMethod.getOcapClient();
63
- const claim = claims.find((x) => x.type === 'signature');
64
-
65
- // execute the delegate tx
66
- const tx: Partial<Transaction> = client.decodeTx(claim.origin);
67
- tx.signature = claim.sig;
68
-
69
- // @ts-ignore
70
- const { buffer } = await client.encodeDelegateTx({ tx });
71
- const txHash = await client.sendDelegateTx(
72
- // @ts-ignore
73
- { tx, wallet: fromPublicKey(userPk, toTypeInfo(userDid)) },
74
- getGasPayerExtra(buffer)
75
- );
76
-
77
- await subscription?.update({
78
- payment_details: {
79
- arcblock: {
80
- tx_hash: txHash,
81
- payer: userDid,
82
- },
83
- },
84
- });
96
+ const paymentDetails = await executeOcapTransactions(userDid, userPk, claims, paymentMethod);
97
+ await subscription?.update({ payment_details: { arcblock: paymentDetails } });
85
98
 
86
99
  if (invoice) {
87
100
  if (invoice.status === 'uncollectible') {
88
101
  await invoice.update({ status: 'open' });
89
102
  }
90
-
91
103
  await invoiceQueue.pushAndWait({
92
104
  id: invoice.id,
93
105
  job: { invoiceId: invoice.id, retryOnError: false, waitForPayment: true },
@@ -97,7 +109,7 @@ export default {
97
109
  await addSubscriptionJob(subscription, 'cycle', false, subscription.trial_end);
98
110
  }
99
111
 
100
- return { hash: txHash };
112
+ return { hash: paymentDetails.tx_hash };
101
113
  }
102
114
 
103
115
  throw new Error(`Payment method ${paymentMethod.type} not supported`);
@@ -98,6 +98,7 @@ export default {
98
98
  arcblock: {
99
99
  tx_hash: txHash,
100
100
  payer: userDid,
101
+ type: 'transfer',
101
102
  },
102
103
  },
103
104
  });
@@ -58,7 +58,7 @@ export default {
58
58
  userPk,
59
59
  nonce: invoice.id,
60
60
  data: getTxMetadata({ subscriptionId: subscription!.id, invoiceId: invoice.id }),
61
- trial: false,
61
+ trialInDays: 0,
62
62
  paymentCurrency,
63
63
  paymentMethod,
64
64
  items,
@@ -102,6 +102,7 @@ export default {
102
102
  arcblock: {
103
103
  tx_hash: txHash,
104
104
  payer: userDid,
105
+ type: 'transfer',
105
106
  },
106
107
  },
107
108
  });
@@ -90,6 +90,7 @@ export default {
90
90
  arcblock: {
91
91
  tx_hash: txHash,
92
92
  payer: userDid,
93
+ type: 'transfer',
93
94
  },
94
95
  },
95
96
  });
@@ -1,14 +1,18 @@
1
- import { toTypeInfo } from '@arcblock/did';
2
- import type { Transaction } from '@ocap/client';
3
- import { fromPublicKey } from '@ocap/wallet';
4
-
5
1
  import type { CallbackArgs } from '../../libs/auth';
6
- import { getGasPayerExtra } from '../../libs/payment';
2
+ import logger from '../../libs/logger';
3
+ import { isDelegationSufficientForPayment } from '../../libs/payment';
4
+ import { getFastCheckoutAmount } from '../../libs/session';
7
5
  import { getTxMetadata } from '../../libs/util';
8
6
  import { invoiceQueue } from '../../queues/invoice';
9
7
  import { addSubscriptionJob } from '../../queues/subscription';
10
8
  import type { TLineItemExpanded } from '../../store/models';
11
- import { ensureSetupIntent, getAuthPrincipalClaim, getDelegationTxClaim } from './shared';
9
+ import {
10
+ ensureSetupIntent,
11
+ executeOcapTransactions,
12
+ getAuthPrincipalClaim,
13
+ getDelegationTxClaim,
14
+ getStakeTxClaim,
15
+ } from './shared';
12
16
 
13
17
  export default {
14
18
  action: 'setup',
@@ -21,7 +25,7 @@ export default {
21
25
  },
22
26
  onConnect: async ({ userDid, userPk, extraParams }: CallbackArgs) => {
23
27
  const { checkoutSessionId } = extraParams;
24
- const { paymentMethod, paymentCurrency, checkoutSession, subscription } = await ensureSetupIntent(
28
+ const { paymentMethod, paymentCurrency, checkoutSession, subscription, customer } = await ensureSetupIntent(
25
29
  checkoutSessionId,
26
30
  userDid
27
31
  );
@@ -30,20 +34,51 @@ export default {
30
34
  }
31
35
 
32
36
  if (paymentMethod.type === 'arcblock') {
37
+ const claims: { [type: string]: [string, object] } = {};
38
+
39
+ // if we can complete purchase without any wallet interaction
33
40
  const items = checkoutSession.line_items as TLineItemExpanded[];
34
- return {
35
- signature: await getDelegationTxClaim({
36
- mode: checkoutSession.mode,
41
+ const trialInDays = Number(checkoutSession.subscription_data?.trial_period_days || 0);
42
+ const billingThreshold = Number(checkoutSession.subscription_data?.billing_threshold_amount || 0);
43
+ const fastCheckoutAmount = getFastCheckoutAmount(items, checkoutSession.mode, paymentCurrency.id, !!trialInDays);
44
+ const delegation = await isDelegationSufficientForPayment({
45
+ paymentMethod,
46
+ paymentCurrency,
47
+ userDid: customer.did,
48
+ amount: fastCheckoutAmount,
49
+ });
50
+ if (delegation.sufficient === false) {
51
+ claims.delegation = [
52
+ 'signature',
53
+ await getDelegationTxClaim({
54
+ mode: checkoutSession.mode,
55
+ userDid,
56
+ userPk,
57
+ nonce: checkoutSession.id,
58
+ data: getTxMetadata({ subscriptionId: subscription.id, checkoutSessionId }),
59
+ paymentCurrency,
60
+ paymentMethod,
61
+ trialInDays,
62
+ billingThreshold,
63
+ items,
64
+ }),
65
+ ];
66
+ }
67
+
68
+ // we always need to stake for the subscription
69
+ claims.staking = [
70
+ 'prepareTx',
71
+ await getStakeTxClaim({
37
72
  userDid,
38
73
  userPk,
39
- nonce: checkoutSession.id,
40
- data: getTxMetadata({ subscriptionId: subscription.id, checkoutSessionId }),
41
74
  paymentCurrency,
42
75
  paymentMethod,
43
- trial: !!checkoutSession.subscription_data?.trial_period_days,
44
76
  items,
77
+ subscription,
45
78
  }),
46
- };
79
+ ];
80
+
81
+ return claims;
47
82
  }
48
83
 
49
84
  throw new Error(`Payment method ${paymentMethod.type} not supported`);
@@ -60,63 +95,42 @@ export default {
60
95
  }
61
96
 
62
97
  if (paymentMethod.type === 'arcblock') {
63
- await setupIntent.update({ status: 'processing' });
64
- await subscription.update({
65
- payment_settings: {
66
- payment_method_types: ['arcblock'],
67
- payment_method_options: {
68
- arcblock: { payer: userDid },
69
- },
98
+ const paymentSettings = {
99
+ payment_method_types: ['arcblock'],
100
+ payment_method_options: {
101
+ arcblock: { payer: userDid },
70
102
  },
71
- });
72
-
73
- const client = paymentMethod.getOcapClient();
74
- const claim = claims.find((x) => x.type === 'signature');
75
-
76
- // execute the delegate tx
77
- const tx: Partial<Transaction> = client.decodeTx(claim.origin);
78
- tx.signature = claim.sig;
79
-
80
- // @ts-ignore
81
- const { buffer } = await client.encodeDelegateTx({ tx });
82
- const txHash = await client.sendDelegateTx(
83
- // @ts-ignore
84
- { tx, wallet: fromPublicKey(userPk, toTypeInfo(userDid)) },
85
- getGasPayerExtra(buffer)
86
- );
103
+ };
104
+ await setupIntent.update({ status: 'processing' });
105
+ await subscription.update({ payment_settings: paymentSettings });
106
+ if (invoice) {
107
+ await invoice.update({ payment_settings: paymentSettings });
108
+ }
87
109
 
110
+ const paymentDetails = await executeOcapTransactions(userDid, userPk, claims, paymentMethod);
88
111
  await setupIntent.update({
89
112
  status: 'succeeded',
90
113
  last_setup_error: null,
91
- payment_method_types: ['arcblock'],
92
- payment_method_options: {
93
- arcblock: { payer: userDid },
94
- },
95
- setup_details: {
96
- arcblock: {
97
- tx_hash: txHash,
98
- payer: userDid,
99
- },
100
- },
114
+ setup_details: { arcblock: paymentDetails },
115
+ ...paymentSettings,
101
116
  });
102
-
103
117
  await subscription.update({
104
118
  status: subscription.trial_end ? 'trialing' : 'active',
105
- payment_details: {
106
- arcblock: {
107
- tx_hash: txHash,
108
- payer: userDid,
109
- },
110
- },
119
+ payment_details: { arcblock: paymentDetails },
111
120
  });
112
121
 
113
122
  await checkoutSession.update({ status: 'complete', payment_status: 'paid' });
114
123
  if (invoice) {
115
- invoiceQueue.push({ id: invoice.id, job: { invoiceId: invoice.id, retryOnError: false } });
124
+ invoiceQueue.pushAndWait({ id: invoice.id, job: { invoiceId: invoice.id, retryOnError: false } });
116
125
  }
117
126
  await addSubscriptionJob(subscription, 'cycle', false, subscription.trial_end);
127
+ logger.info('CheckoutSession updated on setup done', {
128
+ checkoutSession: checkoutSession.id,
129
+ setupIntent: setupIntent.id,
130
+ paymentDetails,
131
+ });
118
132
 
119
- return { hash: txHash };
133
+ return { hash: paymentDetails.tx_hash };
120
134
  }
121
135
 
122
136
  throw new Error(`Payment method ${paymentMethod.type} not supported`);