كيفية تكييف تطبيق الدفع المستند إلى الويب مع 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
[payment handler] frontend
لتجربة هذه الميزة:
- انتقِل إلى https://paymentrequest-demo.glitch.me/.
- انتقل إلى أسفل الصفحة.
- اضغط على إضافة زر دفع.
- أدخِل
https://paymenthandler-demo.glitch.me
في حقل معرّف طريقة الدفع. - اضغط على الزر الدفع بجانب الحقل.
الخطوات التالية
في هذه المقالة، تعرّفنا على كيفية تنسيق معاملة دفع من أحد العاملِين في الخدمة. الخطوة التالية هي التعرّف على كيفية إضافة بعض الميزات المتقدّمة إلى الخدمة العاملة.