Stripe — система обработки онлайн-платежей для кредитных карт (и других способов оплаты, включая Google Pay и Apple Pay). Они предлагают широкий спектр функций, от регулярных платежей до отсроченных платежей (очень полезно для бронирования), и их цены действительно удобны.

С точки зрения разработчика, они предлагают два основных способа интеграции платежей на веб-сайте или в приложении: Checkout и Elements.

С Checkout, когда ваш пользователь готов заплатить, он перенаправляется на страницу, размещенную в Stripe (которую вы можете настроить), где он завершает свой платеж; с Elements вы можете разместить платежную форму на своем сайте, чтобы вы могли предложить отличный опыт пользователям, которые не покинут ваш сайт во время процесса оплаты, но при этом сохраняя безопасность и безопасность на высоком уровне.

В этом уроке я сосредоточусь на элементах, так как их реализация может быть немного сложнее, чем проверка, также мы будем использовать Next.js в качестве нашей основы, поскольку Stripe нуждается в межсерверной связи, Next предлагает эту возможность из коробки.

Чтобы следовать этому руководству, вы можете клонировать полный репозиторий отсюда:



Предпосылки

Чтобы следовать этому руководству, вам необходимо:

  • Учетная запись Stripe (вы можете зарегистрироваться в Stripe бесплатно), настроенная и находящаяся в тестовом режиме (с доступом к публикации, секретному ключу и секрету Webhook).
  • Знание фреймворка Next.js, как для фронтенд-разработки, так и для разработки API.
  • Знание того, как работает обратный вызов, веб-перехватчик, связь между серверами.
  • Немного знаний о том, как работают Node и NPM для установки модулей и запуска локального сервера.

Вам также понадобятся некоторые знания CSS-фреймворка Tailwind для стилей.

Если вы хотите протестировать веб-перехватчик локально, вам понадобится ngrok (бесплатная версия прекрасно подходит для этого руководства) или Stripe CLI.

Как работает Stripe Elements

Прежде чем приступить к кодированию, мы должны получить общее представление о том, как работает транзакция Stripe. Предполагая, что вы работаете над электронной коммерцией (но любой другой сайт, требующий оплаты, будет работать), в какой-то момент ваш клиент/пользователь перейдет на страницу оформления заказа, и здесь начнется рабочий процесс Stripe (позже мы подробно рассмотрим каждое действие). ):

  • При переходе на эту страницу ваше приложение свяжется с сервером Stripe для создания PaymentIntent, отправки суммы в корзине и получения обратно идентификатора и секретного ключа; рекомендуется хранить идентификатор где-нибудь на клиенте.
  • Если пользователь изменяет корзину (добавляет или удаляет товары, применяет купоны и т. д.), приложение обновит значение PaymentIntent на сервере Stripe (сохранение идентификатора позволяет пользователю выйти из корзины и получить вернуться позже и все еще иметь готовый PaymentIntent)
  • Тем временем страница будет динамически получать необходимый код JavaScript для создания платежной формы с сервера Stripe. Из-за правил безопасности этот код JavaScript нельзя хранить локально, а форма кредитной карты будет отображаться как iframe внутри страницы. Форма уже настроена для текущего PaymentIntent с помощью ранее сгенерированного секретного ключа.
  • В этот момент пользователь заполнит форму данными кредитной карты и отправит ее. Ваше приложение вызовет удаленную конечную точку confirmPayment Stripe, которая создаст карту и отправит результат (и перенаправит пользователя).
  • В течение всего этого времени, кроме обычных ответов, Stripe будет связываться с нашим сервером через webhook (если он настроен на Stripe Dashboard), уведомляя нас обо всем происходящем; это особенно полезно для обработки действий после оплаты (обновление заказов, отправка электронной почты, обновление запасов) без ожидания обратного вызова клиента. Подробнее об этом позже.

Инициализировать проект и зависимости

Создайте новый проект с:

npx create-react-app stripe-element

Войдите во вновь созданную папку и установите следующие зависимости:

npm i @stripe/stripe-js @stripe/react-stripe-js stripe micro 
npm i -D tailwindcss postcss autoprefixer @tailwindcss/forms

