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 cũng như cách các giao dịch thanh toán hoạt động với 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 dụng lần đầu tiên được tích hợp vào trình duyệt. Với 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 trong khi trải nghiệm khách hàng được sắp xếp hợp lý và an toàn hơn.

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

Bài viết này hướng dẫn bạn về 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 việc 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 cho thấy nút thanh toán.
  3. Khách hàng nhấn vào nút thanh toán.

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

  4. Trình duyệt khởi chạy ứng dụng thanh toán.

    Sơ đồ trang web cửa hàng phô mai với ứng dụng BobPay được khởi chạy theo một phương thức. Cửa sổ phụ hiển thị 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ư lựa chọn giao hàng hoặc địa chỉ của họ), thì người bán sẽ cập nhật thông tin giao dịch phản ánh sự thay đổi đó.

    Sơ đồ cho thấy khách hàng đang chọn một cách tính phí vận chuyển khác trong cửa sổ phụ của ứng dụng BobPay. Sơ đồ thứ hai cho thấy người bán đang 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, 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 thực hiện 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 một đố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 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.
  • Những lựa chọn mà người bán có thể yêu cầu thông tin vận chuyển như địa chỉ giao hàng và cách tính phí vận chuyển.
  • 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 thông tin vận chuyển không bắt buộc (shipping, delivery hoặc pickup) trong PaymentRequest. Ứng dụng thanh toán có thể dùng thông tin đó làm gợi ý để hiển thị đúng nhãn 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. Quy trình tích hợp điển hình là hoạt động giao tiếp giữ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 chặn khách hàng có ý đồ xấu thao túng giá và lừa đảo 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 vào 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 sẽ 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 quá 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 đưa ra 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ị nút thanh toán cho những phương thức 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 phương thức thanh toán được chỉ định trong đối tượng PaymentRequest sẽ không phù hợp với khách hàng, thì người bán có thể cung cấp giải pháp dự phòng hoặc hoàn toàn không cho thấy 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 không.

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 thiết bị của khách hàng có một ứng dụng thanh toán. "Có sẵn" có nghĩa là ứng dụng thanh toán có hỗ trợ phương thức thanh toán đã được tìm thấy, ứ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 nền tảng web đã sẵn sàng được đă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 sẽ ngay lập tức kích hoạt quá trình 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 tự độ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 biết tổng số tiền.

Trì hoãn việc chạy giao diện người dùng thanh toán

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

Để 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 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ẽ ngay lập tức khởi chạy giao diện người dùng thanh toán.

Bước 4: Trình duyệt khởi 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 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 nào sẽ chạy.)

Phần lớn cách xây dựng ứng dụng thanh toán là tuỳ thuộc vào nhà phát triển, nhưng các sự kiện được tạo 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 chạy, ứng dụng thanh toán sẽ nhận được thông tin giao dịch đã chuyển đến đối tượng PaymentRequest ở Bước 1, bao gồm các thông tin sau:

  • Dữ liệu về phương thức thanh toán
  • Tổng số tiền thuê xe
  • 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 chi tiết 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, chẳng hạn như phương thức thanh toán và tuỳ chọn vận chuyển trong ứng dụng thanh toán. Trong khi 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.

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

  • 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 tuỳ chọn 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. Để đáp ứng 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á đã áp dụng chiết khấu rồi trả lại ứ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 thuận tiện cho khách hàng vì họ không phải nhập thủ công bất kỳ thông tin nào vào biểu mẫu và có thể lưu trữ địa chỉ giao hàng của mình trong ứng dụng thanh toán ư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 đã 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 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ỉ mới cập nhật, người bán có thể gửi thông báo lỗi bằng cách thêm một tham số lỗi vào thông tin giao dịch được trả về ứng dụng thanh toán.

Sự kiện thay đổi tuỳ chọn vận chuyển

Người bán có thể cung cấp nhiều tuỳ 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 tuỳ chọn vận chuyển 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ụ:

  • Vận chuyển tiêu chuẩn – Miễn phí
  • Vận chuyển nhanh – 50.000 VND

Khi khách hàng cập nhật lựa chọn vận chuyển trong ứng dụng thanh toán, 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á rồi trả lại cho ứ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 cách tính phí 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 các nhóm tuỳ chọn vận chuyển khác nhau cho khách hàng nội địa 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ể xác thực người bán trước khi chuyển sang quy trình thanh toán. Thiết kế của 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 có vai trò 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 uỷ quyền thanh toán thành công, phương thức show() sẽ trả về một lời hứa giải quyết là PaymentResponse. Đối tượng PaymentResponse bao gồm những thông tin sau:

  • 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 có thể vẫn hiển thị chỉ báo 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 lỗi thanh toán, 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.

Đang 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 để xử lý hoặc xác thực thông tin thanh toán. Cách hoạt động của quy trình quan trọng này sẽ 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 xem 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.
  • Hãy để 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