payment-kit 1.25.6 → 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.
@@ -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.6
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.6",
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.6",
63
- "@blocklet/payment-react": "1.25.6",
64
- "@blocklet/payment-vendor": "1.25.6",
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.6",
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": "8a1d87eed8aaa803f29b7c3c69652f2e0c467058"
182
+ "gitHead": "0aa950a5d3f01a150ec21c66e2efeaf81ee1cc69"
183
183
  }