STRIPE - 通过试用创建订阅,在试用结束后对 3D 安全卡实施 one-time 身份验证失败

STRIPE - Creating Subscription with trial, implementing one-time authentication fails for 3D secure cards after trial ends

https://stripe.com/docs/testing#regulatory-cards

大家好, 所以标题几乎说明了一切,我在试用结束时遇到 3d 安全卡问题。

重现步骤: 节点(服务器):

  1. 创建客户
const customer = await this.getInstance().customers.create({
      email: userData.email,
      name: userData.fullname,
    });
  1. 创建订阅
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,
});
  1. return数据到客户端
 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 端:

  1. 正在获取响应:
 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;
  1. 取决于意图的类型:
 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 },
          });
        }
  1. 确认触发 3d 安全模式,确认后,支付 0 美元的发票。

在下一点之前一切正常。

为了尽可能快地测试跟踪模式,我已经API从订阅中删除试用

 const subscription = await this.getInstance().subscriptions.update(subscriptionId, {
      trial_end: 'now',
    });

之后,Invoice OverDue,订阅失败(切换到pending)。 我注意到 default_payment_method 不存在,所以我什至从前面 returned 设置意向付款方式,并附加到客户,甚至是发票设置。 但无论我修改了什么,新的发票和付款意向从未使用过该信息。

这是由于某些规定导致的预期行为还是我遗漏了什么?

/////////// ////////////

默认情况下,创建和更新订阅都被视为 on-session 请求,因此卡需要身份验证。

如果这纯粹是为了测试目的,您可以包括 off_session=true

 const subscription = await this.getInstance().subscriptions.update(subscriptionId, {
    trial_end: 'now',
    off_session : true
 });

如果您让订阅试用自然结束并继续进行(无需调用 API 更新订阅),您会看到不会请求 3DS(使用以 3155 结尾的卡) .

您可以通过将 trial_end 设置为最接近的时间来创建订阅来进行尝试。如果您不想等待 1 小时自动完成,您可以 API 调用 finalize and pay 发票。

const subscription = await stripe.subscriptions.create({
  customer: 'cus_FfkjLYmWcepurw',
  items: [
    {price: 'price_1JXgRCJQtHgRImA7fDIHY4B2'},
  ],
  trial_end : 1634536700
});