תזמור עסקאות תשלום עם קובץ שירות (service worker)

איך להתאים את אפליקציית התשלומים מבוססת האינטרנט לתשלומים באינטרנט ולספק ללקוחות חוויית משתמש טובה יותר.

אחרי שאפליקציית התשלומים תירשם, תוכלו לקבל בקשות תשלום מעסקים. במאמר הזה נסביר איך לתזמור עסקת תשלום מ-service worker במהלך זמן הריצה (כלומר, כשחלון מוצג והמשתמש מבצע איתו אינטראקציה).

תזמור עסקאות תשלום באמצעות שירות עובד (service worker)
תזמור עסקאות תשלום באמצעות שירות עובד (service worker)

'שינויים בפרמטרים של תשלום בסביבת זמן ריצה' מתייחסים לקבוצה של אירועים שמאפשרים למוכרים ולמפעילי התשלומים להחליף הודעות בזמן שהמשתמשים מבצעים אינטראקציה עם מפעיל התשלומים. מידע נוסף זמין במאמר טיפול בפרטי תשלום אופציונליים באמצעות שירות עובד.

קבלת אירוע של בקשת תשלום מהסוחר

כשלקוח בוחר לשלם באמצעות אפליקציית תשלומים מבוססת-אינטרנט והמוכר מפעיל PaymentRequest.show(), ה-Service Worker יקבל אירוע paymentrequest. מוסיפים ל-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 מחרוזת שמציינת את המקור של מבצע הקריאה. הערך הזה יכול להיות זהה לערך של 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;
      

ביטול עסקת התשלום

כדי לאפשר ללקוח לבטל את העסקה, ממשק הקצה יכול לשלוח הודעה ל-post ל-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] frontend

כדי לנסות:

  1. נכנסים לכתובת https://paymentrequest-demo.glitch.me/.
  2. עבור לתחתית הדף.
  3. לוחצים על הוספת לחצן תשלום.
  4. מזינים https://paymenthandler-demo.glitch.me בשדה מזהה אמצעי התשלום.
  5. לוחצים על הלחצן Pay (תשלום) ליד השדה.

השלבים הבאים

במאמר הזה למדנו איך לתזמר עסקת תשלום מעובדי שירות. בשלב הבא תלמדו איך להוסיף עוד כמה תכונות מתקדמות ל-Service Worker.