Vòng đời của một giao dịch thanh toán

Tìm hiểu cách người bán tích hợp ứng dụng thanh toán và cách hoạt động của giao dịch thanh toán bằng API Yêu cầu thanh toán.

API Thanh toán trên web là các tính năng thanh toán chuyên biệt được tích hợp vào trình duyệt lần đầu tiên. Với tính năng Thanh toán trên web, việc tích hợp người bán với các ứng dụng thanh toán trở nên đơn giản hơn, đồng thời trải nghiệm của khách hàng được tinh giản và an toàn hơn.

Để tìm hiểu thêm về lợi ích của việc sử dụng tính năng Thanh toán trên web, hãy xem bài viết Tăng cường tính năng thanh toán cho ứng dụng bằng tính năng Thanh toán trên web.

Bài viết này hướng dẫn bạn thực hiện một giao dịch thanh toán trên trang web của người bán và giúp bạn hiểu cách hoạt động của tính năng tích hợp ứng dụng thanh toán.

Quy trình này bao gồm 6 bước:

  1. Người bán bắt đầu một giao dịch thanh toán.
  2. Người bán sẽ hiện một nút thanh toán.
  3. Khách hàng nhấn vào nút thanh toán.

    Sơ đồ trang web của một cửa hàng bán pho mát có nút BobPay (ứng dụng thanh toán).

  4. Trình duyệt sẽ chạy ứng dụng thanh toán.

    Sơ đồ trang web của cửa hàng bán phô mai với ứng dụng BobPay được chạy trong một cửa sổ bật lên. Cửa sổ phụ cho biết các cách tính phí vận chuyển và tổng chi phí.

  5. Nếu khách hàng thay đổi bất kỳ thông tin chi tiết nào (chẳng hạn như phương thức giao hàng hoặc địa chỉ của họ), người bán sẽ cập nhật thông tin chi tiết về giao dịch để phản ánh sự thay đổi đó.

    Sơ đồ cho thấy khách hàng chọn một phương thức giao hàng khác trong cửa sổ bật lên của ứng dụng BobPay. Sơ đồ thứ hai cho thấy người bán cập nhật tổng chi phí hiển thị trong BobPay.

  6. Sau khi khách hàng xác nhận giao dịch mua hàng, người bán sẽ xác thực khoản thanh toán và hoàn tất giao dịch.

    Sơ đồ cho thấy khách hàng nhấn vào

Bước 1: Người bán bắt đầu một giao dịch thanh toán

Khi khách hàng quyết định mua hàng, người bán sẽ bắt đầu giao dịch thanh toán bằng cách tạo đối tượng PaymentRequest. Đối tượng này bao gồm thông tin quan trọng về giao dịch:

  • Phương thức thanh toán được chấp nhận và dữ liệu của các phương thức đó để xử lý giao dịch.
  • Thông tin chi tiết, chẳng hạn như tổng giá (bắt buộc) và thông tin về các mặt hàng.
  • Các lựa chọn mà người bán có thể yêu cầu thông tin vận chuyển, chẳng hạn như địa chỉ giao hàng và phương thức giao hàng.
  • Người bán cũng có thể yêu cầu địa chỉ thanh toán, tên, email và số điện thoại của người thanh toán.
  • Người bán cũng có thể thêm loại phí vận chuyển (shipping, delivery hoặc pickup) không bắt buộc vào PaymentRequest. Ứng dụng thanh toán có thể sử dụng thông tin đó làm gợi ý để hiển thị nhãn chính xác trong giao diện người dùng.
const request = new PaymentRequest([{
  supportedMethods: 'https://bobpay.xyz/pay',
  data: {
    transactionId: '****'
  }
}], {
  displayItems: [{
    label: 'Anvil L/S Crew Neck - Grey M x1',
    amount: { currency: 'USD', value: '22.15' }
  }],
  total: {
    label: 'Total due',
    amount: { currency: 'USD', value : '22.15' }
  }
}, {
  requestShipping: true,
  requestBillingAddress: true,
  requestPayerEmail: true,
  requestPayerPhone: true,
  requestPayerName: true,
  shippingType: 'delivery'
});
Bao gồm mã giao dịch

