Zahlungstransaktionen mit einem Service Worker orchestrieren

Hier erfahren Sie, wie Sie Ihre webbasierte Zahlungs-App an Web Payments anpassen und die Nutzerfreundlichkeit für Ihre Kunden verbessern.

Sobald die Zahlungs-App registriert ist, kannst du Zahlungsanfragen von Händlern akzeptieren. In diesem Beitrag wird erläutert, wie eine Zahlungstransaktion von einem Service Worker während der Laufzeit orchestriert wird, d.h. wenn ein Fenster angezeigt wird und der Nutzer damit interagiert.

Zahlungstransaktionen mit einem Service Worker orchestrieren
Zahlungstransaktionen mit einem Service Worker orchestrieren

„Änderungen an Laufzeit-Zahlungsparametern“ bezieht sich auf eine Reihe von Ereignissen, über die der Händler und der Zahlungs-Handler Nachrichten austauschen können, während der Nutzer mit dem Zahlungs-Handler interagiert. Weitere Informationen finden Sie unter Mit einem Service Worker mit optionalen Zahlungsinformationen umgehen.

Eine Zahlungsanforderung vom Händler erhalten

Wenn sich ein Kunde für die Zahlung mit deiner webbasierten Zahlungs-App entscheidet und der Händler PaymentRequest.show() aufruft, erhält dein Service Worker ein paymentrequest-Ereignis. Fügen Sie dem Service Worker einen Event-Listener hinzu, um das Ereignis zu erfassen und sich auf die nächste Aktion vorzubereiten.

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

Die beibehaltene PaymentRequestEvent enthält wichtige Informationen zu dieser Transaktion:

Property-Name Beschreibung
topOrigin Ein String, der den Ursprung der Webseite auf oberster Ebene angibt (normalerweise der Zahlungsempfänger) Hiermit kannst du den Händlerherkunft ermitteln.
paymentRequestOrigin Ein String, der den Ursprung des Aufrufers angibt. Dies kann mit topOrigin identisch sein, wenn der Händler die Payment Request API direkt aufruft. Der Wert kann jedoch abweichen, wenn die API in einem iFrame von einem Drittanbieter wie einem Zahlungs-Gateway aufgerufen wird.
paymentRequestId Die id-Eigenschaft der PaymentDetailsInit, die an die Payment Request API übergeben wurde. Wenn der Händler diese Angabe auslässt, stellt der Browser eine automatisch generierte ID bereit.
methodData Die zahlungsmethodenspezifischen Daten, die vom Händler im Rahmen von PaymentMethodData bereitgestellt werden. Hiermit können Sie die Details der Zahlungstransaktion ermitteln.
total Der vom Händler im Rahmen von PaymentDetailsInit bereitgestellte Gesamtbetrag. Hiermit können Sie eine Benutzeroberfläche erstellen, die den Kunden über den zu zahlenden Gesamtbetrag informiert.
instrumentKey Der vom Nutzer ausgewählte Zahlungsmittelschlüssel. Dies entspricht der instrumentKey, die du im Voraus angegeben hast. Eine leere Zeichenfolge bedeutet, dass der Nutzer keine Instrumente angegeben hat.

Fenster „Zahlungs-Handler“ öffnen, um das Frontend der webbasierten Zahlungs-App anzuzeigen

Wenn ein paymentrequest-Ereignis empfangen wird, kann die Zahlungs-App durch Aufrufen von PaymentRequestEvent.openWindow() ein Zahlungs-Handler-Fenster öffnen. Im Fenster des Zahlungs-Handlers wird den Kunden die Benutzeroberfläche Ihrer Zahlungs-App angezeigt. Hier können sie sich authentifizieren, Versandadresse und Optionen auswählen und die Zahlung autorisieren. Wie Sie den Front-End-Code schreiben, erfahren Sie in Zahlungen im Zahlungs-Front-End verarbeiten (demnächst verfügbar).

Bezahlvorgang mit einer webbasierten Zahlungs-App.

Übergeben Sie ein beibehaltenes Promise an PaymentRequestEvent.respondWith(), damit Sie es in Zukunft mit einem Zahlungsergebnis auflösen können.

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

Du kannst einen praktischen PromiseResolver-Polyfill verwenden, um ein Promise zu einem beliebigen Zeitpunkt aufzulösen.

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

Informationen mit dem Frontend austauschen

Der Service Worker der Zahlungsanwendung kann über ServiceWorkerController.postMessage() Nachrichten mit dem Frontend der Zahlungsanwendung austauschen. Warten Sie auf message-Ereignisse, um Nachrichten vom Front-End zu erhalten.

[Zahlungs-Handler] service-worker.js:

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

Bereit-Signal vom Front-End empfangen

Sobald das Zahlungs-Handler-Fenster geöffnet ist, wartet der Service Worker auf ein Signal vom Typ „Bereit“ vom Front-End der Zahlungsanwendung. Der Service Worker kann wichtige Informationen an das Front-End weiterleiten, wenn es bereit ist.

[Zahlungs-Handler]-Front-End:

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

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

Transaktionsdetails an das Frontend übergeben

Senden Sie nun die Zahlungsdetails zurück. In diesem Fall senden Sie nur die Gesamtsumme der Zahlungsanforderung. Sie können aber auch weitere Details übergeben.

[Zahlungs-Handler] service-worker.js:

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

[Zahlungs-Handler]-Front-End:

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

Die Zahlungsdaten des Kunden zurückgeben

Wenn der Kunde die Zahlung autorisiert, kann das Front-End eine Post-Nachricht an den Service Worker senden, um fortzufahren. Du kannst das an PaymentRequestEvent.respondWith() übergebene Versprechen auflösen, um das Ergebnis an den Händler zu senden. Übergeben Sie ein PaymentHandlerResponse-Objekt.

Property-Name Beschreibung
methodName Die Kennung der Zahlungsmethode, die für die Zahlung verwendet wurde.
details Die spezifischen Daten zur Zahlungsmethode, die dem Händler die erforderlichen Informationen zur Verarbeitung der Zahlung liefern.

[Zahlungs-Handler]-Front-End:

  const paymentMethod = …

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

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

Zahlungstransaktion abbrechen

Damit der Kunde die Transaktion abbrechen kann, kann das Front-End eine entsprechende Post-Nachricht an den Service Worker senden. Der Service Worker kann dann das an PaymentRequestEvent.respondWith() übergebene Versprechen mit null auflösen und dem Händler mitteilen, dass die Transaktion abgebrochen wurde.

[Zahlungs-Handler]-Front-End:

  postMessage('CANCEL_PAYMENT');

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

Beispielcode

Alle Beispielcodes in diesem Dokument waren Auszüge aus der folgenden funktionierenden Beispiel-App:

https://paymenthandler-demo.glitch.me

[payment-Handler]-Service-Worker

[Zahlungs-Handler] Frontend

So probierst du es aus:

  1. Rufen Sie https://paymentrequest-demo.glitch.me/ auf.
  2. Sehen Sie sich den Bereich ganz unten auf der Seite an.
  3. Klicken Sie auf Zahlungsschaltfläche hinzufügen.
  4. Geben Sie in das Feld ID der Zahlungsmethode https://paymenthandler-demo.glitch.me ein.
  5. Drücke auf die Schaltfläche Bezahlen, die neben dem Feld angezeigt wird.

Weitere Informationen

In diesem Artikel wurde beschrieben, wie eine Zahlungstransaktion von einem Service Worker orchestriert wird. Im nächsten Schritt erfahren Sie, wie Sie dem Service Worker einige erweiterte Features hinzufügen.