Как обрабатывать продукты и подписки в одном счете с помощью 3D Secure Flow on Stripe?

ребята! При первом прикосновении к полосе возникла такая проблема - необходимо создать поток для оплаты комбинации ТОВАР + ПОДПИСКА одним платежом (с потоком 3D secure, если он требуется) и отправить один общий счет для клиента. Итак, я составил такой план:

  1. Создать клиента полосы
  2. Создать способ оплаты на основе элементов карты
  3. Прикрепите способ оплаты к клиенту
  4. Создавайте подписки.
  5. Создайте paymentIntent (с обратным URL-адресом, если требуется 3ds) для хранения денег на карте клиента.
  6. Снимайте деньги с карты клиента, когда я получаю от службы доставки информацию о том, что статус заказа отправлен.

Но когда я начал пункт 4 своего списка, я запутался из-за логики подписки на полосе. Как я понял из документации, подписка создаст собственное платежное намерение, собственный счет и запросит собственные 3ds. Итак, я немного запутался, потому что похоже, что пользователю нужно будет передать два 3ds для продукта и подписки, оплатить оба двумя разными платежами и получить два счета. Что мне не хватает? Почему подписку нельзя привязать к основному платежу, оплатить ею после прохождения 3ds и активировать после этого? Почему я должен разделить их и сделать более сложным, чем один отдельный платеж / счет-фактура?

как это выглядит с точки зрения кода (просто макет без каких-либо побочных операций):

  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 счет, созданный по подписке, полностью пропущена логика счета-фактуры продукта, потому что я не Я понимаю, как справиться с двойной оплатой по счету и намерению, и это похоже на костыль.


person Vadim Melnikov    schedule 26.03.2021    source источник


Ответы (1)


Вы можете добавить дополнительные элементы при создании подписки, что, вероятно, вы хотите сделать здесь: https://stripe.com/docs/billing/invoices/subscription#first-invoice-extra

person floatingLomas    schedule 26.03.2021
comment
Это работает! Большое спасибо, но не могли бы вы объяснить мне еще две вещи, пожалуйста? При создании платежного намерения мы можем передать method = manual для удержания денег и для вызова .capture позже, как я могу сделать это таким образом? Как я вижу, в подписке такого реквизита нет. И второе - как я могу перенаправить после 3ds? То же самое с платежным намерением, у него есть свойство return_url. Простите за тупость. - person Vadim Melnikov; 26.03.2021