#stripe-payments
#stripe-платежи
Вопрос:
У меня есть основы работы с платежными намерениями Stripe. Я продаю свое оригинальное произведение искусства. Я хочу иметь возможность отправлять метаданные в процесс оформления заказа. API говорит, что я могу сделать это с помощью payment_intents_data.метаданные показаны здесь:https://support.stripe.com/questions/using-metadata-with-checkout-sessions
const result = stripe.redirectToCheckout({
sessionId: session,
metadata: {
id: this.props.id,
title: this.props.title
}
});
Я получаю сообщение об ошибке, в котором говорится, что stripe.redirectToCheckout не имеет метаданных. Идентификатор сеанса работает нормально.
Как мне передать метаданные? Я вижу в api, что это возможно, но нет примеров того, как это сделать.
Ответ №1:
Моя интеграция с Stripe написана на TypeScript и Angular с использованием AWS Node.js Лямбда-функции через шлюз AWS API. Имея скромные потребности в платежных сервисах, я решил не кодировать страницу оплаты Stripe для своего приложения и вместо этого решил использовать Stripe Checkout. Код пользовательского интерфейса моего приложения вызывает проверку Stripe путем подготовки options
объекта и передачи его stripe.redirectToCheckout(options?)
.
Ограничения Stripe Checkout
В настоящее время Stripe Checkout не поддерживается metadata
в options
параметре redirectToCheckout(options)
функции, и, насколько я могу судить, нет способа обойти это ограничение. Интерфейс для options
параметра, определенный внутри checkout.d.ts
из @stripestripe.js
библиотеки, предоставляет только следующие поля:
interface RedirectToCheckoutClientOptions {
/**
* The URL to which Stripe should send customers when payment is complete.
* If you’d like access to the Checkout Session for the successful payment, read more about it in our guide on [fulfilling your payments with webhooks](https://stripe.com/docs/payments/checkout/fulfillment#webhooks).
*/
successUrl: string;
/**
* The URL to which Stripe should send customers when payment is canceled.
*/
cancelUrl: string;
/**
* An array of objects representing the items that your customer would like to purchase.
* These items are shown as line items in the Checkout interface and make up the total amount to be collected by Checkout.
*/
lineItems?: Array<{
/**
* The ID of the price that the customer would like to purchase. SKU or plan IDs may also be used.
*/
price?: string;
/**
* The quantity of units for the item.
*/
quantity?: number;
}>;
/**
* An array of objects representing the items that your customer would like to purchase.
* These items are shown as line items in the Checkout interface and make up the total amount to be collected by Checkout.
*
* @deprecated
*/
items?: Array<{
/**
* The ID of the SKU that the customer would like to purchase
*/
sku?: string;
/**
* The ID of the plan that the customer would like to subscribe to.
*/
plan?: string;
/**
* The quantity of units for the item.
*/
quantity?: number;
}>;
/**
* The mode of the Checkout Session. Required if using lineItems.
*/
mode?: 'payment' | 'subscription';
/**
* A unique string to reference the Checkout session.
* This can be a customer ID, a cart ID, or similar.
* It is included in the `checkout.session.completed` webhook and can be used to fulfill the purchase.
*/
clientReferenceId?: string;
/**
* The email address used to create the customer object.
* If you already know your customer's email address, use this attribute to prefill it on Checkout.
*/
customerEmail?: string;
/**
* Specify whether Checkout should collect the customer’s billing address.
* If set to `required`, Checkout will attempt to collect the customer’s billing address.
* If not set or set to `auto` Checkout will only attempt to collect the billing address when necessary.
*/
billingAddressCollection?: 'auto' | 'required';
/**
* Provides configuration for Checkout to collect a shipping address from a customer.
*/
shippingAddressCollection?: {
/**
* An array of two-letter ISO country codes representing which countries
* Checkout should provide as options for shipping locations. The codes are
* expected to be uppercase. Unsupported country codes: AS, CX, CC, CU, HM, IR, KP, MH, FM, NF, MP, PW, SD, SY, UM, VI.
*/
allowedCountries: string[];
};
/**
* The [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) of the locale to display Checkout in.
* Default is `auto` (Stripe detects the locale of the browser).
*/
locale?: CheckoutLocale;
/**
* Describes the type of transaction being performed by Checkout in order to customize relevant text on the page, such as the **Submit** button.
* `submitType` can only be specified when using using line items or SKUs, and not subscriptions.
* The default is `auto`.
*/
submitType?: 'auto' | 'book' | 'donate' | 'pay';
}
Два API
Запутанная часть (по крайней мере, для меня) заключается в том, что в документации Stripe четко не указано, что существуют (по крайней мере) два разных API с разными подходами, которые не предназначены для совместной работы.
Более крупный и полнофункциональный API предназначен для Node.js Интеграция (или другого общего внутреннего сервера), при которой пользовательский интерфейс выполняет платежные вызовы для приложения Node.js серверная часть, которая, в свою очередь, вызывает Stripe для обработки платежей.
API Stripe Checkout очень ограничен и подходит для интеграции непосредственно с клиентом (например, для обработки платежа этот API «изначально» не требует какой-либо серверной части для вызова методов обработки платежей Stripe). Причина, по которой я квалифицирую инструкцию Stripe Checkout как не требующую наличия Node.js серверная часть «изначально» заключается в том, что после того, как Stripe отобразит их простой / стандартный экран оплаты, и пользователь произведет платеж, я бы не рекомендовал пытаться завершить процесс оплаты через ваш код пользовательского интерфейса и вместо этого реализовать веб-ссылки Stripe (используя Node.js серверная часть (или, в моем случае, функции AWS Lambda за шлюзом AWS)). Конечные точки Webhook, которые вы регистрируете в Stripe, которые будут вызываться по мере обработки платежа. В моем случае, как только redirectToCheckout(options)
функция перенаправляет на URL-адреса, подтверждающие успех моего приложения или отмененные, пользовательский интерфейс кодируется для опроса одной из моих функций AWS endpoint Lambda, которая в конечном итоге подтверждает или не подтверждает, что платеж был завершен.
Искусственная пауза
Ошибка, которую я допустил (у меня был опыт обучения), заключалась в попытке использовать Node.js Библиотеки Stripe непосредственно в моем приложении пользовательского интерфейса… (Я смог включить библиотеку Stripe Checkout в свое приложение, почему бы также не импортировать Node.js Библиотека Stripe?) Я думаю, что это можно было бы заставить работать, но зависимости, которые ожидает библиотека Stripe, будут доступны, потому что она предполагает Node.js установка также должна быть импортирована в ваш пользовательский интерфейс… Я быстро отказался от этого подхода, потому что казалось, что я покупаю кошмар обслуживания зависимостей на длительный срок … другие более бесстрашные разработчики могут захотеть / быть достаточно умелыми для работы с управлением зависимостями… но не я.
Рекомендация:
Если вам нужно передать metadata
для оплаты Stripe, я бы рекомендовал не использовать функцию Stripe Checkout redirectToCheckout(options)
… вместо этого создайте свою собственную страницу оплаты, которая передается metadata
вашему бэкэнду, который, в свою очередь, использует полный Stripe API для обработки вашего платежа.
Запрос на улучшение
Возможно, в какой-то момент Stripe расширит функциональность Stripe Checkout для поддержки передачи metadata
, а также будет поддерживать типы платежей, отличные от кредитных карт…
Как минимум, я бы рекомендовал Stripe свободно размещать перекрестные ссылки (или предупреждения) в документации обоих API, чтобы было очевидно, что они не предназначены для совместного использования с клиентом приложения.
Ответ №2:
Если вы хотите включить метаданные в PaymentIntent, созданный во время CheckoutSession, вам придется включить его во время создания CheckoutSession, а не в redirectToCheckout
. При создании CheckoutSession вы можете использовать payment_intent_data.metadata
( https://stripe.com/docs/api/checkout/sessions/create?lang=python#create_checkout_session-payment_intent_data-metadata). Затем вы можете продолжить вызов redirectToCheckout
, указав только идентификатор сеанса.
Комментарии:
1. независимо от того, что я пытаюсь, я не могу заставить свое представление django принимать метаданные, я получаю эти ошибки: Получен неизвестный параметр: line_items [0] [метаданные или получен неизвестный параметр: line_items [0] [payment_intent_data.metadata] в зависимости от того, добавляю ли я payment_intent_data.metadata или просто метаданные к элементу строки
2. Вот тут-то и возникает ваша проблема —
platform_intent_data.metadata
это не дочерний параметрline_items
. Это отдельная вещь, и ее следует передавать в вызов Create CheckoutSession в качестве собственного параметра.3. Я также думаю, что я использую оформление заказа вместо намерений оплаты. Итак, используя intents, я должен создать intent на сервере, а также на сеансе?
4. Нет, нет необходимости создавать намерение на сервере перед сеансом. Пока вы создаете сеанс в режиме «оплата», он будет генерировать для вас PaymentIntent. Передавая
payment_intent_data.metadata
, вы просто сообщаете Stripe, что должно быть включено в генерируемый им PaymentIntent.5. На случай, если кто-то пытается сделать это в режиме подписки, вы не сможете.
stripe.error.InvalidRequestError: Request req_xyz123: You can not pass payment_intent_data in subscription mode.