Stripe v3 - SetupIntents и подписки
Я пытаюсь использовать SetupIntents для проверки и сохранения метода оплаты, а затем создать подписку, используя ее, чтобы взимать с клиента (сразу, а затем ежемесячно) требуемую сумму.
Кажется, это работает нормально:
- Карта проверена (включая SCA при необходимости)
- Способ оплаты создан, по умолчанию привязан к клиенту и включен для использования в будущем со статусом ВСТРЕЧЕН.
- Подписка создана и использует указанный выше способ оплаты.
Проблема в том, что Stripe затем генерирует соответствующий счет-фактуру и платежное намерение, но последнее со статусом "requires_action" всякий раз, когда предоставленная карта требует безопасной авторизации клиента (SCA), даже если используется правильный способ оплаты (включен для использования в будущем) и проверка карты уже проведена.
Я думал, что весь смысл использования SetupIntents как раз в том, чтобы заранее проверить метод оплаты и иметь возможность взимать плату с клиента впоследствии.
Мое предположение просто неверно или это действительно возможно, и я просто что-то упускаю?
заранее спасибо
РЕДАКТИРОВАТЬ: это код создания подписки в бэкэнде:
# Set the default payment method on the customer
Stripe::Customer.update(
stripe_customer_id,
invoice_settings: {
default_payment_method: @requested_source
}
)
subscription = Stripe::Subscription.create({
"customer" => stripe_customer_id,
"proration_behavior" => 'create_prorations',
"items" => [
[
"plan" => "#{@stripe_plan_api_id}",
],
],
'default_tax_rates' => [
"#{@stripe_tax_rate_id}",
],
"expand" => ["latest_invoice.payment_intent"]
});
1 ответ
Спасибо за вопрос, Эдуардо.
Есть несколько способов создать Subscription
при получении аутентификации клиента SCA и разрешения на списание средств с карты позже. Предполагая, что у нас уже есть объект Stripe Customer, и его идентификатор хранится вstripe_customer_id
. Теперь у вас есть пара шагов:
Создать
SetupIntent
. Обратите внимание, что если вы создадите его с использованием: 'off_session' иCustomer
после подтверждения он прикрепит полученный метод PaymentMethod.setup_intent = Stripe::SetupIntent.create({ customer: stripe_customer_id, usage: 'off_session', })
Соберите платежные реквизиты и подтвердите SetupIntent, используя его
client_secret
на клиенте, который прикрепит к нему PaymentMethod. Обратите внимание, что он будет прикреплен, но не будет установлен какinvoice_settings.default_payment_method
по умолчанию, поэтому вам нужно будет сделать отдельный вызов API позже, чтобы обновитьCustomer
(см. шаг 3).stripe.confirmCardSetup( '{{setup_intent.client_secret}}', { payment_method: { card: cardElement, }, } ).then(function(result) { // Handle result.error or result.setupIntent });
Обновите
Customer
и установить егоinvoice_settings.default_payment_method
равный IDPaymentMethod
на успешно подтвержденном SetupIntent.Stripe::Customer.update( stripe_customer_id, { invoice_settings: { default_payment_method: 'pm_xxxx', # passed to server from client. On the client this is available on the result of confirmCardSetup } })
Создать
Subscription
с участиемoff_session: true
subscription = Stripe::Subscription.create({ customer: stripe_customer_id, proration_behavior: 'create_prorations', items: [{ plan: "#{@stripe_plan_api_id}", }], default_tax_rates: [ "#{@stripe_tax_rate_id}", ], expand: ["latest_invoice.payment_intent"], off_session: true, })
При этом используется так называемая "транзакция, инициированная продавцом" (MIT) для первого платежа по подписке. Технически это нормально, если Подписка создается позже, после ухода Клиента, и технически должна работать.
Если клиент находится на вашем сайте / в приложении, когда вы создаете Subscription
, есть другой поток, который немного более правильный и не требует использования исключения MIT для SCA. Поток для aSubscription
без суда:
Собирайте данные карты с помощью createPaymentMethod на клиенте (нет
SetupIntent
)stripe.createPaymentMethod({ type: 'card', card: cardElement, }).then(function(result) { //pass result to your server. })
Прикрепите данные карты к
Customer
Stripe::PaymentMethod.attach( "pm_xxx", { customer: stripe_customer_id } )
Обновите
Customer
сinvoice_settings.default_payment_method
Stripe::Customer.update( stripe_customer_id, invoice_settings: { default_payment_method: @requested_source } )
Создать
Subscription
(безoff_session: true
)subscription = Stripe::Subscription.create( customer: data['customerId'], items: [ { price: 'price_H1NlVtpo6ubk0m' } ], expand: ['latest_invoice.payment_intent'] )
Использовать
Subscription
сlatest_invoice
сpayment_intent
сclient_secret
для сбора реквизитов платежа и подтверждения на клиенте.stripe.confirmCardPayment( '{{subscription.latest_invoice.payment_intent.client_secret}}', { ......
Этот второй поток платежей немного более правильный с точки зрения SCA для получения авторизации для списания средств с карты. Второй подход описан в руководстве здесь: https://stripe.com/docs/billing/subscriptions/fixed-price.
У нас также есть образец полосы, который вы можете использовать для экспериментов здесь: https://github.com/stripe-samples/subscription-use-cases/tree/master/fixed-price-subscriptions