Как адаптировать ваше онлайн-платежное приложение к веб-платежам и обеспечить лучший пользовательский опыт для клиентов.
После регистрации платежного приложения вы сможете принимать платежные запросы от продавцов. В этом посте объясняется, как организовать платежную транзакцию от сервис-воркера во время выполнения (т. е. когда отображается окно и пользователь взаимодействует с ним).
![Организация платежных транзакций с помощью сервис-воркера](https://web.dev/static/articles/orchestrating-payment-transactions/image/orchestrating-payment-tra-dd17687ea595a.png?authuser=5&hl=ru)
«Изменения параметров оплаты во время выполнения» относятся к набору событий, которые позволяют продавцу и обработчику платежей обмениваться сообщениями, пока пользователь взаимодействует с обработчиком платежей. Дополнительные сведения см. в разделе «Обработка дополнительной платежной информации с помощью сервисного работника» .
Получить событие запроса платежа от продавца
Когда клиент решает оплатить с помощью вашего веб-платежного приложения, а продавец вызывает PaymentRequest.show()
, ваш сервисный работник получит событие paymentrequest
. Добавьте прослушиватель событий в сервис-воркер, чтобы перехватить событие и подготовиться к следующему действию.
[обработчик платежей] service-worker.js:
…
let payment_request_event;
let resolver;
let client;
// `self` is the global object in service worker
self.addEventListener('paymentrequest', async e => {
if (payment_request_event) {
// If there's an ongoing payment transaction, reject it.
resolver.reject();
}
// Preserve the event for future use
payment_request_event = e;
…
Сохраненный PaymentRequestEvent
содержит важную информацию об этой транзакции:
Имя свойства | Описание |
---|---|
topOrigin | Строка, указывающая происхождение веб-страницы верхнего уровня (обычно торговец-получатель). Используйте это, чтобы определить происхождение продавца. |
paymentRequestOrigin | Строка, указывающая происхождение инициатора. Это может быть то же самое, что и topOrigin когда продавец напрямую вызывает API запроса платежа, но может быть другим, если API вызывается из iframe третьей стороной, например платежным шлюзом. |
paymentRequestId | Свойство id объекта PaymentDetailsInit предоставленное API запроса платежа. Если продавец пропустит этот параметр, браузер предоставит автоматически сгенерированный идентификатор. |
methodData | Данные о способе оплаты, предоставленные продавцом как часть PaymentMethodData . Используйте это для определения деталей платежной транзакции. |
total | Общая сумма, предоставленная продавцом как часть PaymentDetailsInit . Используйте это для создания пользовательского интерфейса, позволяющего клиенту узнать общую сумму к оплате. |
instrumentKey | Ключ инструмента, выбранный пользователем. Это отражает instrumentKey который вы указали заранее. Пустая строка означает, что пользователь не указал никаких инструментов. |
Откройте окно обработчика платежей, чтобы отобразить интерфейс веб-платежного приложения.
При получении события paymentrequest
платежное приложение может открыть окно обработчика платежей, вызвав PaymentRequestEvent.openWindow()
. В окне обработчика платежей клиентам будет представлен интерфейс вашего платежного приложения, где они смогут пройти аутентификацию, выбрать адрес и параметры доставки, а также авторизовать платеж. Мы расскажем, как написать код внешнего интерфейса в разделе «Обработка платежей» (скоро).
Передайте сохраненное обещание в PaymentRequestEvent.respondWith()
, чтобы в будущем можно было разрешить его с результатом платежа.
[обработчик платежей] service-worker.js:
…
self.addEventListener('paymentrequest', async e => {
…
// Retain a promise for future resolution
// Polyfill for PromiseResolver is provided below.
resolver = new PromiseResolver();
// Pass a promise that resolves when payment is done.
e.respondWith(resolver.promise);
// Open the checkout page.
try {
// Open the window and preserve the client
client = await e.openWindow(checkoutURL);
if (!client) {
// Reject if the window fails to open
throw 'Failed to open window';
}
} catch (err) {
// Reject the promise on failure
resolver.reject(err);
};
});
…
Вы можете использовать удобный полифил PromiseResolver
для разрешения обещания в произвольное время.
class PromiseResolver {
constructor() {
this.promise_ = new Promise((resolve, reject) => {
this.resolve_ = resolve;
this.reject_ = reject;
})
}
get promise() { return this.promise_ }
get resolve() { return this.resolve_ }
get reject() { return this.reject_ }
}
Обмен информацией с фронтендом
Сервис-воркер платежного приложения может обмениваться сообщениями с интерфейсом платежного приложения через ServiceWorkerController.postMessage()
. Чтобы получать сообщения от внешнего интерфейса, прослушивайте события message
.
[обработчик платежей] service-worker.js:
// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
if (client) client.postMessage({ type, ...contents });
}
Получите сигнал готовности от фронтенда
После открытия окна обработчика платежей сервис-воркер должен дождаться сигнала о готовности от интерфейса платежного приложения. Работник службы может передать важную информацию во внешний интерфейс, когда она будет готова.
[обработчик платежей] интерфейс:
navigator.serviceWorker.controller.postMessage({
type: 'WINDOW_IS_READY'
});
[обработчик платежей] service-worker.js:
…
// Received a message from the frontend
self.addEventListener('message', async e => {
let details;
try {
switch (e.data.type) {
// `WINDOW_IS_READY` is a frontend's ready state signal
case 'WINDOW_IS_READY':
const { total } = payment_request_event;
…
Передайте детали транзакции во внешний интерфейс
Теперь отправьте платежные реквизиты обратно. В этом случае вы отправляете только общую сумму платежного запроса, но при желании можете передать более подробную информацию.
[обработчик платежей] service-worker.js:
…
// Pass the payment details to the frontend
postMessage('PAYMENT_IS_READY', { total });
break;
…
[обработчик платежей] интерфейс:
let total;
navigator.serviceWorker.addEventListener('message', async e => {
switch (e.data.type) {
case 'PAYMENT_IS_READY':
({ total } = e.data);
// Update the UI
renderHTML(total);
break;
…
Возврат платежных данных клиента
Когда клиент авторизует платеж, интерфейс может отправить почтовое сообщение работнику службы для продолжения. Вы можете разрешить обещание, переданное в PaymentRequestEvent.respondWith()
, чтобы отправить результат обратно продавцу. Передайте объект PaymentHandlerResponse
.
Имя свойства | Описание |
---|---|
methodName | Идентификатор способа оплаты, используемый для совершения платежа. |
details | Данные о способе оплаты, которые предоставляют продавцу необходимую информацию для обработки платежа. |
[обработчик платежей] интерфейс:
const paymentMethod = …
postMessage('PAYMENT_AUTHORIZED', {
paymentMethod, // Payment method identifier
});
[обработчик платежей] service-worker.js:
…
// Received a message from the frontend
self.addEventListener('message', async e => {
let details;
try {
switch (e.data.type) {
…
case 'PAYMENT_AUTHORIZED':
// Resolve the payment request event promise
// with a payment response object
const response = {
methodName: e.data.paymentMethod,
details: { id: 'put payment credential here' },
}
resolver.resolve(response);
// Don't forget to initialize.
payment_request_event = null;
break;
…
Отменить платежную транзакцию
Чтобы клиент мог отменить транзакцию, интерфейсная часть может отправить для этого почтовое сообщение сервисному работнику. Затем сервисный работник может разрешить обещание, переданное в PaymentRequestEvent.respondWith()
со значением null
, чтобы указать продавцу, что транзакция была отменена.
[обработчик платежей] интерфейс:
postMessage('CANCEL_PAYMENT');
[обработчик платежей] service-worker.js:
…
// Received a message from the frontend
self.addEventListener('message', async e => {
let details;
try {
switch (e.data.type) {
…
case 'CANCEL_PAYMENT':
// Resolve the payment request event promise
// with null
resolver.resolve(null);
// Don't forget to initialize.
payment_request_event = null;
break;
…
Образец кода
Все примеры кода, которые вы видели в этом документе, были выдержками из следующего рабочего примера приложения:
https://payhandler-demo.glitch.me
[обработчик платежей] работник службы поддержки
[обработчик платежей] интерфейс
Чтобы попробовать:
- Перейдите на https://payrequest-demo.glitch.me/ .
- Перейдите в конец страницы.
- Нажмите кнопку «Добавить платеж» .
- Введите
https://paymenthandler-demo.glitch.me
в поле «Идентификатор способа оплаты» . - Нажмите кнопку «Оплатить» рядом с полем.
Следующие шаги
В этой статье мы узнали, как организовать платежную транзакцию у сервис-воркера. Следующий шаг — научиться добавлять в сервис-воркера некоторые более продвинутые функции.