Como adaptar seu app de pagamento baseado na Web para o Web Payments e proporcionar uma melhor experiência do usuário aos clientes.
Depois que o app de pagamento for registrado, você vai poder aceitar solicitações de pagamento dos comerciantes. Nesta postagem, explicamos como orquestrar uma transação de pagamento de um service worker durante o tempo de execução (ou seja, quando uma janela é exibida e o usuário está interagindo com ela).
![Como orquestrar transações de pagamento com um service worker](https://web.dev/static/articles/orchestrating-payment-transactions/image/orchestrating-payment-tra-dd17687ea595a.png?authuser=6&hl=pt)
"Alterações no parâmetro de pagamento no ambiente de execução" se referem a um conjunto de eventos que permite que o comerciante e o gerenciador de pagamento troquem mensagens enquanto o usuário interage com o gerenciador de pagamento. Saiba mais em Como gerenciar informações de pagamento opcionais com um service worker.
Receber um evento de solicitação de pagamento do comerciante
Quando um cliente opta por pagar com seu app de pagamento baseado na Web e o comerciante invoca PaymentRequest.show()
, o service worker recebe um evento paymentrequest
. Adicione um listener de eventos
ao service worker para capturar o evento e se preparar para a próxima ação.
[gerenciador de pagamentos] 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;
…
O PaymentRequestEvent
preservado contém informações importantes sobre essa
transação:
Nome da propriedade | Descrição |
---|---|
topOrigin |
Uma string que indica a origem da página da Web de nível superior (geralmente o comerciante beneficiário). Use isso para identificar a origem do comerciante. |
paymentRequestOrigin |
Uma string que indica a origem do invocador. Pode ser igual a topOrigin quando o comerciante invoca a API Payment Request diretamente, mas pode ser diferente se a API for invocada em um iframe por um terceiro, como um gateway de pagamento.
|
paymentRequestId |
A propriedade id do PaymentDetailsInit fornecida à API Payment Request. Se o comerciante fizer isso, o navegador vai fornecer um ID gerado automaticamente.
|
methodData |
Os dados específicos da forma de pagamento fornecidos pelo comerciante como parte do PaymentMethodData .
Use isso para determinar os detalhes da transação de pagamento.
|
total |
O valor total fornecido pelo comerciante como parte do PaymentDetailsInit .
Use-o para criar uma interface e informar ao cliente o valor total a ser pago.
|
instrumentKey |
A chave do instrumento selecionada pelo usuário. Isso reflete o instrumentKey que você forneceu com antecedência. Uma string vazia indica que o usuário não especificou nenhum instrumento.
|
Abra a janela do gerenciador de pagamento para exibir o front-end do app de pagamento baseado na Web.
Quando um evento paymentrequest
é recebido, o app de pagamento pode abrir uma janela do gerenciador de pagamentos chamando PaymentRequestEvent.openWindow()
. A janela do gerenciador de pagamento apresentará aos clientes a interface do app de pagamento, em que eles podem se autenticar, escolher o endereço de entrega e as opções e autorizar o pagamento. Abordaremos como escrever o código front-end em Como processar pagamentos no front-end de pagamento (em breve).
Transmita uma promessa preservada para PaymentRequestEvent.respondWith()
a fim de que você possa resolvê-la com um resultado de pagamento no futuro.
[gerenciador de pagamentos] 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);
};
});
…
Você pode usar um polyfill PromiseResolver
conveniente para resolver uma promessa no tempo arbitrário.
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_ }
}
Trocar informações com o front-end
O service worker do app de pagamento pode trocar mensagens com o front-end do app de pagamento
por meio de ServiceWorkerController.postMessage()
. Para receber mensagens
do front-end, detecte eventos message
.
[gerenciador de pagamentos] service-worker.js:
// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
if (client) client.postMessage({ type, ...contents });
}
Receber o indicador de prontidão do front-end
Depois que a janela do gerenciador de pagamento é aberta, o service worker precisa aguardar um sinal de estado pronto do front-end do app de pagamento. O service worker pode transmitir informações importantes para o front-end quando estiver pronto.
front-end do [gerenciador de pagamentos]:
navigator.serviceWorker.controller.postMessage({
type: 'WINDOW_IS_READY'
});
[gerenciador de pagamentos] 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;
…
Transmitir os detalhes da transação para o front-end
Agora envie os detalhes de pagamento de volta. Nesse caso, você está enviando apenas o total da solicitação de pagamento, mas pode passar mais detalhes se quiser.
[gerenciador de pagamentos] service-worker.js:
…
// Pass the payment details to the frontend
postMessage('PAYMENT_IS_READY', { total });
break;
…
front-end do [gerenciador de pagamentos]:
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;
…
Devolver as credenciais de pagamento do cliente
Quando o cliente autoriza o pagamento, o front-end pode enviar uma mensagem de postagem
ao service worker para prosseguir. Você pode resolver a promessa passada ao PaymentRequestEvent.respondWith()
para enviar o resultado de volta ao comerciante.
Transmita um
objeto
PaymentHandlerResponse
.
Nome da propriedade | Descrição |
---|---|
methodName |
O identificador da forma de pagamento usada para fazer o pagamento. |
details |
Os dados específicos da forma de pagamento que fornecem as informações necessárias para o comerciante processar o pagamento. |
front-end do [gerenciador de pagamentos]:
const paymentMethod = …
postMessage('PAYMENT_AUTHORIZED', {
paymentMethod, // Payment method identifier
});
[gerenciador de pagamentos] 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 a transação de pagamento
Para permitir que o cliente cancele a transação, o front-end pode enviar uma mensagem de postagem para o service worker, que pode resolver a promessa transmitida ao PaymentRequestEvent.respondWith()
com null
para indicar ao comerciante que a transação foi cancelada.
front-end do [gerenciador de pagamentos]:
postMessage('CANCEL_PAYMENT');
[gerenciador de pagamentos] 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;
…
Exemplo de código
Todos os códigos de amostra que você viu neste documento foram trechos do seguinte app de exemplo em funcionamento:
https://paymenthandler-demo.glitch.me
[gerenciador de pagamentos] service worker
front-end do [gerenciador de pagamentos]
Para testar:
- Acesse https://paymentrequest-demo.glitch.me/ (link em inglês).
- Acesse a parte inferior da página.
- Pressione o botão Adicionar um pagamento.
- Insira
https://paymenthandler-demo.glitch.me
no campo Identificador da forma de pagamento. - Pressione o botão Pagar ao lado do campo.
Próximas etapas
Neste artigo, aprendemos como orquestrar uma transação de pagamento de um service worker. A próxima etapa é aprender como adicionar alguns recursos mais avançados ao service worker.