Güvenli Ödeme Onayı ile kimliğinizi doğrulayın

Eiji Kitamura
Eiji Kitamura

Satıcılar, belirli bir kredi kartı veya banka hesabı için güçlü bir müşteri kimlik doğrulama (SCA) sürecinin bir parçası olarak Güvenli Ödeme Onayı (SPC) özelliğini kullanabilir. WebAuthn, kimlik doğrulamasını genellikle biyometri aracılığıyla gerçekleştirir. WebAuthn'un önceden kaydettirilmesi gerekir. Bu konu hakkında daha fazla bilgiyi Güvenli Ödeme Onayı Kaydetme bölümünde bulabilirsiniz.

Tipik bir uygulamanın işleyiş şekli

SPC'nin en yaygın kullanımı, müşterinin satıcının sitesinden alışveriş yapması ve kredi kartını veren kuruluş ya da bankanın ödeyen kimlik doğrulamasını zorunlu kılmasıdır.

Kimlik doğrulama iş akışı.

Kimlik doğrulama akışını inceleyelim:

  1. Bir müşteri, ödeme kimlik bilgilerini (kredi kartı bilgileri gibi) satıcıya iletir.
  2. Ödeme yapan kişinin ayrı bir kimlik doğrulaması gerekiyorsa satıcı, ödeme kimlik bilgisinin ilgili kuruluşundan veya bankadan (bağımlı taraf veya RP) iletişime geçmesini ister. Bu değişim, örneğin EMV® 3-D Secure ile yapılabilir.
    • RP, satıcının SPC'yi kullanmasını isterse ve kullanıcı daha önce kayıt yaptırdıysa RP yanıt veren taraf tarafından kaydedilen kimlik bilgisi kimliklerinin bir listesi ve bir girişle yanıt verir.
    • Kimlik doğrulama gerekmiyorsa satıcı işlemi tamamlamaya devam edebilir.
  3. Kimlik doğrulama gerekiyorsa tarayıcının SPC'yi destekleyip desteklemediğini satıcı belirler.
    • Tarayıcı SPC'yi desteklemiyorsa mevcut kimlik doğrulama akışını uygulayın.
  4. Satıcının SPC'yi çağırması. Tarayıcıda bir onay iletişim kutusu görüntülenir.
    • RP'den geçirilen kimlik bilgisi kimliği yoksa mevcut kimlik doğrulama akışına geri dönün. Başarılı bir kimlik doğrulama işlemi gerçekleştirdikten sonra, gelecekteki kimlik doğrulama işlemlerini kolaylaştırmak için SPC kaydını kullanabilirsiniz.
  5. Kullanıcı, cihazın kilidini açarak ödemenin tutarını ve hedefini onaylar ve doğrular.
  6. Satıcı, kimlik doğrulamadan kimlik bilgisi alır.
  7. RP, kimlik bilgisini satıcıdan alır ve orijinalliğini doğrular.
  8. RP, doğrulama sonuçlarını satıcıya gönderir.
  9. Satıcı, kullanıcıya ödemenin başarılı veya başarısız olduğunu belirten bir mesaj gösterir.

Özellik algılama

Tarayıcıda SPC'nin desteklenip desteklenmediğini belirlemek için canMakePayment() adresine sahte bir arama gönderebilirsiniz.

SPC'yi algılama özelliğini bir satıcının web sitesinde öne çıkarmak için aşağıdaki kodu kopyalayıp yapıştırın.

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.
  }
});

Kullanıcının kimliğini doğrulayın

Kullanıcının kimliğini doğrulamak için secure-payment-confirmation ve WebAuthn parametreleriyle PaymentRequest.show() yöntemini çağırın:

Ödeme yönteminin data mülküne (SecurePaymentConfirmationRequest) sağlamanız gereken parametreler aşağıda verilmiştir.

Parametre Açıklama
rpId RP kimliği olarak RP kaynağının ana makine adıdır.
challenge Tekrar oynama saldırılarını önleyen rastgele bir meydan okuma.
credentialIds Kimlik bilgisi kimlikleri dizisi. WebAuthn'un kimlik doğrulamasında allowCredentials özelliği, bir dizi PublicKeyCredentialDescriptor nesnesini kabul eder, ancak SPC'de yalnızca kimlik bilgisi kimliklerinin listesini iletirsiniz.
payeeName (isteğe bağlı) Alacaklının adı.
payeeOrigin Alacaklının kaynağı. Yukarıda belirtilen senaryoda bu, satıcının kaynağıdır.
instrument Bir resim kaynağına işaret eden displayName dizesi ve icon için bir URL. iconMustBeShown için, isteğin başarılı olması için bir simgenin başarıyla getirilmesi ve gösterilmesi gerektiğini belirten isteğe bağlı bir boole değeri (varsayılan olarak true).
timeout İşlemi imzalamak için zaman aşımı (milisaniye)
extensions Uzantılar WebAuthn çağrısına eklendi. "Ödeme" uzantısını sizin belirtmeniz gerekmez.

Şu örnek koda bakın:

// 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);
}

details işlevi, RP tarafından doğrulanması için işlem verilerini (payment) içeren bir ortak anahtar kimlik bilgisi içermesi dışında .show() işlevi bir PaymentResponse nesnesiyle sonuçlanır.clientDataJSON

Elde edilen kimlik bilgisi, kaynaklar arası olarak RP'ye aktarılmalı ve doğrulanmalıdır.

RP'nin işlemi doğrulama şekli

RP sunucusundaki işlem verilerinin doğrulanması, ödeme sürecinin en önemli adımıdır.

RP, işlem verilerini doğrulamak için WebAuthn'un kimlik doğrulama onayı doğrulama sürecini izleyebilir. Ayrıca, payment belgesini doğrulaması gerekir.

Örnek clientDataJSON yükü:

{
  "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"
    }
  }
}
  • rp, RP'nin kaynağıyla eşleşiyor.
  • topOrigin, RP'nin beklediği üst düzey kaynakla (satıcının yukarıdaki örnekte kaynağı) eşleşir.
  • payeeOrigin, kullanıcıya gösterilmesi gereken alacaklının kaynağıyla eşleşir.
  • total, kullanıcıya gösterilmesi gereken işlem tutarıyla eşleşir.
  • instrument, kullanıcıya gösterilmesi gereken ödeme aracı ayrıntılarıyla eşleşir.
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.';
}

Tüm doğrulama kriterleri geçildikten sonra RP, satıcıya işlemin başarılı olduğunu bildirebilir.

Sonraki adımlar