المصادقة باستخدام تأكيد الدفع الآمن

يمكن للتجّار استخدام ميزة "تأكيد الدفع الآمن" (SPC) كجزء من عملية المصادقة القوية للعملاء (SCA) على بطاقة ائتمان أو حساب مصرفي معيّن. يُجري WebAuthn المصادقة (غالبًا من خلال المقاييس الحيوية). يجب تسجيل WebAuthn مسبقًا، ويمكنك الاطّلاع على مزيد من المعلومات في مقالة تسجيل تأكيد الدفع الآمن.

آلية عمل التنفيذ النموذجي

الاستخدام الأكثر شيوعًا لبطاقة SPC هو عندما يُجري العميل عملية شراء على الموقع الإلكتروني للتاجر، وتتطلّب جهة إصدار بطاقة الائتمان أو المصرف مصادقة الجهة المسدِّدة.

سير عمل المصادقة

لنطّلِع على مسار المصادقة:

  1. يقدّم العميل بيانات اعتماد الدفع (مثل بيانات بطاقة الائتمان) إلى التاجر.
  2. ويطلب التاجر من جهة إصدار بيانات اعتماد الدفع أو المصرف (الطرف المعتمد أو الجهة المحظورة) جهة إصدار بيانات اعتماد الدفع إذا احتاجت الجهة المسدِّدة إلى مصادقة منفصلة. وقد يحدث هذا التبادل، على سبيل المثال، مع EMV® 3-D Secure.
    • إذا كان الطرف المعني يريد أن يستخدم التاجر SPC، وإذا كان المستخدم قد سجّل في وقت سابق، فإن الجهة المحظورة يجيب بقائمة من معرّفات بيانات الاعتماد المسجلة من قبل الدافع بالإضافة إلى تحدٍ.
    • إذا لم تكن هناك حاجة إلى المصادقة، يمكن للتاجر مواصلة إكمال المعاملة.
  3. إذا كانت المصادقة مطلوبة، يحدد التاجر ما إذا كان المتصفِّح متوافقًا مع SPC.
    • إذا كان المتصفّح لا يتيح استخدام وحدة SPC، يمكنك المتابعة من خلال خطوات المصادقة الحالية.
  4. يستدعي التاجر بطاقة SPC. يعرض المتصفّح مربّع حوار التأكيد.
    • إذا لم يكن هناك أي معرّفات بيانات اعتماد تم تمريرها من الجهة المحظورة، يُرجى الرجوع إلى مسار المصادقة الحالي. بعد إجراء مصادقة ناجحة، يمكنك استخدام تسجيل SPC لتبسيط عمليات المصادقة المستقبلية.
  5. يتحقق المستخدم من مبلغ الدفعة ووجهتها ويصادق عليها من خلال فتح قفل الجهاز.
  6. يتلقّى التاجر بيانات اعتماد من عملية المصادقة.
  7. يتلقّى الجهة المحظورة بيانات الاعتماد من التاجر وتتحقّق من أصالتها.
  8. يرسل الجهة المحظورة نتائج إثبات الهوية إلى التاجر.
  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:

في ما يلي المَعلمات التي يجب تقديمها للموقع SecurePaymentConfirmationRequest الخاص بطريقة الدفع على data.

المَعلمة الوصف
rpId اسم المضيف لمصدر الجهة المحظورة كرقم تعريف الجهة المحظورة.
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() كائن PaymentResponse باستثناء أنّ details يحتوي على بيانات اعتماد مفتاح عام مع clientDataJSON يحتوي على بيانات المعاملة (payment) لإثباتها الجهة المحظورة.

يجب نقل بيانات الاعتماد الناتجة من مصدر آخر إلى الجهة المحظورة والتحقّق منها.

كيف يتحقق الجهة المحظورة من المعاملة؟

يُعد التحقّق من بيانات المعاملات على خادم الجهة المحظورة أهمّ خطوة في عملية الدفع.

للتحقّق من بيانات المعاملات، يمكن للجهة المحظورة اتّباع عملية التحقّق من تأكيد المصادقة في 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 مع مصدر الجهة المحظورة.
  • تتطابق السمة topOrigin مع مصدر المستوى الأعلى الذي يتوقّعه الجهة المحظورة (مصدر التاجر في المثال أعلاه).
  • يتطابق 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.';
}

بعد استيفاء جميع معايير إثبات الملكية، يمكن للجهة المحظورة إعلام التاجر بأنّ المعاملة تمّت بنجاح.

الخطوات التالية