Sắp xếp các giao dịch thanh toán với nhân viên dịch vụ

Cách điều chỉnh ứng dụng thanh toán dựa trên web cho phù hợp với Web Payments và mang lại trải nghiệm người dùng tốt hơn cho khách hàng.

Sau khi đăng ký ứng dụng thanh toán, bạn đã sẵn sàng chấp nhận yêu cầu thanh toán của người bán. Bài đăng này giải thích cách điều phối một giao dịch thanh toán từ một worker dịch vụ trong thời gian chạy (tức là khi một cửa sổ hiển thị và người dùng đang tương tác với cửa sổ đó).

Điều phối giao dịch thanh toán bằng một worker dịch vụ
Điều phối các giao dịch thanh toán bằng một worker dịch vụ

"Các thay đổi về tham số thanh toán trong thời gian chạy" đề cập đến một nhóm sự kiện cho phép người bán và trình xử lý thanh toán trao đổi thông báo trong khi người dùng đang tương tác với trình xử lý thanh toán. Tìm hiểu thêm trong bài viết Xử lý thông tin thanh toán không bắt buộc bằng một worker dịch vụ.

Nhận sự kiện yêu cầu thanh toán từ người bán

Khi khách hàng chọn thanh toán bằng ứng dụng thanh toán dựa trên web của bạn và người bán gọi PaymentRequest.show(), service worker của bạn sẽ nhận được sự kiện paymentrequest. Thêm một trình nghe sự kiện vào trình chạy dịch vụ để ghi lại sự kiện và chuẩn bị cho hành động tiếp theo.

[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 được giữ lại chứa thông tin quan trọng về giao dịch này:

Tên tài sản Mô tả
topOrigin Một chuỗi cho biết nguồn gốc của trang web cấp cao nhất (thường là người bán được thanh toán). Sử dụng thuộc tính này để xác định nguồn gốc của người bán.
paymentRequestOrigin Một chuỗi cho biết nguồn gốc của phương thức gọi. Tham số này có thể giống với topOrigin khi người bán gọi trực tiếp Payment Request API, nhưng có thể khác nếu API được gọi từ bên trong một iframe của bên thứ ba, chẳng hạn như một cổng thanh toán.
paymentRequestId Thuộc tính id của PaymentDetailsInit được cung cấp cho Payment Request API. Nếu người bán bỏ qua, trình duyệt sẽ cung cấp một mã nhận dạng được tạo tự động.
methodData Dữ liệu dành riêng cho phương thức thanh toán do người bán cung cấp trong PaymentMethodData. Sử dụng thông tin này để xác định thông tin chi tiết về giao dịch thanh toán.
total Tổng số tiền mà người bán cung cấp trong PaymentDetailsInit. Sử dụng thông tin này để tạo giao diện người dùng nhằm cho khách hàng biết tổng số tiền phải thanh toán.
instrumentKey Khoá xác định xuất phát điểm do người dùng chọn. Đây là instrumentKey mà bạn đã cung cấp trước. Một chuỗi trống cho biết người dùng không chỉ định nhạc cụ nào.

Mở cửa sổ trình xử lý thanh toán để hiển thị giao diện người dùng của ứng dụng thanh toán dựa trên web

Khi nhận được sự kiện paymentrequest, ứng dụng thanh toán có thể mở một cửa sổ trình xử lý thanh toán bằng cách gọi PaymentRequestEvent.openWindow(). Cửa sổ trình xử lý thanh toán sẽ hiển thị cho khách hàng giao diện của ứng dụng thanh toán nơi họ có thể xác thực, chọn địa chỉ và lựa chọn giao hàng, đồng thời uỷ quyền thanh toán. Chúng ta sẽ tìm hiểu cách viết mã giao diện người dùng trong phần Xử lý các khoản thanh toán trên giao diện người dùng thanh toán (sắp ra mắt).

Quy trình thanh toán bằng ứng dụng thanh toán dựa trên web.

Truyền một lời hứa được giữ lại đến PaymentRequestEvent.respondWith() để bạn có thể giải quyết lời hứa đó bằng kết quả thanh toán trong tương lai.

[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);
  };
});

Bạn có thể sử dụng một polyfill PromiseResolver thuận tiện để giải quyết một lời hứa vào thời điểm tuỳ ý.

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_ }
}

Trao đổi thông tin với giao diện người dùng

Service worker của ứng dụng thanh toán có thể trao đổi thông báo với giao diện người dùng của ứng dụng thanh toán thông qua ServiceWorkerController.postMessage(). Để nhận thông báo từ giao diện người dùng, hãy theo dõi các sự kiện message.

[payment handler] service-worker.js:

// Define a convenient `postMessage()` method
const postMessage = (type, contents = {}) => {
  if (client) client.postMessage({ type, ...contents });
}

Nhận tín hiệu sẵn sàng từ giao diện người dùng

Sau khi cửa sổ trình xử lý thanh toán mở ra, trình chạy dịch vụ sẽ đợi tín hiệu trạng thái sẵn sàng từ giao diện người dùng của ứng dụng thanh toán. Service worker có thể truyền thông tin quan trọng đến giao diện người dùng khi đã sẵn sàng.

[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;

Truyền thông tin giao dịch đến giao diện người dùng

Bây giờ, hãy gửi lại thông tin thanh toán. Trong trường hợp này, bạn chỉ gửi tổng số tiền của yêu cầu thanh toán, nhưng bạn có thể truyền thêm thông tin chi tiết nếu muốn.

[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;

Trả về thông tin đăng nhập thanh toán của khách hàng

Khi khách hàng uỷ quyền thanh toán, giao diện người dùng có thể gửi một thông báo đăng đến trình chạy dịch vụ để tiếp tục. Bạn có thể giải quyết lời hứa được truyền đến PaymentRequestEvent.respondWith() để gửi kết quả về cho người bán. Truyền một đối tượng PaymentHandlerResponse.

Tên tài sản Mô tả
methodName Mã nhận dạng phương thức thanh toán được dùng để thanh toán.
details Dữ liệu cụ thể về phương thức thanh toán cung cấp thông tin cần thiết để người bán xử lý việc thanh toán.

[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;
      

Huỷ giao dịch thanh toán

Để cho phép khách hàng huỷ giao dịch, giao diện người dùng có thể gửi một thông báo đăng đến trình chạy dịch vụ để thực hiện việc này. Sau đó, trình chạy dịch vụ có thể giải quyết lời hứa được truyền đến PaymentRequestEvent.respondWith() bằng null để cho người bán biết rằng giao dịch đã bị huỷ.

[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;
      

Mã mẫu

Tất cả mã mẫu mà bạn thấy trong tài liệu này đều là đoạn trích từ: Bản minh hoạ Trình xử lý thanh toán

Các bước tiếp theo

Trong bài viết này, chúng ta đã tìm hiểu cách điều phối một giao dịch thanh toán từ một service worker. Bước tiếp theo là tìm hiểu cách thêm một số tính năng nâng cao khác vào service worker.