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ę.

Po zarejestrowaniu aplikacji do płatności możesz akceptować prośby o płatności od sprzedawców. W tym poście wyjaśnimy, jak zorganizować transakcję płatności za pomocą skryptu service worker w czasie działania (czyli w czasie, gdy wyświetla się okno, a użytkownik wchodzi z nim w interakcję).

Administrowanie transakcjami płatniczymi z wykorzystaniem narzędzi service worker
Organizowanie transakcji płatniczych za pomocą skryptu service worker

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

Otrzymuj informacje o żądaniu płatności od sprzedawcy

Gdy klient zdecyduje się zapłacić za pomocą internetowej aplikacji płatniczej, a sprzedawca wywoła PaymentRequest.show(), skrypt service worker otrzyma zdarzenie paymentrequest. Dodaj do skryptu service worker detektor zdarzeń, aby zarejestrować zdarzenie i przygotować się do następnego działania.

[moduł obsługi płatności] 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 określający źródło strony internetowej najwyższego poziomu (zwykle jest to sprzedawca będący odbiorcy płatności). Służy do określania pochodzenia sprzedawcy.
paymentRequestOrigin Ciąg tekstowy wskazujący pochodzenie wywołującego. Może on być taki sam jak topOrigin, gdy sprzedawca bezpośrednio wywołuje Payment Request API, ale może być inny, jeśli interfejs API jest wywoływany w elemencie iframe przez inną firmę, na przykład bramę płatności.
paymentRequestId Właściwość id elementu PaymentDetailsInit udostępniana interfejsowi Payment Request API. Jeśli sprzedawca pominie prośbę, przeglądarka poda automatycznie wygenerowany identyfikator.
methodData Dane związane z formą płatności podane przez sprzedawcę w ramach PaymentMethodData. Służy do określania szczegółów transakcji płatności.
total Łączna kwota podana przez sprzedawcę w ramach PaymentDetailsInit. Za jego pomocą możesz utworzyć interfejs informujący klienta o łącznej kwocie do zapłaty.
instrumentKey Klucz instrumentu wybrany przez użytkownika. Odzwierciedla to podaną przez Ciebie wcześniej wartość (instrumentKey). Pusty ciąg oznacza, że użytkownik nie określił żadnych instrumentów.

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

Po otrzymaniu zdarzenia paymentrequest aplikacja płatnicza może otworzyć okno modułu obsługi płatności, wywołując metodę PaymentRequestEvent.openWindow(). W oknie modułu obsługi płatności wyświetli się interfejs Twojej aplikacji płatniczej, w którym klienci mogą dokonać uwierzytelnienia, wybrać adres dostawy i opcje, a także autoryzować płatność. Jak pisać kod frontendu, dowiesz się z artykułu 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ż zachowaną obietnicę do usługi PaymentRequestEvent.respondWith(), aby w przyszłości można było rozwiązać ją za pomocą wyniku płatności.

[moduł obsługi płatności] 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);
  };
});
…

Aby zrealizować obietnicę w dowolnym czasie, możesz użyć wygodnego kodu polyfill PromiseResolver.

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

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

[moduł obsługi płatności] service-worker.js:

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

Odbieranie sygnału gotowości z frontendu

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

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

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

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

Przekaż szczegóły transakcji do frontendu

Teraz odeślij dane do płatności. W tym przypadku wysyłasz tylko łączną kwotę żądania płatności, ale jeśli chcesz, możesz przekazać więcej szczegółów.

[moduł obsługi płatności] service-worker.js:

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

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

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

Zwrot danych uwierzytelniających płatność klienta

Gdy klient autoryzuje płatność, frontend może wysłać wiadomość do skryptu service worker, aby kontynuować. Możesz zrealizować obietnicę przekazaną firmie PaymentRequestEvent.respondWith(), aby odesłać wynik do sprzedawcy. Przekaż obiekt PaymentHandlerResponse.

nazwa usługi, Opis
methodName Identyfikator formy płatności używany do dokonywania płatności.
details Dane formy płatności, które dostarczają sprzedawcy informacji niezbędnych do przetworzenia płatności.

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

  const paymentMethod = …

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

[moduł obsługi płatności] 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, frontend może wysłać w tym celu wiadomość z postem do skryptu service worker. Skrypt service worker może następnie wykonać zadanie przekazane sprzedawcy PaymentRequestEvent.respondWith() za pomocą polecenia null, aby poinformować sprzedawcę, że transakcja została anulowana.

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

  postMessage('CANCEL_PAYMENT');

[moduł obsługi płatności] 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 widoczne w tym dokumencie pochodzą z tej działającej przykładowej aplikacji:

https://paymenthandler-demo.glitch.me

[moduł obsługi płatności] skrypt service worker

[moduł obsługi płatności] frontend

Aby to zrobić:

  1. Wejdź na https://paymentrequest-demo.glitch.me/.
  2. Przewiń do dołu strony.
  3. Kliknij Dodaj przycisk płatności.
  4. Wpisz https://paymenthandler-demo.glitch.me w polu Identyfikator formy płatności.
  5. Naciśnij przycisk Zapłać obok pola.

Dalsze kroki

Z tego artykułu dowiesz się, jak administrować transakcją płatniczą wykonywanej przez pracownika service worker. W kolejnym kroku dowiesz się, jak dodać bardziej zaawansowane funkcje do skryptu service worker.