Secure Payment Confirmation

This is a test website. Nothing is charged.

(with credential #1)

(with credential #2)

(with credential #1)

(with credential #2)


  

Enroll Credential will make the following request:

const instrument = {
  displayName: 'Troy ยทยทยทยท',
  icon: 'https://rsolomakhin.github.io/pr/spc/troy.png',
};
const rp = {
  id: 'maxlgu.github.io',
  name: 'Max Pay',
};
const pubKeyCredParams = [{
  type: 'public-key',
  alg: -7,  // ECDSA, not supported on Windows.
}, {
  type: 'public-key',
  alg: -257,  // RSA, supported on Windows.
}];
const payment = {
  rp,
  instrument,
  challenge: textEncoder.encode('Enrollment challenge'),
  pubKeyCredParams,
};
const publicKeyCredential = await navigator.credentials.create({payment});
window.localStorage.setItem(
    'credential_identifier',
    btoa(String.fromCharCode(...new Uint8Array(
        publicKeyCredential.rawId))));

Pay $0.01 will make the following request:

new PaymentRequest([{
  supportedMethods: 'secure-payment-confirmation',
  data: {
    action: 'authenticate',
    credentialIds: [Uint8Array.from(
        atob(window.localStorage.getItem('credential_identifier')),
        c => c.charCodeAt(0))],
    instrument,
    networkData: textEncoder.encode('network_data'),
    challenge: textEncoder.encode('network_data'),
    timeout: 60000,
    fallbackUrl: 'https://rsolomakhin.github.io/pr/spc/fallback'
  },
}], {
  total: {
    label: 'Total',
    amount: {
      currency: 'USD',
      value: '0.01',
    },
  },
});

Based on the Secure Payment Confirmation explainer.