node.js - STRIPE - 使用试用创建订阅,试用结束后对 3D 安全卡实施一次性身份验证失败
问题描述
- 堆栈:Nodejs/Vue/Stripe
- 注意:逻辑适用于标准卡 (4242424242424242),当不存在试用版时,即使 3D 卡也可以使用。
- 此卡用于此测试:4000002500003155
大家好,所以标题几乎说明了一切,试用期结束时我遇到了 3d 安全卡的问题。
重现步骤:节点(服务器):
- 创建客户
const customer = await this.getInstance().customers.create({ email: userData.email, name: userData.fullname, });
- 创建订阅
const subscription = await this.getInstance().subscriptions.create({ customer, items: [ { price: priceId, }, ], off_session: true, promotion_code, payment_behavior: 'default_incomplete', expand: ['latest_invoice.payment_intent', 'pending_setup_intent'], metadata, trial_from_plan: true, });
- 返回数据到客户端
const invoice = subscription.latest_invoice as Stripe.Invoice; const intentType = subscription.pending_setup_intent ? 'setup' : 'payment'; const intent = intentType === 'payment' ? (invoice.payment_intent as Stripe.PaymentIntent) : (subscription.pending_setup_intent as Stripe.SetupIntent); const formattedSubscription = pick(subscription,['cancel_at_period_end','cancel_at','canceled_at']); return { intentType, ...pick(intent, ['id', 'client_secret', 'status']), ...formattedSubscription, };
从 CLINET 方面:
- 获取响应:
const response = await this.$pricesService.buyPlan(this.selectedPlan.id, { fullname: this.nameOnTheCard, email: this.email, hash: this.couponApplied?.hash, }); if (response.error) { throw new Error(response.error); }
const { intentSecret, intentID, intentType, ...restOfBuyResponse } = response;
- 根据意图的类型:
if (intentType === 'payment') { stripeResponse = await StripeInstance.confirmCardPayment(intentSecret, { payment_method: { card: this.$refs.cardElement.$refs.element._element }, }); } else { stripeResponse = await StripeInstance.confirmCardSetup(intentSecret, { payment_method: { card: this.$refs.cardElement.$refs.element._element }, }); }
- 确认触发 3d 安全模式,确认后,支付 0 美元的发票。
一切正常,直到下一点。
为了尽可能快地测试跟踪模式,我制作了 API 以从订阅中删除试用版
const subscription = await this.getInstance().subscriptions.update(subscriptionId, { trial_end: 'now', });
之后,发票过期,订阅失败(切换到待处理)。我注意到 default_payment_method 不存在,所以我什至从前端返回了设置意图付款方式,并附加到客户,甚至发票设置。但无论我修改了什么,新的发票和付款意图都不会使用该信息。
这种预期行为是由于某些规定还是我遗漏了什么?
解决方案
默认情况下,创建和更新订阅都被视为会话请求,因此卡需要身份验证。
如果这纯粹是为了测试目的,您可以包括off_session=true
.
const subscription = await this.getInstance().subscriptions.update(subscriptionId, {
trial_end: 'now',
off_session : true
});
如果您让订阅的试用结束并自然进行(没有进行 API 调用来更新订阅),您会看到不会请求 3DS(使用以 3155 结尾的卡)。
trial_end
您可以通过创建一个设置为最近可能时间的订阅来尝试此操作。如果您不想等待 1 小时自动完成发票,您可以调用 API 来完成并支付发票。
const subscription = await stripe.subscriptions.create({
customer: 'cus_FfkjLYmWcepurw',
items: [
{price: 'price_1JXgRCJQtHgRImA7fDIHY4B2'},
],
trial_end : 1634536700
});
推荐阅读
- c# - 如何转换为运行时已知的类型
- python - 如何让 Decimal 正确反映价值?
- python - 我从 API 获取数据,形式为
我想使用python语言提取所有字段 - oracle - Oracle DB 中的许多并行事务与事务隔离级别
- r - 如何找到不包括 0 值的稀疏矩阵的列均值?
- ios - FCM 在 iOS 上使用 Flutter 有什么要求?
- postgresql - Postgresql 请求获取推荐好友
- php - 如何从 txt 文件中用 PHP 找到一个特定的词?
- sql - 两个子查询之间的 AND 操作
- javafx - 如何在 JAVAFX 中将控件从不同的 VBox 对齐