Signatur
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
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 });
}
});
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}`;
}
});
// 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
InvalidStateErrorabgelehnt, 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 ausrespondWith()erledigt ist, schlägt der Aufruf fehl. - Der Händler bekommt nur die Daten, die in
methodDetailsstehen. 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 oderupdateWith()nicht aufruft, wird das Promise mitnullerfüllt. Diesen Fall immer abfangen. - Eine Antwort mit gesetztem Feld
erroroderpaymentMethodErrorssollte im Zahlungsfenster als Fehlermeldung erscheinen.