การจัดการธุรกรรมการชำระเงินกับ Service Worker

วิธีปรับแอปการชำระเงินบนเว็บให้ใช้กับการชำระเงินผ่านเว็บได้และมอบประสบการณ์การใช้งานที่ดีขึ้นให้แก่ลูกค้า

เมื่อลงทะเบียนแอปการชำระเงินแล้ว คุณก็พร้อมรับคำขอการชำระเงินจากผู้ขาย โพสต์นี้อธิบายวิธีจัดการธุรกรรมการชำระเงินจาก 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 ใช้ข้อมูลนี้เพื่อสร้าง UI เพื่อแจ้งให้ลูกค้าทราบจํานวนเงินทั้งหมดที่ต้องชําระ
instrumentKey คีย์ระบุตำแหน่งของ Tick ที่ผู้ใช้เลือก ซึ่งแสดงถึง 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 polyfill ที่สะดวกเพื่อแก้ไข Promise ณ เวลาใดก็ได้

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 ควรรอสัญญาณสถานะ "พร้อม" จากส่วนหน้าของแอปการชำระเงิน บริการนี้สามารถส่งข้อมูลสำคัญไปยังส่วนหน้าได้เมื่อพร้อม

[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 จะแก้ไข Promise ที่ส่งไปยัง 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. กดปุ่มชำระเงินข้างช่อง

ขั้นตอนถัดไป

ในบทความนี้ เราได้เรียนรู้วิธีจัดการธุรกรรมการชำระเงินจาก Service Worker ขั้นตอนถัดไปคือดูวิธีเพิ่มฟีเจอร์ขั้นสูงบางอย่างลงใน Service Worker