如何使用条带上的 3d 安全流处理一张发票中的产品和订阅?

How to handle products and subscriptions in one invoice with 3d secure flow on stripe?

伙计们!第一次接触条纹时对这样的问题感到困惑 - 需要在一次付款中为组合产品 + 订阅进行支付(如果需要,则使用 3d 安全流程)并为客户发送一张总发票。所以我做了这样一个计划:

  1. 创建条纹客户
  2. 根据卡元素创建支付方式
  3. 将付款方式附加到客户
  4. 创建订阅。
  5. 创建 paymentIntent(如果需要 3ds,则使用 return url 属性)以在客户的卡上存钱。
  6. 当我从送货服务处获得订单状态为“已发送”的信息时,从客户的卡中扣款。

但是当我开始列表的第 4 点时,由于条带上的订阅逻辑,我感到困惑。正如我从文档中获得的那样,订阅将创建自己的付款意向、自己的发票并要求提供自己的 3ds。所以我很困惑,因为看起来用户需要为产品和子产品传递两个 3ds,将以两种不同的付款方式支付,并将获得两张发票。我错过了什么?为什么订阅不能附加到“主要”付款,在 3ds 过后由它支付并在之后激活?为什么我要拆分它们并使它比一个更复杂 payment/invoice?

从代码的角度来看它是怎样的(只是没有任何辅助操作的模型):

  1. 创建用户
const customer = await stripe.customers.create({
        email,
        address,
        name,
});
  1. 创建付款方式
const { paymentMethod } = await stripe.createPaymentMethod({
        type: "card",
        card: cardElement,
        billing_details: {
          address: {
            city,
            country,
            line1: address1,
            line2: address2,
            postal_code: zip,
          },
          email,
          name,
        },
      });
  1. 将付款方式附加到客户
const paymentMethod = await stripe.paymentMethods.attach(paymentId, {
      customer,
    });
  1. 创建持有货币的付款意图
const order = await stripe.paymentIntents.create({
      amount: sum * 100,
      currency: unit,
      description: "project name",
      customer,
      payment_method: paymentId,
      setup_future_usage: "off_session",
      confirm: true,
      capture_method: "manual", // to hold money
      receipt_email: email,
      return_url: returnUrl,   // to return after 3ds
    });
  1. 创建订阅
const subs = await stripe.subscriptions.create({
      customer: customerId,
      items: subscriptions,
      expand: ["latest_invoice.payment_intent"], 
    });

if (subs.status === "incomplete" && subs.latest_invoice.payment_intent) {
        await stripe
          .confirmCardPayment(
            subs.latest_invoice.payment_intent.client_secret,
            {
              payment_method: {
                card: cardElement,
              },
            }
          )
      }

/* the only way i found to pass 3ds on sub without getting "incomplete" status
but it provide second 3ds for subs */
  1. 重定向 3ds
const action = order.next_action;
      if (action && action.type === "redirect_to_url") {
        window.location = action.redirect_to_url.url;
      }
  1. 在 3ds 后重定向后 - 获取资金
    await stripe.paymentIntents.capture(paymentId);

所以最终结果是-我有两次付款(一次-我计算的产品是总篮子-订阅价格,第二次-订阅),每个有两个 3ds,订阅创建了 1 个发票,完全没有产品发票逻辑, 因为我不明白如何处理发票和意图的双重支付,这看起来像拐杖。

您可以在创建订阅时添加其他项目,这很可能是您想在此处执行的操作:https://stripe.com/docs/billing/invoices/subscription#first-invoice-extra