payment-kit 1.25.5 → 1.25.7

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.
@@ -34,11 +34,6 @@ export async function getMigratedFromList(client: OcapClient): Promise<string[]>
34
34
  cachedMigratedFrom &&
35
35
  cachedMigratedFrom.length > 0
36
36
  ) {
37
- logger.info('wallet-migration: using cached migratedFrom list', {
38
- walletAddress: wallet.address,
39
- chainHost,
40
- migratedFromCount: cachedMigratedFrom.length,
41
- });
42
37
  return cachedMigratedFrom;
43
38
  }
44
39
 
@@ -49,13 +44,13 @@ export async function getMigratedFromList(client: OcapClient): Promise<string[]>
49
44
  cachedWalletAddress = wallet.address;
50
45
  cachedChainHost = chainHost;
51
46
 
52
- logger.info('wallet-migration: loaded migratedFrom list', {
53
- walletAddress: wallet.address,
54
- chainHost,
55
- migratedFromCount: cachedMigratedFrom.length,
56
- migratedFrom: cachedMigratedFrom,
57
- migratedTo: state?.migratedTo,
58
- });
47
+ if (cachedMigratedFrom.length > 0) {
48
+ logger.info('wallet-migration: loaded migratedFrom list', {
49
+ walletAddress: wallet.address,
50
+ chainHost,
51
+ migratedFrom: cachedMigratedFrom,
52
+ });
53
+ }
59
54
 
60
55
  return cachedMigratedFrom;
