Mengatur transaksi pembayaran dengan pekerja layanan

Cara menyesuaikan aplikasi pembayaran berbasis web dengan Pembayaran Web dan memberikan pengalaman pengguna yang lebih baik kepada pelanggan.

Setelah aplikasi pembayaran terdaftar, Anda siap untuk menerima permintaan pembayaran dari penjual. Postingan ini menjelaskan cara mengatur transaksi pembayaran dari pekerja layanan selama runtime (yaitu saat jendela ditampilkan dan pengguna berinteraksi dengannya).

Mengorkestrasi transaksi pembayaran dengan pekerja layanan
Mengorkestrasi transaksi pembayaran dengan pekerja layanan

"Perubahan parameter pembayaran runtime" mengacu pada kumpulan peristiwa yang memungkinkan penjual dan pengendali pembayaran bertukar pesan saat pengguna berinteraksi dengan pengendali pembayaran. Pelajari lebih lanjut di Menangani informasi pembayaran opsional dengan pekerja layanan.

Menerima peristiwa permintaan pembayaran dari penjual

Saat pelanggan memilih untuk membayar dengan aplikasi pembayaran berbasis web Anda dan penjual memanggil PaymentRequest.show(), pekerja layanan akan menerima peristiwa paymentrequest. Tambahkan pemroses peristiwa ke pekerja layanan untuk menangkap peristiwa dan mempersiapkan tindakan berikutnya.

[pengendali pembayaran] 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 yang dipertahankan berisi informasi penting tentang transaksi ini:

Nama properti Deskripsi
topOrigin String yang menunjukkan asal halaman tingkat atas (biasanya penjual penerima pembayaran). Gunakan nomor ini untuk mengidentifikasi asal penjual.
paymentRequestOrigin String yang menunjukkan asal invoker. Ini bisa sama seperti topOrigin saat penjual memanggil Payment Request API secara langsung, tetapi mungkin berbeda jika API dipanggil dari dalam iframe oleh pihak ketiga seperti gateway pembayaran.
paymentRequestId Properti id dari PaymentDetailsInit yang diberikan ke Payment Request API. Jika penjual menghapus informasi, browser akan memberikan ID yang dibuat secara otomatis.
methodData Data spesifik per metode pembayaran yang disediakan penjual sebagai bagian dari PaymentMethodData. Gunakan nomor ini untuk menentukan detail transaksi pembayaran.
total Total jumlah yang diberikan penjual sebagai bagian dari PaymentDetailsInit. Gunakan metode ini untuk membuat UI yang memberi tahu pelanggan jumlah total yang harus dibayar.
instrumentKey Kunci instrumen yang dipilih oleh pengguna. Hal ini mencerminkan instrumentKey yang Anda berikan sebelumnya. String kosong menunjukkan bahwa pengguna tidak menetapkan instrumen apa pun.

Buka jendela pengendali pembayaran untuk menampilkan frontend aplikasi pembayaran berbasis web

Saat peristiwa paymentrequest diterima, aplikasi pembayaran dapat membuka jendela pengendali pembayaran dengan memanggil PaymentRequestEvent.openWindow(). Jendela pengendali pembayaran akan menampilkan antarmuka aplikasi pembayaran Anda kepada pelanggan, tempat mereka dapat melakukan autentikasi, memilih alamat dan opsi pengiriman, serta mengizinkan pembayaran. Kami akan membahas cara menulis kode frontend di Menangani pembayaran di frontend pembayaran (segera hadir).

Alur checkout dengan aplikasi pembayaran berbasis web.

Teruskan promise yang dipertahankan ke PaymentRequestEvent.respondWith() agar Anda dapat menyelesaikannya dengan hasil pembayaran pada masa mendatang.

[pengendali pembayaran] 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);
  };
});
…

Anda dapat menggunakan polyfill PromiseResolver yang mudah untuk me-resolve promise pada waktu yang berubah-ubah.

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

Bertukar informasi dengan frontend

Pekerja layanan aplikasi pembayaran dapat bertukar pesan dengan frontend aplikasi pembayaran melalui ServiceWorkerController.postMessage(). Untuk menerima pesan dari frontend, proses peristiwa message.

[pengendali pembayaran] service-worker.js:

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

Menerima sinyal siap dari frontend

Setelah jendela pengendali pembayaran dibuka, pekerja layanan harus menunggu sinyal status siap dari frontend aplikasi pembayaran. Pekerja layanan dapat meneruskan informasi penting ke frontend jika sudah siap.

Frontend [payment handler]:

navigator.serviceWorker.controller.postMessage({
  type: 'WINDOW_IS_READY'
});

[pengendali pembayaran] 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;
…

Teruskan detail transaksi ke frontend

Sekarang, kirimkan kembali detail pembayaran. Dalam hal ini, Anda hanya mengirim total permintaan pembayaran, tetapi Anda dapat meneruskan detail lebih lanjut jika mau.

[pengendali pembayaran] service-worker.js:

…
        // Pass the payment details to the frontend
        postMessage('PAYMENT_IS_READY', { total });
        break;
…

Frontend [payment handler]:

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

Mengembalikan kredensial pembayaran pelanggan

Jika pelanggan mengizinkan pembayaran, frontend dapat mengirim pesan postingan ke pekerja layanan untuk melanjutkan. Anda dapat me-resolve promise yang diteruskan ke PaymentRequestEvent.respondWith() untuk mengirimkan hasilnya kembali ke penjual. Teruskan objek PaymentHandlerResponse.

Nama properti Deskripsi
methodName ID metode pembayaran yang digunakan untuk melakukan pembayaran.
details Data spesifik metode pembayaran yang memberikan informasi yang diperlukan penjual untuk memproses pembayaran.

Frontend [payment handler]:

  const paymentMethod = …

  postMessage('PAYMENT_AUTHORIZED', {
    paymentMethod,              // Payment method identifier
  });

[pengendali pembayaran] 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;
      …

Membatalkan transaksi pembayaran

Agar pelanggan dapat membatalkan transaksi, frontend dapat mengirim pesan postingan ke pekerja layanan untuk melakukannya. Pekerja layanan kemudian dapat me-resolve promise yang diteruskan ke PaymentRequestEvent.respondWith() dengan null untuk menunjukkan kepada penjual bahwa transaksi telah dibatalkan.

Frontend [payment handler]:

  postMessage('CANCEL_PAYMENT');

[pengendali pembayaran] 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;
      …

Kode contoh

Semua kode contoh yang Anda lihat dalam dokumen ini adalah kutipan dari aplikasi contoh kerja berikut:

https://paymenthandler-demo.glitch.me

[pengendali pembayaran] pekerja layanan

Frontend [payment handler]

Untuk mencobanya:

  1. Buka https://paymentrequest-demo.glitch.me/.
  2. Arahkan kursor ke bagian bawah laman.
  3. Tekan Tambahkan tombol pembayaran.
  4. Masukkan https://paymenthandler-demo.glitch.me ke kolom ID Metode Pembayaran.
  5. Tekan tombol Pay di samping kolom.

Langkah berikutnya

Dalam artikel ini, kita telah mempelajari cara mengorkestrasi transaksi pembayaran dari pekerja layanan. Langkah berikutnya adalah mempelajari cara menambahkan beberapa fitur lanjutan ke pekerja layanan.