Autentica con una Confirmación de pago seguro

Los comercios pueden utilizar la confirmación de pago segura (SPC) como parte de un proceso de autenticación sólida de clientes (SCA) para una tarjeta de crédito o cuenta bancaria determinadas. WebAuthn realiza la autenticación (frecuentemente mediante 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 SPC es cuando un cliente realiza una compra en la cuenta de un comercio y la entidad emisora de la tarjeta de crédito o el banco requieren la autenticación del pagador.

Flujo de trabajo de autenticación

Analicemos el flujo de autenticación:

  1. Un cliente proporciona sus credenciales de pago (como la tarjeta de crédito información) al comercio.
  2. El comercio solicita al banco o la entidad emisora correspondiente de la credencial de pago. (parte de confianza o RP) si el pagador necesita una autenticación independiente. Esta intercambio podría ocurrir, por ejemplo, con EMV® 3-D Secure.
    • Si el RP quiere que el comercio use SPC, y si el usuario ya registradas, el RP responde con una lista de IDs de credenciales registradas por el pagador y un desafío.
    • Si no se necesita autenticación, el comercio puede completar la transacción.
  3. Si se necesita una autenticación, el comercio determina si el navegador es compatible con SPC.
    • Si el navegador no es compatible con SPC, continúa con la configuración de autenticación de la organización.
  4. El comercio invoca a SPC. El navegador muestra un cuadro de diálogo de confirmación.
    • Si no hay IDs de credenciales pasados desde la parte restringida, recurre a la flujo de autenticación existente. Tras una autenticación exitosa, considera usar el registro de SPC para optimizar autenticaciones futuras.
  5. El usuario confirma y autentica el importe y el destino del pagos mediante el desbloqueo del dispositivo.
  6. El comercio recibe una credencial de la autenticación.
  7. El RP recibe la credencial del comercio y verifica su la autenticidad.
  8. La parte restringida envía los resultados de la verificación al comercio.
  9. El comercio muestra al usuario un mensaje para indicar si el pago se realizó correcta o incorrecta.

Detección de funciones

Para detectar si se admite SPC en el navegador, puedes enviar una llamada falsa a canMakePayment()

Copia y pega el siguiente código para detectar la 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 Parámetros secure-payment-confirmation y WebAuthn:

Estos son los parámetros que debes proporcionar a la propiedad data de la forma de pago, SecurePaymentConfirmationRequest.

Parámetro Descripción
rpId El nombre de host del origen del RP como ID de RP.
challenge Un desafío aleatorio que evita ataques de repetición.
credentialIds Un array de IDs de credenciales. En la autenticación de WebAuthn, la propiedad allowCredentials acepta un array de objetos PublicKeyCredentialDescriptor, pero en SPC, solo se pasa una lista de IDs de credenciales.
payeeName (opcional) Nombre del beneficiario.
payeeOrigin Indica el origen del beneficiario. En el caso anterior, se trata del origen del comercio.
instrument Una cadena para displayName y una URL para icon que apunta a un recurso de imagen. Un valor booleano opcional (el valor predeterminado es true) para iconMustBeShown que especifica un ícono que se debe recuperar y mostrar correctamente para que la solicitud se realice correctamente.
timeout Tiempo de espera para firmar la transacción en milisegundos
extensions Se agregaron las extensiones a la llamada de WebAuthn. No es necesario que especifiques el "pago". con extensiones por tu cuenta.

Mira 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() da como resultado una PaymentResponse excepto que details contiene una credencial de clave pública con una clientDataJSON que contiene los datos de la transacción (payment) para que el RP la verifique.

La credencial resultante debe transferirse de origen cruzado al RP y verificados.

Cómo la parte restringida verifica la transacción

Verificar los datos de la transacción en el servidor de RP es el paso más importante el proceso de pago.

Para verificar los datos de la transacción, el RP puede seguir el proceso de verificación de aserción de autenticación de WebAuthn. Además, deben Verifica 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 el origen del comercio en el ejemplo anterior).
  • El payeeOrigin coincide con el origen del beneficiario que debería haber sido que se le muestran al usuario.
  • El total coincide con el importe de la transacción que se debería haber mostrado. para el usuario.
  • El instrument coincide con los detalles del instrumento de pago que deberían se le mostraron 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.';
}

Una vez que se aprueban todos los criterios de verificación, el RP puede informar al comerciante que la transacción se realizó correctamente.

Próximos pasos