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

إيجي كيتامورا
إيجي كيتامورا

يمكن للتجّار استخدام "تأكيد الدفع الآمن" (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:

في ما يلي المَعلمات التي يجب توفيرها للموقع الإلكتروني على data في طريقة الدفع، SecurePaymentConfirmationRequest.

المَعلمة الوصف
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.';
}

بعد اجتياز جميع معايير التحقق، يمكن للجهة المحظورة إعلام التاجر بنجاح العملية.

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