Os comerciantes podem usar a Confirmação de Pagamento Seguro (SPC, na sigla em inglês) como parte de um processo de Autenticação forte do cliente (SCA) para um determinado cartão de crédito ou conta bancária. O WebAuthn realiza a autenticação (geralmente por biometria). O WebAuthn precisa ser registrado com antecedência. Saiba mais em Registrar uma confirmação de pagamento seguro.
Como funciona uma implementação típica
O uso mais comum do SPC é quando um cliente faz uma compra no site de um comerciante e o emissor do cartão de crédito ou o banco exige a autenticação do pagador.
Vamos analisar o fluxo de autenticação:
- Um cliente fornece as credenciais de pagamento (como informações de cartão de crédito) ao comerciante.
- O comerciante pergunta ao emissor ou banco correspondente da credencial de pagamento (parte confiável ou RP) se o pagador precisa de uma autenticação separada. Essa troca pode acontecer, por exemplo, com a EMV® 3-D Secure.
- Se o RP quiser que o comerciante use o SPC e se o usuário já tiver se registrado, o RP vai responder com uma lista de IDs de credenciais registrados pelo pagador e um desafio.
- Se não for necessário, o comerciante poderá continuar concluindo a transação.
- Se for necessário fazer uma autenticação, o comerciante determina se o navegador oferece suporte ao SPC.
- Se o navegador não for compatível com o SPC, prossiga com o fluxo de autenticação atual.
- O comerciante invoca o SPC. O navegador mostra uma caixa de diálogo de confirmação.
- Se não houver IDs de credencial transmitidos pelo RP, volte ao fluxo de autenticação atual. Depois de uma autenticação bem-sucedida, use o registro de SPC para agilizar autenticações futuras.
- O usuário confirma e autentica o valor e o destino do pagamento desbloqueando o dispositivo.
- O comerciante recebe uma credencial da autenticação.
- O RP recebe a credencial do comerciante e verifica a autenticidade dela.
- O RP envia os resultados da verificação ao comerciante.
- O comerciante mostra ao usuário uma mensagem para indicar se o pagamento foi bem-sucedido ou não.
Detecção de recursos
Para detectar se o SPC é compatível com o navegador, envie uma chamada falsa para canMakePayment()
.
Copie e cole o código abaixo para detectar SPC no site de um comerciante.
const isSecurePaymentConfirmationSupported = async () => { if (!'PaymentRequest' in window) { return [false, 'Payment Request API is not supported']; } try { // The data below is the minimum required to create the request and // check if a payment can be made. const supportedInstruments = [ { supportedMethods: "secure-payment-confirmation", data: { // RP's hostname as its ID rpId: 'rp.example', // A dummy credential ID credentialIds: [new Uint8Array(1)], // A dummy challenge challenge: new Uint8Array(1), instrument: { // Non-empty display name string displayName: ' ', // Transparent-black pixel. icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg==', }, // A dummy merchant origin payeeOrigin: 'https://non-existent.example', } } ]; const details = { // Dummy shopping details total: {label: 'Total', amount: {currency: 'USD', value: '0'}}, }; const request = new PaymentRequest(supportedInstruments, details); const canMakePayment = await request.canMakePayment(); return [canMakePayment, canMakePayment ? '' : 'SPC is not available']; } catch (error) { console.error(error); return [false, error.message]; } }; isSecurePaymentConfirmationSupported().then(result => { const [isSecurePaymentConfirmationSupported, reason] = result; if (isSecurePaymentConfirmationSupported) { // Display the payment button that invokes SPC. } else { // Fallback to the legacy authentication method. } });
Autenticação do usuário
Para autenticar o usuário, invoque o método PaymentRequest.show()
com os parâmetros secure-payment-confirmation
e WebAuthn:
PublicKeyCredentialRequestOptions
- Outros parâmetros específicos de pagamento na plataforma do comerciante.
Confira os parâmetros que você precisa fornecer à propriedade data
da forma de pagamento, SecurePaymentConfirmationRequest
.
Confira este exemplo de código:
// After confirming SPC is available on this browser via a feature detection, // fetch the request options cross-origin from the RP server. const options = fetchFromServer('https://rp.example/spc-auth-request'); const { credentialIds, challenge } = options; const request = new PaymentRequest([{ // Specify `secure-payment-confirmation` as payment method. supportedMethods: "secure-payment-confirmation", data: { // The RP ID rpId: 'rp.example', // List of credential IDs obtained from the RP server. credentialIds, // The challenge is also obtained from the RP server. challenge, // A display name and an icon that represent the payment instrument. instrument: { displayName: "Fancy Card ****1234", icon: "https://rp.example/card-art.png", iconMustBeShown: false }, // The origin of the payee (merchant) payeeOrigin: "https://merchant.example", // The number of milliseconds to timeout. timeout: 360000, // 6 minutes } }], { // Payment details. total: { label: "Total", amount: { currency: "USD", value: "5.00", }, }, }); try { const response = await request.show(); // response.details is a PublicKeyCredential, with a clientDataJSON that // contains the transaction data for verification by the issuing bank. // Make sure to serialize the binary part of the credential before // transferring to the server. const result = fetchFromServer('https://rp.example/spc-auth-response', response.details); if (result.success) { await response.complete('success'); } else { await response.complete('fail'); } } catch (err) { // SPC cannot be used; merchant should fallback to traditional flows console.error(err); }
A função .show()
resulta em um objeto PaymentResponse
, exceto que o details
contém uma credencial de chave pública com um clientDataJSON
que contém os dados da transação (payment
) para verificação pelo RP.
A credencial resultante precisa ser transferida entre origens para o RP e verificada.
Como o RP verifica a transação
A verificação dos dados da transação no servidor do RP é a etapa mais importante do processo de pagamento.
Para verificar os dados da transação, o RP pode seguir o processo de verificação de declaração de autenticação do WebAuthn. Além disso, eles precisam verificar o payment
.
Um exemplo de payload do clientDataJSON
:
{ "type":"payment.get", "challenge":"SAxYy64IvwWpoqpr8JV1CVLHDNLKXlxbtPv4Xg3cnoc", "origin":"https://spc-merchant.glitch.me", "crossOrigin":false, "payment":{ "rp":"spc-rp.glitch.me", "topOrigin":"https://spc-merchant.glitch.me", "payeeOrigin":"https://spc-merchant.glitch.me", "total":{ "value":"15.00", "currency":"USD" }, "instrument":{ "icon":"https://cdn.glitch.me/94838ffe-241b-4a67-a9e0-290bfe34c351%2Fbank.png?v=1639111444422", "displayName":"Fancy Card 825809751248" } } }
- O
rp
corresponde à origem do RP. - O
topOrigin
corresponde à origem de nível superior esperada pelo RP (a origem do comerciante no exemplo acima). - O
payeeOrigin
corresponde à origem do beneficiário que deveria ter sido exibida ao usuário. - O
total
corresponde ao valor da transação que deveria ter sido mostrado ao usuário. - O
instrument
corresponde aos detalhes do instrumento de pagamento que deveriam ter sido exibidos ao usuário.
const clientData = base64url.decode(response.clientDataJSON); const clientDataJSON = JSON.parse(clientData); if (!clientDataJSON.payment) { throw 'The credential does not contain payment payload.'; } const payment = clientDataJSON.payment; if (payment.rp !== expectedRPID || payment.topOrigin !== expectedOrigin || payment.payeeOrigin !== expectedOrigin || payment.total.value !== '15.00' || payment.total.currency !== 'USD') { throw 'Malformed payment information.'; }
Depois que todos os critérios de verificação forem atendidos, o RP poderá informar ao merchant que a transação foi concluída.
Próximas etapas
- Leia a visão geral da Confirmação de pagamento segura.
- Saiba mais sobre o registro com a Confirmação de Pagamento Seguro