Signatur
Beschreibung
respondWith() ist das zentrale Werkzeug einer webbasierten Zahlungs-App, die über die Payment Handler API im Service Worker implementiert ist. Ruft eine Händlerseite new PaymentRequest(...).show() auf und wählt der Nutzer Ihre Zahlungs-App aus, empfängt Ihr Service Worker ein paymentrequest-Event vom Typ PaymentRequestEvent. Mit respondWith() teilen Sie dem Browser mit, dass Sie die Zahlung selbst abwickeln und das Ergebnis später liefern.
Als Argument übergeben Sie ein Promise, das mit einem PaymentHandlerResponse-Objekt erfüllt wird. Es enthält mindestens methodName (die genutzte Zahlungsmethode) und details (methodenspezifische Daten wie ein Token), optional Versand- und Zahlerdaten. Der Browser gibt diese Daten als PaymentResponse an das Promise von show() auf der Händlerseite weiter.
Typischerweise öffnen Sie innerhalb des Events mit event.openWindow() ein Fenster, in dem sich der Nutzer anmeldet und die Zahlung bestätigt. Das Fenster kommuniziert per postMessage mit dem Service Worker, der daraufhin das an respondWith() übergebene Promise auflöst. Wird das Promise abgelehnt, erhält die Händlerseite einen Fehler (meist AbortError) und die Zahlung gilt als abgebrochen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $promise Pflicht | Promise<PaymentHandlerResponse> | PaymentHandlerResponse | Promise (oder direkter Wert), das mit einem Objekt { methodName, details, payerName?, payerEmail?, payerPhone?, shippingAddress?, shippingOption? } erfüllt wird. Eine Ablehnung bricht die Zahlung ab. |
Beispiele
Einfache Zahlungsantwort im Service Worker
// sw.js — Service Worker der Zahlungs-App
self.addEventListener('paymentrequest', (event) => {
console.log('Betrag:', event.total.value, event.total.currency);
// Direkt eine Antwort liefern (z. B. für Tests)
event.respondWith(Promise.resolve({
methodName: 'https://pay.example.com',
details: { token: 'tok_demo_123' }
}));
});
Zahlungsfenster öffnen und auf Bestätigung warten
// sw.js
let resolver = null;
self.addEventListener('paymentrequest', (event) => {
event.respondWith(new Promise((resolve, reject) => {
resolver = { resolve, reject };
// Checkout-Seite der Zahlungs-App öffnen
event.openWindow('/checkout.html').catch((err) => {
reject(err);
resolver = null;
});
}));
});
// Nachricht aus /checkout.html empfangen
self.addEventListener('message', (event) => {
if (!resolver) return;
const { type, token } = event.data;
if (type === 'confirm') {
resolver.resolve({
methodName: 'https://pay.example.com',
details: { token }
});
} else {
resolver.reject(new DOMException('Vom Nutzer abgebrochen', 'AbortError'));
}
resolver = null;
});
Gegenstück auf der Checkout-Seite
// checkout.html — sendet das Ergebnis an den Service Worker
const sendToSW = (data) => navigator.serviceWorker.controller?.postMessage(data);
document.querySelector('#pay').addEventListener('click', async () => {
const res = await fetch('/api/authorize', { method: 'POST' });
const { token } = await res.json();
sendToSW({ type: 'confirm', token });
});
document.querySelector('#cancel').addEventListener('click', () => {
sendToSW({ type: 'cancel' });
});
Händlerseite: Antwort empfangen
// shop.js — Seite des Händlers
const request = new PaymentRequest(
[{ supportedMethods: 'https://pay.example.com' }],
{ total: { label: 'Summe', amount: { currency: 'EUR', value: '49.90' } } }
);
try {
const response = await request.show();
console.log(response.methodName, response.details);
await response.complete('success');
} catch (err) {
console.log('Zahlung abgebrochen:', err.name);
}
// Wichtig · Fallstricke
- Synchron aufrufen:
respondWith()muss während der synchronen Event-Verarbeitung aufgerufen werden, nicht erst nach einemawait– sonst wirft der BrowserInvalidStateError. Asynchrone Logik gehört in das übergebene Promise. - Nur einmal: Ein zweiter Aufruf pro Event wirft ebenfalls
InvalidStateError. - Offene Promises: Bleibt das Promise dauerhaft unerfüllt (z. B. Nutzer schließt das Fenster), hängt die Zahlung. Behandeln Sie Abbrüche daher aktiv, etwa über eine Abbruch-Nachricht oder Zeitüberschreitung.
- Sicherheit: Nur in sicheren Kontexten (HTTPS) verfügbar. Prüfen Sie in
message-Handlern die Herkunft (event.source/event.origin) und senden Sie indetailskeine rohen Kartendaten, sondern Tokens. - Kompatibilität: Die Payment Handler API ist experimentell und nur in Chromium-Browsern implementiert; Firefox und Safari unterstützen sie nicht. Die Payment-App muss vorher über
registration.paymentManagerbzw. ein Web-App-Manifest registriert sein.