Organizowanie transakcji płatniczych z użyciem skryptu service worker

Jak dostosować internetową aplikację do płatności do płatności internetowych i zapewnić klientom lepsze wrażenia.

Gdy aplikacja do płatności zostanie zarejestrowana, możesz zacząć akceptować prośby o płatność od sprzedawców. Z tego posta dowiesz się, jak w czasie działania (tzn. gdy wyświetla się okno i użytkownik wchodzi z nim w interakcję) koordynować transakcję płatniczą z poziomu service workera.

Orkiestracja transakcji płatniczych za pomocą skryptu service worker
Orchestrating payment transactions with a service worker

„Zmiany parametrów płatności w czasie działania” to zestaw zdarzeń, które umożliwiają sprzedawcy i procesorowi płatności wymianę wiadomości, gdy użytkownik wchodzi w interakcję z procesorem płatności. Więcej informacji znajdziesz w artykule Obsługa opcjonalnych informacji o płatnościach za pomocą service workera.

Otrzymywanie od sprzedawcy zdarzenia prośby o płatność

Gdy klient zdecyduje się zapłacić za pomocą Twojej aplikacji płatniczej opartej na internecie i sprzedawca wywołaPaymentRequest.show(), Twój proces roboczy usługi otrzyma zdarzenie paymentrequest. Dodaj do service workera detektor zdarzeń, aby przechwytywać zdarzenia i przygotowywać się do kolejnych działań.

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

Zachowany PaymentRequestEvent zawiera ważne informacje o tej transakcji:

Nazwa usługi Opis
topOrigin Ciąg znaków wskazujący pochodzenie strony internetowej najwyższego poziomu (zwykle sprzedawca będący odbiorcą płatności). Użyj tego, aby określić pochodzenie sprzedawcy.
paymentRequestOrigin Ciąg znaków wskazujący pochodzenie wywołującego. Może to być ten sam adres URL co topOrigin, gdy sprzedawca wywołuje interfejs Payment Request API bezpośrednio, ale może się różnić, jeśli interfejs API jest wywoływany z poziomu elementu iframe przez inną firmę, np. bramę płatności.
paymentRequestId Właściwość id obiektu PaymentDetailsInit przekazywanego do Payment Request API. Jeśli sprzedawca pominie ten parametr, przeglądarka poda wygenerowany automatycznie identyfikator.
methodData Dane dotyczące formy płatności podane przez sprzedawcę w ramach PaymentMethodData. Użyj tego parametru, aby określić szczegóły transakcji płatniczej.
total Łączna kwota podana przez sprzedawcę w ramach PaymentDetailsInit. Użyj tej wartości, aby utworzyć interfejs, który poinformuje klienta o łącznej kwocie do zapłaty.
instrumentKey Klucz instrumentu wybrany przez użytkownika. Odpowiada to instrumentKey, które zostały przez Ciebie podane z wyprzedzeniem. Pusty ciąg znaków oznacza, że użytkownik nie określił żadnych instrumentów.

Otwórz okno modułu do obsługi płatności, aby wyświetlić interfejs aplikacji internetowej do obsługi płatności.

Gdy aplikacja do płatności otrzyma paymentrequest, może otworzyć okno obsługi płatności, wywołując PaymentRequestEvent.openWindow(). W oknie obsługi płatności wyświetli się interfejs aplikacji do płatności, w którym klient może się uwierzytelnić, wybrać adres dostawy i opcje oraz autoryzować płatność. W artykule Obsługa płatności w interfejsie płatności (wkrótce) wyjaśnimy, jak napisać kod interfejsu.

Proces płatności z użyciem aplikacji płatniczej w internecie.

Przekaż zachowaną obietnicę do PaymentRequestEvent.respondWith(), aby w przyszłości można było ją zrealizować za pomocą wyniku płatności.

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

Możesz użyć wygodnego PromiseResolverpolyfillu, aby rozwiązać obietnicę w dowolnym momencie.

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

Wymiana informacji z frontendem

Service worker aplikacji płatniczej może wymieniać wiadomości z interfejsem aplikacji płatniczej za pomocą ServiceWorkerController.postMessage(). Aby otrzymywać wiadomości z interfejsu, nasłuchuj zdarzeń message.

[payment handler] service-worker.js:

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

Otrzymywanie sygnału gotowości z interfejsu

Po otwarciu okna modułu do obsługi płatności skrypt service worker powinien czekać na sygnał gotowości z interfejsu aplikacji do płatności. Gdy service worker jest gotowy, może przekazywać ważne informacje do frontendu.

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

Przekazywanie szczegółów transakcji do frontendu

Teraz prześlij dane do płatności z powrotem. W tym przypadku wysyłasz tylko łączną kwotę prośby o płatność, ale możesz przekazać więcej szczegółów.

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

zwracać dane do płatności klienta;

Gdy klient autoryzuje płatność, interfejs może wysłać do procesu usługi wiadomość typu post, aby kontynuować. Możesz rozwiązać obietnicę przekazaną do PaymentRequestEvent.respondWith(), aby wysłać wynik z powrotem do sprzedawcy. Przekaż obiekt PaymentHandlerResponse.

Nazwa usługi Opis
methodName Identyfikator formy płatności użytej do dokonania płatności.
details Dane dotyczące formy płatności, które dostarczają sprzedawcy niezbędnych informacji do przetworzenia płatności.

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

Anulowanie transakcji płatniczej

Aby umożliwić klientowi anulowanie transakcji, interfejs może wysłać do procesu roboczego żądanie postMessage. Proces roboczy może następnie rozwiązać obietnicę przekazaną do PaymentRequestEvent.respondWith() za pomocą null, aby poinformować sprzedawcę, że transakcja została anulowana.

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

Przykładowy kod

Wszystkie przykładowe kody w tym dokumencie to fragmenty z tego źródła: Payment Handler Demo

Dalsze kroki

Z tego artykułu dowiedzieliśmy się, jak koordynować transakcję płatniczą z poziomu komponentu service worker. W następnym kroku dowiesz się, jak dodać do service workera bardziej zaawansowane funkcje.