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

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

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

ניהול עסקאות תשלום באמצעות Service Worker
תזמור עסקאות תשלום באמצעות Service Worker

המונח 'שינויים בפרמטרים של התשלום בזמן הריצה' מתייחס לסדרה של אירועים שמאפשרים למוֹכר ולרכיב לטיפול בתשלומים להחליף הודעות בזמן שהמשתמש מקיים אינטראקציה עם הרכיב לטיפול בתשלומים. מידע נוסף על טיפול בפרטי תשלום אופציונליים באמצעות 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 מחרוזת שמציינת את המקור של הפונקציה שהופעלה. יכול להיות שהערך יהיה זהה לערך של topOrigin אם המוכר מפעיל את Payment Request API ישירות, אבל יכול להיות שהערך יהיה שונה אם ה-API מופעל מתוך iframe על ידי צד שלישי, כמו שער תשלומים.
paymentRequestId המאפיין id של האובייקט PaymentDetailsInit שסופק ל-Payment Request API. אם המוכר לא מציין מזהה, הדפדפן יספק מזהה שנוצר אוטומטית.
methodData הנתונים הספציפיים לאמצעי התשלום שסופקו על ידי המוכר כחלק מPaymentMethodData. השתמשו בפרטים האלה כדי לקבוע את פרטי עסקת התשלום.
total הסכום הכולל שהמוֹכר סיפק כחלק מPaymentDetailsInit. המאפיין הזה מאפשר ליצור ממשק משתמש שבו הלקוח יכול לראות את הסכום הכולל לתשלום.
instrumentKey המפתח לציון מקום שנבחר על ידי המשתמש. הסכום הזה משקף את instrumentKey שציינתם מראש. מחרוזת ריקה מציינת שהמשתמש לא ציין כלי נגינה.

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

כשמתקבל אירוע paymentrequest, אפליקציית התשלום יכולה לפתוח חלון של אמצעי תשלום על ידי קריאה ל-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);
  };
});

אפשר להשתמש ב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 });
}

קבלת אות מוכנות מהחלק הקדמי של האתר

אחרי שחלון אמצעי התשלום נפתח, קובץ השירות (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;

החזרת פרטי התשלום של הלקוח

כשהלקוח מאשר את התשלום, קצה הלקוח יכול לשלוח הודעת POST ל-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;
      

קוד לדוגמה

כל דוגמאות הקוד שמופיעות במסמך הזה הן קטעים מתוך: Payment Handler Demo

השלבים הבאים

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