Một số trình xử lý thanh toán có thể yêu cầu người bán cung cấp mã giao dịch mà họ đã phát hành trước đó trong thông tin giao dịch. Một quy trình tích hợp thông thường bao gồm hoạt động giao tiếp giữa máy chủ của người bán và máy chủ của trình xử lý thanh toán để đặt trước tổng giá. Điều này giúp ngăn khách hàng độc hại thao túng giá và lừa gạt người bán bằng quy trình xác thực ở cuối giao dịch.

Người bán có thể truyền mã giao dịch trong thuộc tính data của đối tượng PaymentMethodData.

Khi cung cấp thông tin giao dịch, trình duyệt sẽ trải qua quy trình khám phá các ứng dụng thanh toán được chỉ định trong PaymentRequest dựa trên giá trị nhận dạng phương thức thanh toán. Bằng cách này, trình duyệt có thể xác định ứng dụng thanh toán cần khởi chạy ngay khi người bán sẵn sàng tiếp tục giao dịch.

Để tìm hiểu chi tiết cách hoạt động của quy trình khám phá, hãy xem bài viết Thiết lập phương thức thanh toán.

Bước 2: Người bán hiển thị nút thanh toán

Người bán có thể hỗ trợ nhiều phương thức thanh toán, nhưng chỉ nên hiển thị các nút thanh toán mà khách hàng thực sự có thể sử dụng. Việc hiển thị nút thanh toán không sử dụng được là trải nghiệm người dùng kém. Nếu có thể dự đoán rằng một phương thức thanh toán được chỉ định trong đối tượng PaymentRequest sẽ không hoạt động với khách hàng, người bán có thể cung cấp một giải pháp dự phòng hoặc không hiển thị nút đó.

Khi sử dụng thực thể PaymentRequest, người bán có thể truy vấn xem khách hàng đã có ứng dụng thanh toán hay chưa.

Khách hàng có ứng dụng thanh toán không?

Phương thức canMakePayment() của PaymentRequest sẽ trả về true nếu có ứng dụng thanh toán trên thiết bị của khách hàng. "Có sẵn" có nghĩa là một ứng dụng thanh toán hỗ trợ phương thức thanh toán đã được phát hiện và ứng dụng thanh toán dành riêng cho nền tảng đã được cài đặt hoặc ứng dụng thanh toán dựa trên web đã sẵn sàng để đăng ký.

const canMakePayment = await request.canMakePayment();
if (!canMakePayment) {
  // Fallback to other means of payment or hide the button.
}

Bước 3: Khách hàng nhấn vào nút thanh toán

Khi khách hàng nhấn nút thanh toán, người bán sẽ gọi phương thức show() của thực thể PaymentRequest. Phương thức này ngay lập tức kích hoạt việc khởi chạy giao diện người dùng thanh toán.

Trong trường hợp tổng giá cuối cùng được đặt một cách linh động (ví dụ: được truy xuất từ máy chủ), người bán có thể trì hoãn việc khởi chạy giao diện người dùng thanh toán cho đến khi xác định được tổng số tiền.

Hoãn khởi chạy giao diện người dùng thanh toán

Hãy xem bản minh hoạ cách trì hoãn giao diện người dùng thanh toán cho đến khi xác định được tổng giá cuối cùng.

Để hoãn giao diện người dùng thanh toán, người bán chuyển lời hứa đến phương thức show(). Trình duyệt sẽ hiển thị chỉ báo đang tải cho đến khi lời hứa được giải quyết và giao dịch sẵn sàng bắt đầu.

const getTotalAmount = async () => {
  // Fetch the total amount from the server, etc.
};

