איך להתאים את אפליקציית התשלומים מבוססת-האינטרנט ל'תשלומים באינטרנט' ולספק חוויית משתמש טובה יותר ללקוחות.
אחרי שאפליקציית התשלומים תירשם, תוכלו לקבל בקשות תשלום ממוכרים. בפוסט הזה מוסבר איך לתאם עסקת תשלום מ-Service Worker במהלך זמן ריצה (כלומר כשמוצג חלון והמשתמש מקיים איתו אינטראקציה).
![תזמור עסקאות תשלום עם קובץ שירות (service worker)](https://web.dev/static/articles/orchestrating-payment-transactions/image/orchestrating-payment-tra-dd17687ea595a.png?authuser=5&hl=he)
'שינויים בפרמטר של תשלום בזמן הריצה' מתייחסים לקבוצת אירועים שמאפשרים למוכר ולגורם המטפל בתשלום להחליף הודעות בזמן שהמשתמש מנהל אינטראקציה עם ה-handler של התשלום. מידע נוסף על טיפול בפרטי תשלום אופציונליים עם Service Worker
קבלת אירוע של בקשת תשלום מהמוכר
כשלקוח בוחר לשלם באמצעות אפליקציית תשלומים מבוססת-אינטרנט והמוכר מפעיל PaymentRequest.show()
, ה-Service Worker מקבל אירוע paymentrequest
. כדי לתעד את האירוע ולהתכונן לפעולה הבאה, מוסיפים פונקציות event listener ל-Service Worker.
[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 |
מחרוזת שמציינת את מקור ה-invoker. הערך הזה יכול להיות זהה לערך topOrigin כשהמוכר מפעיל את Payment Request API באופן ישיר. הוא יכול להיות שונה אם ה-API מופעל מתוך iframe על ידי צד שלישי, כמו שער תשלומים.
|
paymentRequestId |
המאפיין id של PaymentDetailsInit שסופק ל-Payment Request API. אם המוכר לא יענה, הדפדפן יספק מזהה שנוצר באופן אוטומטי.
|
methodData |
הנתונים הספציפיים לאמצעי התשלום שהמוכר סיפק כחלק מ-PaymentMethodData .
אפשר להשתמש בה כדי לקבוע את פרטי עסקת התשלום.
|
total |
הסכום הכולל שהמוכר סיפק כחלק מ-PaymentDetailsInit .
השתמשו בו כדי ליצור ממשק משתמש כדי ליידע את הלקוח מה הסכום הכולל לשלם.
|
instrumentKey |
מפתח האמצעי שנבחר על ידי המשתמש. הערך הזה משקף את instrumentKey שסיפקת מראש. מחרוזת ריקה מציינת שהמשתמש לא ציין אמצעי תשלום.
|
פתיחת חלון ה-handler של התשלומים כדי להציג את הקצה הקדמי של אפליקציית התשלומים מבוססת-האינטרנט
כשמתקבל אירוע paymentrequest
, אפליקציית התשלומים יכולה לפתוח חלון של handler תשלומים על ידי קריאה ל-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_ }
}
החלפת מידע עם הקצה הקדמי
ה-Service Worker של אפליקציית התשלום יכול להחליף הודעות עם הקצה הקדמי של אפליקציית התשלום באמצעות ServiceWorkerController.postMessage()
. כדי לקבל הודעות מהחזית, צריך להאזין לאירועי message
.
[payment handler] service-worker.js:
// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
if (client) client.postMessage({ type, ...contents });
}
קבלת האות המוכן מהחזית
אחרי שפותחים את חלון ה-handler של התשלום, ה-Service Worker צריך להמתין לאות מצב מוכן מהחזית של אפליקציית התשלומים. ה-Service Worker יכול להעביר מידע חשוב לממשק הקצה כשהוא מוכן.
[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;
…
החזרת פרטי הכניסה לתשלום של הלקוח
כשהלקוח מאשר את התשלום, החזית יכולה לשלוח ל-Service Worker הודעה בדואר כדי להמשיך. אפשר לטפל בהבטחה שהועברה אל 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;
…
לבטל את עסקת התשלום.
כדי לאפשר ללקוח לבטל את הטרנזקציה, החזית יכולה לשלוח ל-Service Worker הודעת פרסום כדי לעשות זאת. לאחר מכן, ה-Service Worker יכול לפתור את ההבטחה שהועברה ל-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]
כדי לנסות את הכלים:
- נכנסים לכתובת https://paymentrequest-demo.glitch.me/.
- עבור לתחתית הדף.
- לוחצים על הוספת לחצן תשלום.
- מזינים
https://paymenthandler-demo.glitch.me
בשדה מזהה אמצעי התשלום. - לוחצים על הלחצן Pay (תשלום) ליד השדה.
השלבים הבאים
במאמר הזה למדנו איך לתזמר עסקת תשלום מעובדי שירות. בשלב הבא תלמדו איך להוסיף עוד תכונות מתקדמות ל-Service Worker.