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

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

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

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

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

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

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

[payment معالج] service- employee.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() لتتمكّن من حلّها بنتيجة الدفع في المستقبل

[payment معالج] service- employee.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

[payment معالج] service- employee.js:

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

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

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

[payment معالج] الواجهة الأمامية:

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

[payment معالج] service- employee.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;
…

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

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

[payment معالج] service- employee.js:

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

[payment معالج] الواجهة الأمامية:

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 البيانات الخاصة بطريقة الدفع التي توفّر المعلومات اللازمة حتى يتمكّن التاجر من معالجة الدفعة

[payment معالج] الواجهة الأمامية:

  const paymentMethod = …

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

[payment معالج] service- employee.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 لإعلام التاجر بإلغاء المعاملة.

[payment معالج] الواجهة الأمامية:

  postMessage('CANCEL_PAYMENT');

[payment معالج] service- employee.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

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

[payment handling] الواجهة الأمامية

لتجربتها:

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

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

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