try {
  const result = await request.show(getTotalAmount());
  // Process the result…
} catch(e) {
  handleError(e);
}

Nếu không có lời hứa nào được chỉ định làm đối số cho show(), trình duyệt sẽ khởi chạy giao diện người dùng thanh toán ngay lập tức.

Bước 4: Trình duyệt sẽ chạy ứng dụng thanh toán

Trình duyệt có thể chạy một ứng dụng thanh toán dành riêng cho nền tảng hoặc ứng dụng thanh toán dựa trên web. (Bạn có thể tìm hiểu thêm về cách Chrome xác định ứng dụng thanh toán cần chạy.)

Cách xây dựng ứng dụng thanh toán phần lớn là do nhà phát triển quyết định, nhưng các sự kiện phát ra từ và đến người bán, cũng như cấu trúc của dữ liệu được truyền cùng với các sự kiện đó, đều được chuẩn hoá.

Khi khởi chạy, ứng dụng thanh toán sẽ nhận được thông tin giao dịch được chuyển đến đối tượng PaymentRequest ở Bước 1, bao gồm:

  • Dữ liệu về phương thức thanh toán
  • Tổng giá
  • Các cách thanh toán

Ứng dụng thanh toán sử dụng thông tin giao dịch để gắn nhãn giao diện người dùng.

Bước 5: Cách người bán có thể cập nhật thông tin chi tiết về giao dịch tuỳ thuộc vào hành động của khách hàng

Khách hàng có thể thay đổi thông tin giao dịch như phương thức thanh toán và phương thức giao hàng trong ứng dụng thanh toán. Trong khi khách hàng thực hiện thay đổi, người bán sẽ nhận được các sự kiện thay đổi và cập nhật thông tin giao dịch.

Người bán có thể nhận được 4 loại sự kiện:

  • Sự kiện thay đổi phương thức thanh toán
  • Sự kiện thay đổi địa chỉ giao hàng
  • Sự kiện thay đổi cách tính phí vận chuyển
  • Sự kiện xác thực người bán

Sự kiện thay đổi phương thức thanh toán

Ứng dụng thanh toán có thể hỗ trợ nhiều phương thức thanh toán và người bán có thể đưa ra chiết khấu đặc biệt tuỳ thuộc vào lựa chọn của khách hàng. Để xử lý trường hợp sử dụng này, sự kiện thay đổi phương thức thanh toán có thể thông báo cho người bán về phương thức thanh toán mới để họ có thể cập nhật tổng giá kèm theo khoản chiết khấu và trả về ứng dụng thanh toán.

request.addEventListener('paymentmethodchange', e => {
  e.updateWith({
    // Add discount etc.
  });
});

Sự kiện thay đổi địa chỉ giao hàng

Ứng dụng thanh toán có thể cung cấp địa chỉ giao hàng của khách hàng (không bắt buộc). Điều này rất thuận tiện cho khách hàng vì họ không phải nhập thông tin chi tiết vào biểu mẫu theo cách thủ công và có thể lưu trữ địa chỉ giao hàng trong ứng dụng thanh toán mà họ ưu tiên, thay vì trên nhiều trang web của người bán.

Nếu khách hàng cập nhật địa chỉ giao hàng trong ứng dụng thanh toán sau khi giao dịch được bắt đầu, thì sự kiện 'shippingaddresschange' sẽ được gửi đến người bán. Sự kiện này giúp người bán xác định phí vận chuyển dựa trên địa chỉ mới, cập nhật tổng giá rồi trả lại phí vận chuyển đó cho ứng dụng thanh toán.

request.addEventListener('shippingaddresschange', e => {
  e.updateWith({
    // Update the details
  });
});

Nếu không thể giao hàng đến địa chỉ đã cập nhật, người bán có thể gửi thông báo lỗi bằng cách thêm thông số lỗi vào chi tiết giao dịch được trả về ứng dụng thanh toán.

Sự kiện thay đổi phương thức vận chuyển

