إدارة معاملات الدفع مع عامل الخدمات

كيفية تكييف تطبيق الدفع المستند إلى الويب مع Web Payments وتقديم تجربة مستخدم أفضل للعملاء.

بعد تسجيل تطبيق الدفع، تصبح جاهزًا لقبول طلبات الدفع من التجّار. تشرح هذه المشاركة كيفية تنسيق معاملة دفع من مشغّل الخدمات أثناء وقت التشغيل (أي عندما تظهر نافذة ويتفاعل المستخدم معها).

تنسيق معاملات الدفع مع عامل خدمات
تنسيق معاملات الدفع مع مشغّل خدمات

يشير مصطلح "تغييرات مَعلمات الدفع في وقت التشغيل" إلى مجموعة من الأحداث التي تتيح للتاجر والجهة المسؤولة عن معالجة المعاملات تبادل الرسائل أثناء تفاعل المستخدم مع معالج الدفع. يمكنك الاطّلاع على مزيد من المعلومات في مقالة التعامل مع معلومات الدفع الاختيارية مع عامل خدمات.

تلقّي حدث طلب الدفع من التاجر

عندما يختار العميل الدفع باستخدام تطبيق الدفع المستند إلى الويب ويستدعي التاجر PaymentRequest.show()، سيتلقّى عامل الخدمة حدث paymentrequest. أضف أداة معالجة الحدث إلى عامل الخدمة لتسجيل الحدث والاستعداد للإجراء التالي.

[معالج الدفع] service-worker.js:

…
let payment_request_event;
let resolver;
let client;

