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.
- package/api/src/routes/subscriptions.ts +161 -0
- package/blocklet.yml +1 -1
- package/package.json +6 -6
|
@@ -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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payment-kit",
|
|
3
|
-
"version": "1.25.
|
|
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.
|
|
63
|
-
"@blocklet/payment-react": "1.25.
|
|
64
|
-
"@blocklet/payment-vendor": "1.25.
|
|
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.
|
|
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": "
|
|
182
|
+
"gitHead": "0aa950a5d3f01a150ec21c66e2efeaf81ee1cc69"
|
|
183
183
|
}
|