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, możesz zacząć akceptować żądania płatności od sprzedawców. Z tego posta wyjaśniamy, jak zaplanować transakcję płatności z użyciem skryptu service worker w czasie działania (tj. gdy wyświetla się okno, a użytkownik wchodzi z nim w interakcję).

Administrowanie transakcjami płatności za pomocą skryptu service worker
Administrowanie transakcjami płatności za pomocą mechanizmu Service Worker

„Zmiany parametrów płatności w środowisku wykonawczym” to zbiór zdarzeń, które pozwalają sprzedawcy i modułowi obsługi płatności na wymianę wiadomości, gdy użytkownik wchodzi w interakcję z tym modułem. Więcej informacji znajdziesz w artykule Obsługa opcjonalnych danych karty za pomocą skryptu service worker.

Otrzymywanie od sprzedawcy zdarzenia żądania płatności

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 detektor zdarzeń do skryptu service worker, aby przechwycić zdarzenie i przygotować się do następnego działania.

[obsługa 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 znaków wskazujący źródło witryny najwyższego poziomu (zwykle jest to sprzedawca, który jest odbiorcą płatności). Służy do określania pochodzenia sprzedawcy.
paymentRequestOrigin Ciąg znaków wskazujący miejsce pochodzenia wywołującego. Wartość może być taka sama jak topOrigin, gdy sprzedawca wywołuje bezpośrednio Payment Request API, ale może się różnić, jeśli interfejs API jest wywoływany z elementu iframe przez firmę zewnętrzną, na przykład bramę płatności.
paymentRequestId Właściwość id elementu PaymentDetailsInit udostępniana do interfejsu Payment Request API. Jeśli sprzedawca pominie tę opcję, przeglądarka poda automatycznie wygenerowany identyfikator.
methodData Dane o formie płatności dostarczone przez sprzedawcę w ramach PaymentMethodData. Służy do określenia szczegółów transakcji płatności.
total Łączna kwota podana przez sprzedawcę w ramach PaymentDetailsInit. Użyj go, aby utworzyć interfejs informujący klienta o łącznej kwocie do zapłacenia.
instrumentKey Klucz instrumentu wybrany przez użytkownika. Dotyczy to instrumentKey, o którym mowa z wyprzedzeniem. 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 internetowej aplikacji płatniczej

Po otrzymaniu zdarzenia paymentrequest aplikacja płatnicza może otworzyć okno obsługi płatności, wywołując metodę PaymentRequestEvent.openWindow(). W oknie 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 dostawy 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.

Prześlij do PaymentRequestEvent.respondWith() zachowaną obietnicę, która pozwoli Ci rozwiązać ten problem za pomocą wyniku płatności w przyszłości.

[obsługa 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 momencie, 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łatności może wymieniać wiadomości z frontendem aplikacji płatniczej za pomocą ServiceWorkerController.postMessage(). Aby odbierać wiadomości z frontendu, nasłuchuj zdarzeń message.

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

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

Odbieranie gotowego sygnału 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 przekazać ważne informacje do frontendu, gdy będzie gotowy.

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

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

[obsługa 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;
…

Przekazywanie szczegółów transakcji do frontendu

Teraz odeślij dane do płatności. W takim przypadku wysyłasz tylko łączną kwotę żądania płatności, ale jeśli chcesz, możesz przekazać 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;
…

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

Zwracanie danych uwierzytelniających płatność klienta

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

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

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

  const paymentMethod = …

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

[obsługa 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ść do skryptu service worker. Skrypt ten może następnie zrealizować obietnicę przekazaną PaymentRequestEvent.respondWith() za pomocą null, aby zasygnalizować sprzedawcy, że transakcja została anulowana.

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

  postMessage('CANCEL_PAYMENT');

[obsługa 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 przykładowej aplikacji:

https://paymenthandler-demo.glitch.me

Skrypt service worker [metoda obsługi płatności]

Frontend [obsługi płatności]

Aby wypróbować tę funkcję:

  1. Wejdź na https://paymentrequest-demo.glitch.me/.
  2. Przewiń do dołu strony.
  3. Kliknij przycisk Dodaj płatność.
  4. Wpisz https://paymenthandler-demo.glitch.me w polu Payment Method Identifier (Identyfikator formy płatności).
  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. Następnym krokiem jest nauczenie się, jak dodać do skryptu service worker bardziej zaawansowane funkcje.