كيفية تكييف تطبيق الدفع المستند إلى الويب مع Web Payments وتوفير تجربة مستخدم أفضل للعملاء
بعد تسجيل تطبيق الدفع، ستصبح مستعدًا لقبول طلبات الدفع من التجّار. تشرح هذه المشاركة كيفية تنسيق معاملة دفع من مشغّل الخدمات أثناء وقت التشغيل (أي عندما تظهر نافذة ويتفاعل المستخدم معها).
تشير "تغييرات مَعلمات الدفع أثناء التشغيل" إلى مجموعة من الأحداث التي تسمح للتاجر ومعالج الدفع بتبادل الرسائل أثناء تفاعل المستخدم مع معالج الدفع. اطّلِع على مزيد من المعلومات في مقالة معالجة معلومات الدفع الاختيارية باستخدام Worker Service.
تلقّي حدث طلب دفع من التاجر
عندما يختار أحد العملاء الدفع باستخدام تطبيق الدفع المستند إلى الويب ويُطلِق التاجر
PaymentRequest.show()
،
سيتلقّى عامل الخدمة حدث paymentrequest
. أضف أداة معالجة الحدث إلى عامل الخدمة لتسجيل الحدث والاستعداد للإجراء التالي.
[payment handler] 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
، يمكن لتطبيق الدفع فتح نافذة معالج payment
من خلال استدعاء PaymentRequestEvent.openWindow()
. ستعرض نافذة معالج الدفع للعملاء واجهة تطبيق الدفع الذي تستخدمه، والتي يمكنهم من خلالها مصادقة حساباتهم واختيار عنوان الشحن وخياراته وتفويض عملية الدفع. سنتناول كيفية كتابة رمز الواجهة الأمامية في مقالة معالجة الدفعات في
واجهة الدفع (قريبًا).
أرسِل وعدًا محفوظًا إلى PaymentRequestEvent.respondWith()
حتى تتمكّن من
حلّه من خلال نتيجة دفع في المستقبل.
[payment handler] 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
.
[payment handler] service-worker.js:
// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
if (client) client.postMessage({ type, ...contents });
}
تلقّي إشارة الاستعداد من الواجهة الأمامية
بعد فتح نافذة معالج الدفع، يجب أن ينتظر مشغّل الخدمة إشارة إعلام بالاستعداد من واجهة تطبيق الدفع. يمكن لعامل الخدمة تمرير معلومات مهمة إلى الواجهة الأمامية عندما تكون جاهزة.
[payment handler] frontend:
navigator.serviceWorker.controller.postMessage({
type: 'WINDOW_IS_READY'
});
[payment handler] 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;
…
تمرير تفاصيل المعاملة إلى الواجهة الأمامية
يُرجى الآن إعادة إرسال تفاصيل الدفع. في هذه الحالة، لن ترسل سوى إجمالي طلب الدفع، ولكن يمكنك إرسال المزيد من التفاصيل إذا أردت.
[payment handler] service-worker.js:
…
// Pass the payment details to the frontend
postMessage('PAYMENT_IS_READY', { total });
break;
…
[payment handler] frontend:
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 handler] frontend:
const paymentMethod = …
postMessage('PAYMENT_AUTHORIZED', {
paymentMethod, // Payment method identifier
});
[payment handler] 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
للإشارة إلى التاجر بأنّه تم إلغاء المعاملة.
[payment handler] frontend:
postMessage('CANCEL_PAYMENT');
[payment handler] 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
[payment handler] service worker
[معالج الدفع] الواجهة الأمامية
لتجربتها:
- انتقِل إلى https://paymentrequest-demo.glitch.me/.
- انتقل إلى أسفل الصفحة.
- اضغط على إضافة زر دفع.
- أدخِل
https://paymenthandler-demo.glitch.me
في حقل معرّف طريقة الدفع. - اضغط على الزر الدفع بجانب الحقل.
الخطوات التالية
في هذه المقالة، تعرّفنا على كيفية تنسيق معاملة دفع من أحد العاملِين في الخدمة. الخطوة التالية هي التعرّف على كيفية إضافة بعض الميزات المتقدّمة إلى الخدمة العاملة.