Помимо модулей полосы, мы установилиmicro — небольшую утилиту, которую мы будем использовать при разработке веб-перехватчиков и которая позволит нам получать доступ к содержимому тела запроса в формате RAW. Мы также устанавливаем Tailwind как зависимость от разработчиков.

Настройте (необязательно) tailwind.css:

npx tailwindcss init -p

и настройте tailwind.js.conf следующим образом:

Подготовьте свой файл .env (не забудьте добавить его в .gitignore и поместите переменные в среду вашего хостинга во время развертывания), возьмите эти данные с панели управления Stripe, используя тестовые данные ( Секрет веб-перехватчика можно настроить позже, когда вы включите веб-перехватчики).

Настройте свое рабочее пространство, подготовив нужные нам файлы (остальные файлы можете смело удалить):

Платежное намерение

Как упоминалось в рабочем процессе, первое, что нам нужно обработать, — это paymentIntent, для этого мы используем API, к которому мы обращаемся локально и который будет взаимодействовать с сервером Stripe и обратно в наше приложение.

Отредактируйте файл /pages/api/stripe_intent.js(код прокомментирован в конце):

По сути, этот API (доступ к которому можно получить по URL-адресу http://localhost:3000/api/stripe_intent) будет вызываться с двумя параметрами: сумма, сумма денег. мы хотим выставить счет, и payment_intent_id (но вы также можете обрабатывать дополнительные параметры, такие как описание, которые в нашем случае жестко закодированы) идентификатор ранее созданного платежного намерения ( если он есть), который мы хотим обновить. На основе этих параметров API извлечет, а затем обновит или создаст новый платежный объект Intent и вернет его нашему приложению. Как предлагает Stripe, всегда старайтесь повторно использовать платежное намерение, это поможет отслеживать активность пользователя и будет поддерживать «чистоту» рабочего процесса.

Вы можете протестировать этот API (используя инструмент отдыха, такой как Postman или REST-клиент для VScode), отправив сообщение на http://localhost:3000/api/stripe_intentс параметром bodyamount API ответит объектом paymentIntent, который будет содержать идентификатор (который будет использоваться для его обновления, если он нам понадобится) и client_secret (который будет использоваться для завершения платежа).

Если вы снова вызовете API с новой суммой, но с указанием параметра payment_intent_id со значением, полученным из предыдущего ответа, и новой суммой, в качестве ответа вы получите объект с тем же идентификатором и новой суммой.

Вы также можете попробовать ошибки (например, непрохождение суммы приведет к ошибке).

Вы можете проверить, действительно ли все взаимодействует с Stripe и действительно ли платежное намерение создается на серверах Stripe, зайдя на панель инструментов Stripe и войдя в раздел «Разработчик», чтобы проверить события и журналы:

Как только все будет правильно выровнено, вы можете начать работу над внешним приложением.

Страница оформления заказа/оплаты

Мы создаем одну страницу (index.js), которая, как мы предполагаем, является страницей оформления заказа нашего вымышленного сайта электронной коммерции, где пользователь вводит свой адрес выставления счета/доставки и подтверждает платеж. Наша страница загрузит компонент Stripe Elements и необходимые библиотеки js, используя loadStripe в качестве оболочки. Внутри компонента Elements мы будем отображать компонент CheckoutForm, который является самой платежной формой:

Как только мы доходим до страницы оформления заказа (в нашем случае index.js), мы создаем новый платежный объект, выбирая наш API stripe_intent и передавая сумму, которую собираемся выставить. В этом случае сумма жестко закодирована, но в реальном сценарии сумма будет равна общей сумме корзины (или сумме, которую мы хотим выставить пользователю). Сумма передается как целое число младшей денежной единицы, в нашем случае (евро, но доллар тот же) это цент, поэтому 3000 приводит к 300,00 евро счета.

Ответ API обрабатывается, и два соответствующих данных (clientSecret и paymentIntend id) сохраняются в состоянии. Вы также можете сохранить идентификатор где-нибудь на клиенте (например, LocalStorage), чтобы к нему можно было снова получить доступ, даже если пользователь покинет страницу и вернется позже.

Мы создаем экземпляр компонента Elements, передавая ссылку на основной экземпляр stripe, а также ссылку на объект options, который содержит clientSecret, и объект внешнего вида, который будет использоваться для настройки биллинговой формы (подробнее об Apparence API можно узнать здесь: https://stripe.com/docs/stripe-js/appearance-api)

Мы также передаем идентификатор платежного намерения в CheckoutForm.

Форма оформления заказа

Форма оформления заказа будет отображать форму для сбора данных о платежах и обработки их отправки. Он также будет использоваться для уведомления пользователя об ошибке/успешном платеже. В нашем случае он также будет собирать электронное письмо и отслеживать изменение суммы платежа (например, когда пользователь удаляет продукт из корзины, сумма должна обновляться в paymentIntent).

Мы сохраняем большинство наших переменных (таких как сумма, адрес электронной почты, сообщение о результате и статус загрузки платежа) в состояниях реагирования.

Мы определяем функцию для отслеживания значения суммы обновления при каждом изменении (в производственной среде, возможно, было бы разумнее выбрать событие более разумно, например, при потере фокуса или непосредственно перед отправкой формы) мы обновляем paymentIntent с помощью нашего локального API stripe_intent .

Мы также определяем функцию для обработки отправки формы. По сути, это подтверждает оплату текущих элементов Stripe, которые уже созданы на сервере Stripe. Вы можете передать множество параметров в конечную точку confirmPayment , например квитанцию_email (которая заставит Stripe в рабочей среде отправить электронное письмо пользователю с квитанцией об оплате), сведения о выставлении счетов и доставке (подробнее об это: https://stripe.com/docs/js/payment_intents/confirm_payment). Единственным обязательным является redirect_url, на который перенаправляется пользователь после успешной оплаты, к URL-адресу перенаправления прикрепляются в качестве параметров статус платежа и секрет клиента, который можно использовать для отображения сообщения пользователю после оплаты (в нашем случае реализовано в части страницы useEffect).

В реальном примере электронной коммерции перед подтверждением платежа вы хотите создать и сохранить заказ в своей системе (возможно, со статусом ожидание), чтобы вы могли отправить ссылку на него в Stripe, один раз платеж прошел успешно, вы хотите обновить заказ и перенаправить на страницу благодарности, которая будет обрабатывать параметр статуса возврата, и вы также можете обновить заказ на основе этого статуса.

Вебхуки

Stripe также может связываться с вашим сервером с помощью веб-перехватчиков. Вы можете активировать веб-хуки (и выбрать, какие действия их запускают, на панели инструментов Stripe.

Прежде всего, создайте конечную точку веб-перехватчика в /pages/api/webhook.js.

Stripe будет подписывать каждый запрос веб-перехватчика, а для проверки используется RAW-содержимое запроса (вместе с подписью Stripe заголовка и секретом webhookSecret). Так как next не поддерживает RAW-контент, нам нужно отключить bodyparser и преобразовать запрос в RAW с помощью micro.

Остальное просто, если запрос подтвержден, мы можем прочитать, какое событие было передано и что-то еще (мы просто регистрируемся, чтобы консолидировать пару событий, но вы можете использовать веб-хуки, чтобы уведомить своих клиентов, чтобы обновить заказы и запасы, чтобы уведомить команду какое-то действие произошло).

Если вы работаете на производственном уровне, всегда рекомендуется использовать веб-перехватчик, а не ждать клиента.

Поскольку ваши веб-хуки работают на локальном хосте, но Stripe должен получить к нему удаленный доступ, перед настройкой его на панели инструментов Stripe вам нужен способ разрешить доступ к локальному хосту извне. Я лично использую ngrok, который дает вам общедоступный URL-адрес, сопоставленный с локальным хостом. Просто запустите ngrok, например:

ngrok http http://localhost:3000

он ответит что-то вроде

Forwarding                    http://d12b-2-236-77-43.ngrok.io -> http://localhost:3000

И вы можете использовать http://d12b-2-236-77-43.ngrok.io в качестве конечной точки веб-перехватчика при настройке на Stripe.

Что дальше

Stripe (и Stripe Elements) — очень гибкий инструмент, а его API хорошо документирован (с фрагментами кода React), он позволит вам сохранять клиентов, хранить платежные данные для регулярных платежей, откладывать платежи и многое другое; это одно из лучших решений для дополнения веб-сайта электронной коммерции или веб-приложения, которым требуется интегрированный клиентский опыт и индивидуальные платежные решения.

Дальнейшее чтение



Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.