61
56
  } catch (err) {
@@ -108,23 +103,11 @@ export async function getDelegationAddressWithFallback({
108
103
  // @ts-ignore - OcapClient has host property
109
104
  const chainHost = client?.config?.httpEndpoint || 'unknown';
110
105
 
111
- logger.info('wallet-migration: getDelegationAddressWithFallback called', {
112
- delegator,
113
- storedAddress: storedAddress || null,
114
- walletAddress: wallet.address,
115
- chainHost,
116
- });
117
-
118
106
  // 1. Check stored delegation_address first - but verify it has valid state
119
107
  if (storedAddress) {
120
108
  try {
121
109
  const { state: storedState } = await client.getDelegateState({ address: storedAddress });
122
110
  if (storedState?.ops?.length > 0) {
123
- logger.info('wallet-migration: found valid delegation at stored address', {
124
- storedAddress,
125
- delegator,
126
- opsCount: storedState.ops.length,
127
- });
128
111
  return { address: storedAddress, needsBackfill: false, source: 'stored' };
129
112
  }
130
113
  logger.warn('wallet-migration: stored delegation address has no valid state, falling back', {
@@ -156,12 +139,6 @@ export async function getDelegationAddressWithFallback({
156
139
  opsCount: currentState?.ops?.length || 0,
157
140
  };
158
141
  if (currentState?.ops?.length > 0) {
159
- logger.info('wallet-migration: found valid delegation at current address', {
160
- currentAddress,
161
- delegator,
162
- walletAddress: wallet.address,
163
- opsCount: currentState.ops.length,
164
- });
165
142
  return { address: currentAddress, needsBackfill: true, source: 'current' };
166
143
  }
167
144
  } catch (err) {
@@ -380,8 +357,8 @@ export async function backfillDelegationAddress(subId: string, address: string):
380
357
 
381
358
  // Backfill the address (only if arcblock payment_details exists with required fields)
382
359
  const existingArcblock = subscription.payment_details?.arcblock;
383
- if (!existingArcblock?.tx_hash || !existingArcblock?.payer) {
384
- logger.warn('wallet-migration: cannot backfill delegation_address - missing arcblock payment_details', {
360
+ if (!existingArcblock) {
361
+ logger.info('migration: cannot backfill delegation_address - missing arcblock payment_details', {
385
362
  subscriptionId: subscription.id,
386
363
  });
387
364
  return false;
@@ -3142,4 +3142,165 @@ router.post('/:id/update-stripe-payment-method', authPortal, async (req, res) =>
3142
3142
  }
3143
3143
  });
3144
3144
 
3145
+ /**
3146
+ * Fix subscription after payment method migration from Stripe to non-Stripe
3147
+ * This API is used to fix legacy subscriptions that were migrated but the migration
3148
+ * was incomplete (missing payment_settings/payment_details updates)
3149
+ *
3150
+ * This API will:
3151
+ * 1. Pause the Stripe subscription (if not already paused)
3152
+ * 2. Update payment_settings to use arcblock
3153
+ * 3. Update payment_details to add arcblock info
3154
+ * 4. Recalculate cancel_at if needed
3155
+ */
3156
+ router.put('/:id/fix-stripe-migration', auth, async (req, res) => {
3157
+ try {
3158
+ const subscription = await Subscription.findByPk(req.params.id);
3159
+ if (!subscription) {
3160
+ return res.status(404).json({ error: 'Subscription not found' });
3161
+ }
3162
+
3163
+ const stripeSubscriptionId = subscription.payment_details?.stripe?.subscription_id;
3164
+ if (!stripeSubscriptionId) {
3165
+ return res.status(400).json({ error: 'Subscription does not have Stripe subscription_id' });
3166
+ }
3167
+
3168
+ // Get customer for payer DID
3169
+ const customer = await Customer.findByPk(subscription.customer_id);
3170
+ if (!customer) {
3171
+ return res.status(404).json({ error: 'Customer not found' });
3172
+ }
3173
+
3174
+ // Find arcblock payment method
3175
+ const arcblockMethod = await PaymentMethod.findOne({
3176
+ where: { type: 'arcblock', livemode: subscription.livemode },
3177
+ });
3178
+ if (!arcblockMethod) {
3179
+ return res.status(400).json({ error: 'ArcBlock payment method not found' });
3180
+ }
3181
+
3182
+ // Find Stripe payment method to pause subscription
3183
+ const stripeMethod = await PaymentMethod.findOne({
3184
+ where: { type: 'stripe', livemode: subscription.livemode },
3185
+ });
3186
+
3187
+ // 1. Pause Stripe subscription if not already paused
3188
+ let stripePaused = false;
3189
+ if (stripeMethod) {
3190
+ try {
3191
+ const client = stripeMethod.getStripeClient();
3192
+ const stripeSubscription = await client.subscriptions.retrieve(stripeSubscriptionId);
3193
+ if (stripeSubscription && !stripeSubscription.pause_collection) {
3194
+ await client.subscriptions.update(stripeSubscriptionId, {
3195
+ pause_collection: { behavior: 'void' },
3196
+ });
3197
+ stripePaused = true;
3198
+ logger.info('Stripe subscription paused during fix', {
3199
+ subscriptionId: subscription.id,
3200
+ stripeSubscriptionId,
3201
+ });
3202
+ } else if (stripeSubscription?.pause_collection) {
3203
+ logger.info('Stripe subscription already paused', {
3204
+ subscriptionId: subscription.id,
3205
+ stripeSubscriptionId,
3206
+ });
3207
+ }
3208
+ } catch (stripeErr) {
3209
+ logger.warn('Failed to pause Stripe subscription during fix, continuing anyway', {
3210
+ subscriptionId: subscription.id,
3211
+ stripeSubscriptionId,
3212
+ error: stripeErr,
3213
+ });
3214
+ }
3215
+ }
3216
+
3217
+ const updates: Partial<TSubscription> = {};
3218
+
3219
+ // 2. Update payment_settings to use arcblock (matching change-payment behavior)
3220
+ updates.payment_settings = {
3221
+ payment_method_types: ['arcblock'],
3222
+ payment_method_options: {
3223
+ arcblock: { payer: customer.did },
3224
+ },
3225
+ };
3226
+
3227
+ // 3. Update payment_details.arcblock.payer if not already present
3228
+ if (!subscription.payment_details?.arcblock?.payer) {
3229
+ const existingArcblock = subscription.payment_details?.arcblock;
3230
+ updates.payment_details = {
3231
+ ...subscription.payment_details,
3232
+ arcblock: {
3233
+ ...existingArcblock,
3234
+ payer: customer.did,
3235
+ type: existingArcblock?.type || 'delegate',
3236
+ tx_hash: existingArcblock?.tx_hash || '',
3237
+ },
3238
+ };
3239
+ }
3240
+
3241
+ // 4. Update default_payment_method_id to arcblock
3242
+ updates.default_payment_method_id = arcblockMethod.id;
3243
+
3244
+ // 5. Recalculate cancel_at if subscription has cancelation_details but no cancel_at
3245
+ if (req.body.recalculate_cancel_at !== false) {
3246
+ if (subscription.cancelation_details && !subscription.cancel_at) {
3247
+ const daysUntilCancel = subscription.days_until_cancel || 0;
3248
+ if (daysUntilCancel > 0) {
3249
+ const dueUnit = 24 * 60 * 60; // 1 day in seconds
3250
+ updates.cancel_at = subscription.current_period_start + daysUntilCancel * dueUnit;
3251
+ } else {
3252
+ updates.cancel_at_period_end = true;
3253
+ updates.cancel_at = subscription.current_period_end;
3254
+ }
3255
+ }
3256
+ }
3257
+
3258
+ // Allow manual override of cancel_at
3259
+ if (typeof req.body.cancel_at === 'number') {
3260
+ updates.cancel_at = req.body.cancel_at;
3261
+ }
3262
+
3263
+ await subscription.update(updates);
3264
+
3265
+ logger.info('Subscription stripe migration fixed', {
3266
+ subscriptionId: subscription.id,
3267
+ customerDid: customer.did,
3268
+ updates: {
3269
+ ...updates,
3270
+ payment_details: '(updated)',
3271
+ },
3272
+ stripePaused,
3273
+ stripeSubscriptionId,
3274
+ });
3275
+
3276
+ // Reload subscription to return updated data
3277
+ await subscription.reload();
3278
+
3279
+ return res.json({
3280
+ success: true,
3281
+ stripePaused,
3282
+ subscription: pick(subscription, [
3283
+ 'id',
3284
+ 'status',
3285
+ 'cancel_at',
3286
+ 'cancel_at_period_end',
3287
+ 'canceled_at',
3288
+ 'cancelation_details',
3289
+ 'payment_details',
3290
+ 'payment_settings',
3291
+ 'default_payment_method_id',
3292
+ 'days_until_cancel',
3293
+ 'current_period_start',
3294
+ 'current_period_end',
3295
+ ]),
3296
+ });
3297
+ } catch (err) {
3298
+ logger.error('Failed to fix subscription stripe migration', {
3299
+ error: err,
3300
+ subscriptionId: req.params.id,
3301
+ });
3302
+ return res.status(400).json({ error: err.message });
3303
+ }
3304
+ });
3305
+
3145
3306
  export default router;
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.25.5
17
+ version: 1.25.7
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.25.5",
3
+ "version": "1.25.7",
4
4
  "scripts": {
5
5
  "dev": "blocklet dev --open",
6
6
  "prelint": "npm run types",
@@ -59,9 +59,9 @@
59
59
  "@blocklet/error": "^0.3.5",
60
60
  "@blocklet/js-sdk": "^1.17.8-beta-20260104-120132-cb5b1914",
61
61
  "@blocklet/logger": "^1.17.8-beta-20260104-120132-cb5b1914",
62
- "@blocklet/payment-broker-client": "1.25.5",
63
- "@blocklet/payment-react": "1.25.5",
64
- "@blocklet/payment-vendor": "1.25.5",
62
+ "@blocklet/payment-broker-client": "1.25.7",
63
+ "@blocklet/payment-react": "1.25.7",
64
+ "@blocklet/payment-vendor": "1.25.7",
65
65
  "@blocklet/sdk": "^1.17.8-beta-20260104-120132-cb5b1914",
66
66
  "@blocklet/ui-react": "^3.4.7",
67
67
  "@blocklet/uploader": "^0.3.19",
@@ -132,7 +132,7 @@
132
132
  "devDependencies": {
133
133
  "@abtnode/types": "^1.17.8-beta-20260104-120132-cb5b1914",
134
134
  "@arcblock/eslint-config-ts": "^0.3.3",
135
- "@blocklet/payment-types": "1.25.5",
135
+ "@blocklet/payment-types": "1.25.7",
136
136
  "@types/cookie-parser": "^1.4.9",
137
137
  "@types/cors": "^2.8.19",
138
138
  "@types/debug": "^4.1.12",
@@ -179,5 +179,5 @@
179
179
  "parser": "typescript"
180
180
  }
181
181
  },
182
- "gitHead": "fc70dce73c8d46dd6cd7936d188d551316cd02db"
182
+ "gitHead": "0aa950a5d3f01a150ec21c66e2efeaf81ee1cc69"
183
183
  }