// `self` is the global object in service worker
self.addEventListener('paymentrequest', async e => {
  if (payment_request_event) {
    // If there's an ongoing payment transaction, reject it.
    resolver.reject();
  }
  // Preserve the event for future use
  payment_request_event = e;
…

تحتوي PaymentRequestEvent التي تم الاحتفاظ بها على معلومات مهمة حول هذه المعاملة:

اسم الموقع الوصف
topOrigin سلسلة تشير إلى أصل صفحة الويب ذات المستوى الأعلى (عادةً ما يكون التاجر المدفوع له). استخدِم هذا الحقل لتحديد مصدر التاجر.
paymentRequestOrigin سلسلة تشير إلى أصل الداعي ويمكن أن يشبه هذا السمة topOrigin عندما يستدعي التاجر واجهة Payment Request API مباشرةً، ولكن قد يختلف إذا تم استدعاء واجهة برمجة التطبيقات من داخل إطار iframe من قِبل جهة خارجية، مثل بوابة الدفع.
paymentRequestId السمة id على PaymentDetailsInit التي يتم تقديمها إلى Payment Request API. إذا حذف التاجر، سيقدّم المتصفّح معرّفًا تم إنشاؤه تلقائيًا.
methodData البيانات الخاصة بطريقة الدفع التي يقدّمها التاجر كجزء من "PaymentMethodData" ويمكنك الاستناد إليه لتحديد تفاصيل معاملة الدفع.
total المبلغ الإجمالي الذي يقدّمه التاجر كجزء من PaymentDetailsInit استخدِم هذا الحقل لإنشاء واجهة مستخدم لإعلام العميل بإجمالي المبلغ المدفوع.
instrumentKey مفتاح الأداة الذي يختاره المستخدم. ويعكس ذلك مبلغ instrumentKey الذي قدّمته مسبقًا. تشير السلسلة الفارغة إلى أن المستخدم لم يحدد أي أدوات.

افتح نافذة معالج الدفع لعرض الواجهة الأمامية لتطبيق الدفع المستند إلى الويب.

عند تلقّي حدث paymentrequest، يمكن لتطبيق الدفع فتح نافذة معالج الدفع من خلال الاتصال بـ PaymentRequestEvent.openWindow(). ستعرض نافذة معالج الدفع للعملاء واجهة تطبيق الدفع الخاص بك حيث يمكنهم المصادقة واختيار عنوان الشحن وخياراته والموافقة على عملية الدفع. سنتناول كيفية كتابة رمز الواجهة الأمامية في التعامل مع الدفعات في الواجهة الأمامية للدفع (قريبًا).

مسار الدفع باستخدام تطبيق دفع مستنِد إلى الويب

أرسِل وعودًا محتفظًا به إلى "PaymentRequestEvent.respondWith()" كي تتمكّن من حلّه من خلال نتيجة دفع في المستقبل.

[معالج الدفع] service-worker.js:

…
self.addEventListener('paymentrequest', async e => {
…
  // Retain a promise for future resolution
  // Polyfill for PromiseResolver is provided below.
  resolver = new PromiseResolver();

  // Pass a promise that resolves when payment is done.
  e.respondWith(resolver.promise);
  // Open the checkout page.
  try {
    // Open the window and preserve the client
    client = await e.openWindow(checkoutURL);
    if (!client) {
      // Reject if the window fails to open
      throw 'Failed to open window';
    }
  } catch (err) {
    // Reject the promise on failure
    resolver.reject(err);
  };
});
…

يمكنك استخدام رمز polyfill مناسب من PromiseResolver للوفاء بالوعد في توقيت عشوائي.

class PromiseResolver {
  constructor() {
    this.promise_ = new Promise((resolve, reject) => {
      this.resolve_ = resolve;
      this.reject_ = reject;
    })
  }
  get promise() { return this.promise_ }
  get resolve() { return this.resolve_ }
  get reject() { return this.reject_ }
}

تبادل المعلومات مع الواجهة الأمامية

يمكن لمشغّل الخدمات في تطبيق الدفع تبادل الرسائل مع الواجهة الأمامية لتطبيق الدفع من خلال ServiceWorkerController.postMessage(). لاستلام رسائل من الواجهة الأمامية، يُرجى الاستماع إلى أحداث "message".

[معالج الدفع] service-worker.js:

// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
  if (client) client.postMessage({ type, ...contents });
}

تلقّي إشارة جاهزة من الواجهة الأمامية

بعد فتح نافذة معالج الدفع، يجب على عامل الخدمة الانتظار للحصول على إشارة جاهزة من الواجهة الأمامية لتطبيق الدفع. يمكن لعامل الخدمة تمرير معلومات مهمة إلى الواجهة الأمامية عندما تكون جاهزة.

الواجهة الأمامية لـ [معالج الدفع]:

navigator.serviceWorker.controller.postMessage({
  type: 'WINDOW_IS_READY'
});

[معالج الدفع] service-worker.js:

…
// Received a message from the frontend
self.addEventListener('message', async e => {
  let details;
  try {
    switch (e.data.type) {
      // `WINDOW_IS_READY` is a frontend's ready state signal
      case 'WINDOW_IS_READY':
        const { total } = payment_request_event;
…

تمرير تفاصيل المعاملة إلى الواجهة الأمامية

يمكنك الآن إعادة إرسال تفاصيل الدفع. في هذه الحالة، ترسل فقط إجمالي طلب الدفع، ولكن يمكنك تمرير المزيد من التفاصيل إذا كنت ترغب في ذلك.

[معالج الدفع] service-worker.js:

…
        // Pass the payment details to the frontend
        postMessage('PAYMENT_IS_READY', { total });
        break;
…

الواجهة الأمامية لـ [معالج الدفع]:

let total;

navigator.serviceWorker.addEventListener('message', async e => {
  switch (e.data.type) {
      case 'PAYMENT_IS_READY':
        ({ total } = e.data);
        // Update the UI
        renderHTML(total);
        break;
…

إرجاع بيانات اعتماد الدفع الخاصة بالعميل

عندما يسمح العميل بالدفع، يمكن للواجهة الأمامية إرسال رسالة بريدية إلى عامل الخدمة للمتابعة. يمكنك حلّ الوعد الذي تم إرساله إلى PaymentRequestEvent.respondWith() لإرسال النتيجة إلى التاجر. مرِّر كائن PaymentHandlerResponse.

اسم الموقع الوصف
methodName معرّف طريقة الدفع المُستخدَم لإجراء عملية الدفع
details تمثّل هذه السمة البيانات الخاصة بطريقة الدفع التي توفّر المعلومات اللازمة للتاجر لمعالجة الدفعة.

الواجهة الأمامية لـ [معالج الدفع]:

  const paymentMethod = …

  postMessage('PAYMENT_AUTHORIZED', {
    paymentMethod,              // Payment method identifier
  });

[معالج الدفع] service-worker.js:

…
// Received a message from the frontend
self.addEventListener('message', async e => {
  let details;
  try {
    switch (e.data.type) {
      …
      case 'PAYMENT_AUTHORIZED':
        // Resolve the payment request event promise
        // with a payment response object
        const response = {
          methodName: e.data.paymentMethod,
          details: { id: 'put payment credential here' },
        }
        resolver.resolve(response);
        // Don't forget to initialize.
        payment_request_event = null;
        break;
      …

إلغاء معاملة الدفع

للسماح للعميل بإلغاء المعاملة، يمكن للواجهة الأمامية إرسال رسالة ما بعد إلى عامل الخدمة لإجراء ذلك. يتمكّن عامل الخدمة بعد ذلك من حل الوعد الذي تم تمريره إلى PaymentRequestEvent.respondWith() من خلال null لإعلام التاجر بأنّه تم إلغاء المعاملة.

الواجهة الأمامية لـ [معالج الدفع]:

  postMessage('CANCEL_PAYMENT');

[معالج الدفع] service-worker.js:

…
// Received a message from the frontend
self.addEventListener('message', async e => {
  let details;
  try {
    switch (e.data.type) {
      …
      case 'CANCEL_PAYMENT':
        // Resolve the payment request event promise
        // with null
        resolver.resolve(null);
        // Don't forget to initialize.
        payment_request_event = null;
        break;
      …

نموذج التعليمات البرمجية

جميع نماذج الرموز التي رأيتها في هذا المستند عبارة عن مقتطفات من نموذج تطبيق العمل التالي:

https://paymenthandler-demo.glitch.me

[معالج الدفع] مشغّل الخدمات

[معالج الدفع] الواجهة الأمامية

لتجربتها:

  1. انتقِل إلى https://paymentrequest-demo.glitch.me/.
  2. انتقل إلى أسفل الصفحة.
  3. اضغط على زر إضافة طريقة دفع.
  4. أدخِل https://paymenthandler-demo.glitch.me في الحقل معرّف طريقة الدفع.
  5. اضغط على زر الدفع بجانب الحقل.

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

في هذه المقالة، تعلمنا كيفية تنظيم معاملة دفع من عامل خدمة. والخطوة التالية هي معرفة كيفية إضافة المزيد من الميزات المتقدمة إلى مشغّل الخدمات.