احراز هویت با تأیید پرداخت امن

بازرگانان می‌توانند از تأیید پرداخت امن (SPC) به عنوان بخشی از فرآیند تأیید اعتبار مشتری (SCA) قوی برای یک کارت اعتباری یا حساب بانکی استفاده کنند. WebAuthn احراز هویت را انجام می دهد (اغلب از طریق بیومتریک). WebAuthn باید از قبل ثبت شده باشد، که می توانید در مورد ثبت تأیید پرداخت امن اطلاعات کسب کنید.

یک پیاده سازی معمولی چگونه کار می کند

رایج ترین استفاده از SPC زمانی است که مشتری در سایت یک تاجر خرید می کند و صادرکننده کارت اعتباری یا بانک به احراز هویت پرداخت کننده نیاز دارد.

گردش کار احراز هویت

بیایید از طریق جریان احراز هویت عبور کنیم:

  1. یک مشتری اعتبار پرداخت خود را (مانند اطلاعات کارت اعتباری) در اختیار تاجر قرار می دهد.
  2. تاجر از صادرکننده یا بانک مربوطه اعتبار پرداخت (طرف متکی یا RP) می‌پرسد که آیا پرداخت‌کننده به احراز هویت جداگانه نیاز دارد. این تبادل ممکن است، برای مثال، با EMV® 3-D Secure اتفاق بیفتد.
    • اگر RP بخواهد تاجر از SPC استفاده کند، و اگر کاربر قبلا ثبت نام کرده باشد، RP با لیستی از شناسه های اعتبار ثبت شده توسط پرداخت کننده و یک چالش پاسخ می دهد.
    • اگر به احراز هویت نیاز نباشد، تاجر می‌تواند به تکمیل تراکنش ادامه دهد.
  3. اگر به احراز هویت نیاز باشد، تاجر تعیین می‌کند که آیا مرورگر از SPC پشتیبانی می‌کند یا خیر .
    • اگر مرورگر از SPC پشتیبانی نمی کند، با جریان احراز هویت موجود ادامه دهید.
  4. تاجر SPC را فراخوانی می کند. مرورگر یک گفتگوی تایید را نمایش می دهد.
    • اگر هیچ شناسه اعتباری ارسال شده از RP وجود ندارد، به جریان احراز هویت موجود برگردید. پس از احراز هویت موفقیت آمیز، استفاده از ثبت SPC را برای ساده سازی احراز هویت آینده در نظر بگیرید .
  5. کاربر با باز کردن قفل دستگاه مبلغ و مقصد پرداخت را تایید و احراز هویت می کند.
  6. تاجر از احراز هویت یک اعتبار دریافت می کند.
  7. RP اعتبارنامه را از تاجر دریافت می کند و صحت آن را تأیید می کند.
  8. RP نتایج تأیید را برای تاجر ارسال می کند.
  9. تاجر پیامی را به کاربر نشان می دهد که نشان دهد پرداخت موفقیت آمیز بوده یا ناموفق.

تشخیص ویژگی

برای تشخیص اینکه آیا SPC در مرورگر پشتیبانی می‌شود، می‌توانید یک تماس جعلی به canMakePayment() ارسال کنید.

کد زیر را کپی و جایگذاری کنید تا ویژگی تشخیص SPC در وب سایت یک تاجر وجود داشته باشد.

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

احراز هویت کاربر

برای احراز هویت کاربر، متد PaymentRequest.show() با پارامترهای secure-payment-confirmation و WebAuthn فراخوانی کنید:

در اینجا پارامترهایی است که باید برای ویژگی data روش پرداخت، SecurePaymentConfirmationRequest ، ارائه دهید.

پارامتر توضیحات
rpId نام میزبان مبدا RP به عنوان RP ID.
challenge یک چالش تصادفی که از حملات تکراری جلوگیری می کند.
credentialIds مجموعه ای از شناسه های اعتبار. در احراز هویت WebAuthn، ویژگی allowCredentials آرایه ای از اشیاء PublicKeyCredentialDescriptor را می پذیرد، اما در SPC، شما فقط لیستی از شناسه های اعتبار را ارسال می کنید.
payeeName (اختیاری) نام دریافت کننده پرداخت.
payeeOrigin منشاء گیرنده. در سناریوی فوق، منشأ تاجر است.
instrument یک رشته برای displayName و یک URL برای icon که به یک منبع تصویر اشاره می کند. یک بولی اختیاری (پیش‌فرض به true ) برای iconMustBeShown که یک نماد را مشخص می‌کند باید با موفقیت واکشی شود و نشان داده شود تا درخواست موفق شود.
timeout مهلت امضای تراکنش در میلی ثانیه است
extensions برنامه های افزودنی به تماس WebAuthn اضافه شده است. لازم نیست خودتان پسوند «پرداخت» را مشخص کنید.

این کد نمونه را بررسی کنید:

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

.show() show منجر به یک شی PaymentResponse می شود به جز details حاوی یک اعتبار کلید عمومی با یک clientDataJSON که حاوی داده های تراکنش ( payment ) برای تأیید توسط RP است.

اعتبار حاصل باید به صورت متقاطع به RP منتقل شود و تأیید شود.

چگونه RP تراکنش را تأیید می کند

تأیید داده های تراکنش در سرور RP مهمترین مرحله در فرآیند پرداخت است.

برای تأیید داده‌های تراکنش، RP می‌تواند فرآیند تأیید تأیید اعتبار WebAuthn را دنبال کند. علاوه بر این، آنها باید payment را تأیید کنند .

نمونه بارگیری از 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"
    }
  }
}
  • rp با مبدا RP مطابقت دارد.
  • topOrigin با مبدا سطح بالایی که RP انتظار دارد مطابقت دارد (منشا تاجر در مثال بالا).
  • payeeOrigin با مبدا دریافت‌کننده مطابقت دارد که باید به کاربر نمایش داده می‌شد.
  • total با مبلغ تراکنشی که باید به کاربر نمایش داده می شد مطابقت دارد.
  • instrument با جزئیات ابزار پرداخت مطابقت دارد که باید به کاربر نمایش داده می شد.
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.';
}

پس از گذراندن تمام معیارهای تأیید، RP می تواند به تاجر بگوید که تراکنش موفق بوده است.

مراحل بعدی