Los comercios pueden usar la Confirmación de pago seguro (SPC) como parte de un proceso de autenticación reforzada de clientes (SCA) para una tarjeta de crédito o cuenta bancaria determinada. WebAuthn realiza la autenticación (a menudo a través de datos biométricos). WebAuthn debe registrarse con anticipación. Puedes obtener más información en Registra una confirmación de pago segura.
Cómo funciona una implementación típica
El uso más común de la SPC es cuando un cliente realiza una compra en el sitio de un comercio y la entidad emisora de la tarjeta de crédito o el banco requiere la autenticación del pagador.
Analicemos el flujo de autenticación:
- Un cliente proporciona sus credenciales de pago (como la información de la tarjeta de crédito) al comercio.
- El comercio pregunta al banco o la entidad emisora de la credencial de pago correspondiente (parte de confianza o RP) si el pagador necesita una autenticación independiente. Este intercambio puede ocurrir, por ejemplo, con EMV® 3-D Secure.
- Si el RP desea que el comercio use SPC y el usuario ya se registró, el RP responde con una lista de IDs de credenciales registrados por el pagador y un desafío.
- Si no se necesita una autenticación, el comercio puede seguir completando la transacción.
- Si se necesita una autenticación, el comercio determina si el navegador admite SPC.
- Si el navegador no admite SPC, continúa con el flujo de autenticación existente.
- El comercio invoca a SPC. El navegador muestra un diálogo de confirmación.
- Si no se pasan IDs de credenciales desde el RP, recurre al flujo de autenticación existente. Después de una autenticación correcta, considera usar el registro de SPC para optimizar las autenticaciones futuras.
- El usuario confirma y autentica el importe y el destino del pago desbloqueando el dispositivo.
- El comercio recibe una credencial de la autenticación.
- El RP recibe la credencial del comercio y verifica su autenticidad.
- El RP envía los resultados de la verificación al comercio.
- El comercio muestra al usuario un mensaje para indicar si el pago se realizó correctamente o no.
Detección de atributos
Para detectar si SPC es compatible con el navegador, puedes enviar una llamada falsa a canMakePayment()
.
Copia y pega el siguiente código para detectar SPC en el sitio web de un comercio.
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 al usuario
Para autenticar al usuario, invoca el método PaymentRequest.show()
con los parámetros secure-payment-confirmation
y WebAuthn:
PublicKeyCredentialRequestOptions
- Otros parámetros específicos del pago en la plataforma del comercio
Estos son los parámetros que debes proporcionar a la propiedad data
de la forma de pago, SecurePaymentConfirmationRequest
.
Consulta este código de ejemplo:
// 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);
}
La función .show()
genera un objeto PaymentResponse
, excepto que details
contiene una credencial de clave pública con un clientDataJSON
que contiene los datos de la transacción (payment
) para que los verifique el RP.
La credencial resultante se debe transferir entre orígenes al RP y verificar.
Cómo verifica la transacción el RP
La verificación de los datos de la transacción en el servidor del RP es el paso más importante del proceso de pago.
Para verificar los datos de la transacción, el RP puede seguir el proceso de verificación de la aserción de autenticación de WebAuthn.
Además, debe verificar el payment
.
Una carga útil de ejemplo de 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"
}
}
}
- El
rp
coincide con el origen del RP. - El
topOrigin
coincide con el origen de nivel superior que espera el RP (el origen del comercio en el ejemplo anterior). - El
payeeOrigin
coincide con el origen del beneficiario que se le debería haber mostrado al usuario. - El
total
coincide con el importe de la transacción que se le debería haber mostrado al usuario. - El elemento
instrument
coincide con los detalles del instrumento de pago que se le deberían haber mostrado al usuario.
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.';
}
Después de que se cumplan todos los criterios de verificación, el RP puede informar al comercio que la transacción se realizó correctamente.
Próximos pasos
- Lee la descripción general de la Confirmación de pago seguro.
- Más información sobre el registro con la Confirmación de pago segura