Cómo adaptar tu app de pagos basada en la Web a Pagos web y brindar una mejor experiencia del usuario a los clientes.
Una vez que se registre la app de pagos, estarás listo para aceptar solicitudes de pago de los comercios. En esta publicación, se explica cómo organizar una transacción de pago desde un service worker durante el tiempo de ejecución (es decir, cuando se muestra una ventana y el usuario interactúa con ella).
Los "Cambios en los parámetros de pago del entorno de ejecución" hacen referencia a un conjunto de eventos que permiten que el comercio y el controlador de pagos intercambien mensajes mientras el usuario interactúa con el controlador de pago. Obtén más información en Cómo administrar información de pago opcional con un service worker.
Cómo recibir un evento de solicitud de pago del comercio
Cuando un cliente elige pagar con tu app de pagos basada en la Web y el comercio
invoca
PaymentRequest.show()
,
tu service worker recibe un evento paymentrequest
. Agrega un objeto de escucha de eventos
al service worker para capturar el evento y prepararte para la siguiente acción.
[controlador de pago] 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;
…
El PaymentRequestEvent
preservado contiene información importante sobre esta transacción:
Nombre de la propiedad | Descripción |
---|---|
topOrigin |
Es una cadena que indica el origen de la página web de nivel superior (por lo general, el comerciante beneficiario). Úsalo para identificar el origen del comercio. |
paymentRequestOrigin |
Una cadena que indica el origen del invocador Puede ser igual a topOrigin cuando el comercio invoca la API de Payment Request directamente, pero puede ser diferente si un tercero invoca a la API desde un iframe, como una puerta de enlace de pagos.
|
paymentRequestId |
La propiedad id de PaymentDetailsInit proporcionada a la API de Payment Request. Si el comercio los omite, el navegador proporcionará un ID generado automáticamente.
|
methodData |
Son datos específicos de la forma de pago que proporciona el comercio como parte de PaymentMethodData .
Úsalo para determinar los detalles de la transacción de pago.
|
total |
Importe total proporcionado por el comercio como parte de PaymentDetailsInit .
Úsalo para crear una IU que le permita al cliente conocer el importe total que debe pagar.
|
instrumentKey |
Es la etiqueta de marca que seleccionó el usuario. Esto refleja el instrumentKey que proporcionaste con anticipación. Una cadena vacía indica que el usuario no especificó ningún instrumento.
|
Abre la ventana del controlador de pagos para mostrar el frontend de la app de pagos basada en la Web.
Cuando se recibe un evento paymentrequest
, la app de pagos puede llamar a PaymentRequestEvent.openWindow()
para abrir una ventana del controlador de pagos. En la ventana del controlador de pagos, se mostrará a los clientes la interfaz de tu app de pagos, en la que pueden autenticarse, elegir la dirección y las opciones de envío y autorizar el pago. Abordaremos cómo escribir el código de frontend en Cómo administrar pagos en el frontend de pagos (disponible próximamente).
Pasa una promesa preservada a PaymentRequestEvent.respondWith()
para que puedas resolverla con un resultado de pago en el futuro.
[controlador de pago] 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);
};
});
…
Puedes usar un polyfill PromiseResolver
conveniente para resolver una promesa en un tiempo arbitrario.
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_ }
}
Intercambia información con el frontend
El service worker de la app de pagos puede intercambiar mensajes con el frontend
de la app de pagos a través de ServiceWorkerController.postMessage()
. Para recibir mensajes del frontend, escucha los eventos message
.
[controlador de pago] service-worker.js:
// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
if (client) client.postMessage({ type, ...contents });
}
Recibe el indicador Listo del frontend
Una vez que se abre la ventana del controlador de pagos, el service worker debe esperar una señal de estado listo desde el frontend de la app de pagos. El service worker puede pasar información importante al frontend cuando está listo.
Frontend de [controlador de pago]:
navigator.serviceWorker.controller.postMessage({
type: 'WINDOW_IS_READY'
});
[controlador de pago] 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;
…
Pasa los detalles de la transacción al frontend
Ahora, devuelve los detalles del pago. En este caso, solo enviarás el total de la solicitud de pago, pero puedes pasar más detalles si lo deseas.
[controlador de pago] service-worker.js:
…
// Pass the payment details to the frontend
postMessage('PAYMENT_IS_READY', { total });
break;
…
Frontend de [controlador de pago]:
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;
…
Devuelve las credenciales de pago del cliente
Cuando el cliente autoriza el pago, el frontend puede enviar un mensaje posterior al service worker para continuar. Puedes resolver la promesa que se pasó a PaymentRequestEvent.respondWith()
para devolver el resultado al comercio.
Pasa un objeto PaymentHandlerResponse
.
Nombre de la propiedad | Descripción |
---|---|
methodName |
Es el identificador de la forma de pago que se usa para realizar pagos. |
details |
Son los datos específicos de la forma de pago que proporcionan la información necesaria para que el comercio procese el pago. |
Frontend de [controlador de pago]:
const paymentMethod = …
postMessage('PAYMENT_AUTHORIZED', {
paymentMethod, // Payment method identifier
});
[controlador de pago] 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;
…
Cancelar la transacción de pago
Para permitir que el cliente cancele la transacción, el frontend puede enviar un mensaje posterior
al service worker, que puede resolver la
promesa que se pasó a PaymentRequestEvent.respondWith()
con null
para indicarle
al comercio que se canceló la transacción.
Frontend de [controlador de pago]:
postMessage('CANCEL_PAYMENT');
[controlador de pago] 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;
…
Código de muestra
Todos los códigos de muestra que viste en este documento son extractos de la siguiente app de ejemplo funcional:
https://paymenthandler-demo.glitch.me
[controlador de pagos] service worker
Frontend de [controlador de pagos]
Para probarlo, haz lo siguiente:
- Ve a https://paymentrequest-demo.glitch.me/.
- Ve a la parte inferior de la página.
- Presiona Agregar un botón de pago.
- Ingresa
https://paymenthandler-demo.glitch.me
en el campo Payment Method Identifier (Identificador de la forma de pago). - Presiona el botón Pagar junto al campo.
Próximos pasos
En este artículo, aprendimos a organizar una transacción de pago desde un service worker. El siguiente paso es aprender a agregar algunas funciones más avanzadas al service worker.