Người bán có thể cung cấp nhiều lựa chọn vận chuyển cho khách hàng và có thể uỷ quyền lựa chọn đó cho ứng dụng thanh toán. Các lựa chọn vận chuyển sẽ xuất hiện dưới dạng danh sách giá và tên dịch vụ mà khách hàng có thể chọn. Ví dụ:

  • Giao hàng tiêu chuẩn – Miễn phí
  • Giao hàng nhanh – 5 USD

Khi khách hàng cập nhật phương thức giao hàng trong ứng dụng thanh toán, một sự kiện 'shippingoptionchange' sẽ được gửi đến người bán. Sau đó, người bán có thể xác định phí vận chuyển, cập nhật tổng giá và trả về ứng dụng thanh toán.

request.addEventListener('shippingoptionchange', e => {
  e.updateWith({
    // Update the details
  });
});

Người bán cũng có thể linh động sửa đổi các lựa chọn vận chuyển dựa trên địa chỉ giao hàng của khách hàng. Điều này rất hữu ích khi người bán muốn cung cấp nhiều lựa chọn vận chuyển cho khách hàng trong nước và quốc tế.

Sự kiện xác thực người bán

Để tăng cường tính bảo mật, ứng dụng thanh toán có thể thực hiện quy trình xác thực người bán trước khi chuyển sang quy trình thanh toán. Việc thiết kế cơ chế xác thực là tuỳ thuộc vào ứng dụng thanh toán, nhưng sự kiện xác thực người bán sẽ thông báo cho người bán về URL mà họ có thể sử dụng để tự xác thực.

request.addEventListener('merchantvalidation', e => {
  e.updateWith({
    // Use `e.validateURL` to validate
  });
});

Bước 6: Người bán xác thực khoản thanh toán và hoàn tất giao dịch

Khi khách hàng cho phép thanh toán thành công, phương thức show() sẽ trả về lời hứa phân giải thành PaymentResponse. Đối tượng PaymentResponse bao gồm các thông tin sau:

  • Thông tin chi tiết về kết quả thanh toán
  • Ðịa chỉ giao hàng
  • Cách tính phí vận chuyển
  • Thông tin liên hệ

Tại thời điểm này, giao diện người dùng của trình duyệt vẫn có thể hiển thị chỉ báo đang tải, nghĩa là giao dịch chưa hoàn tất.

Nếu ứng dụng thanh toán bị chấm dứt do lỗi hoặc không thanh toán được, thì lời hứa được trả về từ show() sẽ từ chối và trình duyệt sẽ chấm dứt giao dịch thanh toán.

Xử lý và xác thực khoản thanh toán

details trong PaymentResponse là đối tượng thông tin xác thực thanh toán được trả về từ ứng dụng thanh toán. Người bán có thể sử dụng thông tin xác thực này để xử lý hoặc xác thực giao dịch thanh toán. Cách hoạt động của quy trình quan trọng này tuỳ thuộc vào trình xử lý thanh toán.

Hoàn tất hoặc thử lại giao dịch

Sau khi xác định giao dịch có thành công hay không, người bán có thể:

  • Hãy gọi phương thức .complete() để hoàn tất giao dịch và đóng chỉ báo tải.
  • Cho phép khách hàng thử lại bằng cách gọi phương thức retry().
async function doPaymentRequest() {
  try {
    const request = new PaymentRequest(methodData, details, options);
    const response = await request.show();
    await validateResponse(response);
  } catch (err) {
    // AbortError, SecurityError
    console.error(err);
  }
}

async function validateResponse(response) {
  try {
    const errors = await checkAllValuesAreGood(response);
    if (errors.length) {
      await response.retry(errors);
      return validateResponse(response);
    }
    await response.complete("success");
  } catch (err) {
    // Something went wrong…
    await response.complete("fail");
  }
}
// Must be called as a result of a click
// or some explicit user action.
doPaymentRequest();

Các bước tiếp theo