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

Jak dostosować internetową aplikację płatniczą do płatności internetowych i zapewnić klientom większą wygodę użytkowników.

Gdy aplikacja płatnicza zostanie zarejestrowana, będziesz mieć możliwość akceptowania próśb o płatność od sprzedawców. Z tego artykułu dowiesz się, jak zarządzać transakcją płatności z użyciem service workera w czasie działania aplikacji (czyli gdy wyświetla się okno i użytkownik wchodzi z nim w interakcję).

Administrowanie transakcjami płatności za pomocą skryptu service worker
Zarządzanie transakcjami płatniczymi za pomocą usługi workera

„Zmiany parametrów płatności w czasie wykonywania” to zbiór zdarzeń, które umożliwiają wymianę wiadomości między sprzedawcą a podmiotem obsługującym płatności, gdy użytkownik wchodzi w interakcję z tym podmiotem. Więcej informacji znajdziesz w artykule Obsługa opcjonalnych informacji o płatnościach za pomocą service workera.

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

Gdy klient zdecyduje się zapłacić za pomocą Twojej internetowej aplikacji płatniczej i wywołuje usługę sprzedawcy PaymentRequest.show(), Twój skrypt service worker otrzyma zdarzenie paymentrequest. Dodaj do serwisowego workera listenera zdarzeń, aby rejestrować zdarzenia i przygotowywać się na kolejne działanie.

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

Zapisane PaymentRequestEvent zawiera ważne informacje o tej transakcji:

Nazwa usługi Opis
topOrigin Ciąg znaków wskazujący pochodzenie strony najwyższego poziomu (zwykle sprzedawca, który jest płatnikiem). Używaj go do identyfikacji sprzedawcy.
paymentRequestOrigin Ciąg znaków wskazujący miejsce pochodzenia wywołującego. Może być taki sam jak topOrigin, gdy sprzedawca wywołuje interfejs API Request bezpośrednio, ale może być inny, jeśli interfejs API jest wywoływany z poziomu ramki osadzonej przez osobę trzecią, np. bramkę płatniczą.
paymentRequestId Właściwość id elementu PaymentDetailsInit udostępniana do interfejsu Payment Request API. Jeśli sprzedawca pominie ten element, przeglądarka poda automatycznie wygenerowany identyfikator.
methodData Dane dotyczące formy płatności, które sprzedawca udostępnia w ramach PaymentMethodData. Służy do określania szczegółów transakcji płatniczej.
total Łączna kwota podana przez sprzedawcę w ramach PaymentDetailsInit. Użyj tego, aby utworzyć interfejs użytkownika, który poinformuje klienta o łącznej kwocie do zapłaty.
instrumentKey Klucz instrumentu wybrany przez użytkownika. Odpowiada to podanym wcześniej instrumentKey. Pusty ciąg oznacza, że użytkownik nie określił żadnych instrumentów.

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

Gdy zostanie odebrane zdarzenie paymentrequest, aplikacja do płatności może otworzyć okno menedżera płatności, wywołując PaymentRequestEvent.openWindow(). Okno menedżera płatności wyświetli klientom interfejs Twojej aplikacji do płatności, w którym mogą uwierzytelnić się, wybrać adres dostawy i opcje oraz autoryzować płatność. Omówimy, jak pisać kod frontendu w sekcji Obsługa płatności w frontendzie płatności (już wkrótce).

Proces płatności w aplikacji internetowej do płatności.

Przekaż zachowane zobowiązanie do PaymentRequestEvent.respondWith(), aby móc je rozwiązać w przyszłości za pomocą 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 PromiseResolverpolyfill, 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

Worker usługi aplikacji do płatności może wymieniać wiadomości z interfejsem aplikacji za pomocą ServiceWorkerController.postMessage(). Aby otrzymywać wiadomości z interfejsu, nasłuchuj zdarzenia message.

[payment handler] service-worker.js:

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

Odbieranie gotowego sygnału z frontendu

Gdy okno modułu do obsługi płatności zostanie otwarte, skrypt service worker powinien oczekiwać sygnału o gotowości z interfejsu aplikacji do płatności. Gdy usługa jest gotowa, może przekazać 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 szczegóły płatności. W tym przypadku wysyłasz tylko łączną kwotę prośby o płatność, ale możesz też podać więcej szczegółów.

[obsługa płatności] 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;

zwracanie danych do płatności klienta;

Gdy klient autoryzuje płatność, interfejs może wysłać wiadomość do service workera, aby kontynuować. Możesz spełnić 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 zawierają informacje potrzebne sprzedawcy do przetworzenia płatności.

Frontend [obsługi płatności]:

  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łatności

Aby umożliwić klientowi anulowanie transakcji, interfejs może wysłać wiadomość do service workera. Service worker może następnie spełnić obietnicę przekazaną do PaymentRequestEvent.respondWith() z wartością 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 działającej przykładowej aplikacji:

https://paymenthandler-demo.glitch.me

[payment handler] service worker

Frontend [obsługi płatności]

Aby wypróbować tę funkcję:

  1. Otwórz stronę https://paymentrequest-demo.glitch.me/.
  2. Przewiń do dołu strony.
  3. Naciśnij przycisk Dodaj formę płatności.
  4. W polu Identyfikator formy płatności wpisz https://paymenthandler-demo.glitch.me.
  5. Kliknij przycisk Zapłać obok pola.

Dalsze kroki

Z tego artykułu dowiesz się, jak zarządzać transakcją płatności z poziomu mechanizmu Service Worker. W następnym kroku dowiesz się, jak dodać do usługi nieco bardziej zaawansowane funkcje.