Start · Sprachen · JavaScript · Referenz · PaymentRequestEvent.changePaymentMethod()

PaymentRequestEvent.changePaymentMethod()

Methode

Teilt dem Händler aus dem Zahlungsabwickler heraus mit, dass sich die Zahlungsmethode oder deren Details geändert haben, und liefert per Promise aktualisierte Beträge.

seit JavaScript Experimentell: Chromium-Browser (Chrome/Edge 76+), Kategorie: webapi

Signatur

PaymentRequestEvent.prototype.changePaymentMethod(methodName, methodDetails)

Beschreibung

changePaymentMethod() gehört zur Payment Handler API und wird im Service Worker einer Web-Zahlungs-App aufgerufen, also im Zahlungsabwickler und nicht auf der Händlerseite. Die Methode meldet dem Händler, dass der Nutzer im Zahlungsfenster etwas geändert hat, das den Preis beeinflussen kann. Das kann eine andere Karte sein, eine andere Kartenart (Kredit oder Debit) oder eine neue Rechnungsadresse, aus der sich andere Steuern ergeben.

Auf der Händlerseite löst der Aufruf am PaymentRequest-Objekt das Ereignis paymentmethodchange aus, ein PaymentMethodChangeEvent. Der Händler berechnet dort den Gesamtbetrag neu und gibt ihn mit event.updateWith() zurück. Diese Antwort erfüllt dann das Promise von changePaymentMethod() als PaymentRequestDetailsUpdate-Objekt, zum Beispiel mit total, modifiers, error oder paymentMethodErrors.

Typischerweise öffnet der Service Worker im paymentrequest-Handler mit event.openWindow() ein eigenes Zahlungsfenster. Dieses Fenster meldet Änderungen per postMessage() an den Service Worker. Der Service Worker ruft daraufhin changePaymentMethod() auf und schickt die neuen Beträge an das Fenster zurück, damit es sie anzeigen kann.

Parameter

Name Typ Default Beschreibung
$methodName Pflicht string Kennung der Zahlungsmethode, die sich geändert hat, zum Beispiel eine URL wie "https://bobpay.xyz/pay" oder "basic-card". Sie muss zu den Methoden passen, die der Händler angefordert hat.
$methodDetails object | null null Methodenspezifische Angaben, die der Händler braucht, um den Betrag neu zu berechnen, zum Beispiel { billingAddress: { country: 'DE' } } oder { cardType: 'debit' }. Das Objekt muss serialisierbar sein.

Rückgabewert

Typ
Promise<PaymentRequestDetailsUpdate | null>
Beschreibung
Ein Promise, das mit den aktualisierten Zahlungsdetails des Händlers erfüllt wird (total, modifiers, error, paymentMethodErrors, …). Wenn der Händler das Ereignis nicht mit updateWith() beantwortet, wird es mit null erfüllt. Unter bestimmten Bedingungen wird das Promise abgelehnt, siehe Hinweise.

Beispiele

Service Worker: Rechnungsland ändern und neuen Betrag abfragen

// sw.js des Zahlungsabwicklers
let paymentEvent = null;

self.addEventListener('paymentrequest', (event) => {
  paymentEvent = event;
  // Das Zahlungsfenster der App öffnen
  event.respondWith(new Promise((resolve, reject) => {
    self.resolvePayment = resolve;
    self.rejectPayment = reject;
    event.openWindow('/pay/checkout.html');
  }));
});

self.addEventListener('message', async (e) => {
  if (e.data.type !== 'BILLING_COUNTRY_CHANGED' || !paymentEvent) return;

  try {
    const update = await paymentEvent.changePaymentMethod(
      'https://bobpay.xyz/pay',
      { billingAddress: { country: e.data.country } }
    );
    // Neue Beträge an das Zahlungsfenster schicken
    e.source.postMessage({ type: 'TOTAL_UPDATED', update });
  } catch (err) {
    e.source.postMessage({ type: 'UPDATE_FAILED', message: err.message });
  }
});
// z. B. im Zahlungsfenster empfangen: // { type: 'TOTAL_UPDATED', update: { total: { currency: 'EUR', value: '119.00' } } }

Händlerseite: auf paymentmethodchange reagieren

const methods = [{ supportedMethods: 'https://bobpay.xyz/pay' }];
const details = {
  total: { label: 'Summe', amount: { currency: 'EUR', value: '100.00' } }
};

const request = new PaymentRequest(methods, details);

request.addEventListener('paymentmethodchange', (event) => {
  const country = event.methodDetails?.billingAddress?.country;
  const taxRate = country === 'DE' ? 0.19 : 0;
  const total = (100 * (1 + taxRate)).toFixed(2);

  // Diese Antwort erfüllt das Promise von changePaymentMethod()
  event.updateWith({
    total: { label: 'Summe inkl. USt.', amount: { currency: 'EUR', value: total } }
  });
});

document.querySelector('#buy').addEventListener('click', async () => {
  const response = await request.show();
  await response.complete('success');
});

Zahlungsfenster: Änderung melden und Antwort anzeigen

// checkout.html, Skript im Fenster, das per openWindow() geöffnet wurde
const select = document.querySelector('#country');
const totalEl = document.querySelector('#total');

select.addEventListener('change', () => {
  navigator.serviceWorker.controller?.postMessage({
    type: 'BILLING_COUNTRY_CHANGED',
    country: select.value
  });
});

navigator.serviceWorker.addEventListener('message', (e) => {
  if (e.data.type === 'TOTAL_UPDATED' && e.data.update?.total) {
    const { currency, value } = e.data.update.total;
    totalEl.textContent = `${value} ${currency}`;
  }
});
// Anzeige z. B.: 119.00 EUR

// Wichtig · Fallstricke

  • Experimentell: Die Methode wird nur von Chromium-Browsern unterstützt, also Chrome und Edge. Firefox und Safari unterstützen die Payment Handler API nicht. Vorher prüfen, zum Beispiel mit 'changePaymentMethod' in PaymentRequestEvent.prototype.
  • Nur in einem Service Worker und in einem sicheren Kontext (HTTPS) verfügbar. Das Ereignis muss vom Browser stammen (isTrusted).
  • Das Promise wird mit einem InvalidStateError abgelehnt, wenn schon eine andere Änderung läuft. Der nächste Aufruf sollte also erst erfolgen, wenn das vorherige Promise erledigt ist. Auch nach Abschluss der Zahlung, also nachdem das Promise aus respondWith() erledigt ist, schlägt der Aufruf fehl.
  • Der Händler bekommt nur die Daten, die in methodDetails stehen. Aus Datenschutzgründen nur das Nötigste übergeben, zum Beispiel Land und Postleitzahl statt der vollständigen Adresse.
  • Wenn der Händler keinen paymentmethodchange-Handler hat oder updateWith() nicht aufruft, wird das Promise mit null erfüllt. Diesen Fall immer abfangen.
  • Eine Antwort mit gesetztem Feld error oder paymentMethodErrors sollte im Zahlungsfenster als Fehlermeldung erscheinen.