Signatur
Beschreibung
updateWith() wird innerhalb eines Event-Handlers für shippingaddresschange, shippingoptionchange oder paymentmethodchange aufgerufen. Damit teilst du dem Browser mit, dass sich die Zahlungsdetails auf Grund der Nutzereingabe ändern, etwa weil für eine andere Lieferadresse andere Versandkosten oder Steuern anfallen.
Du kannst der Methode ein fertiges Objekt vom Typ PaymentDetailsUpdate übergeben oder, was üblicher ist, ein Promise, das zu so einem Objekt aufgelöst wird. Solange das Promise noch offen ist, zeigt der Browser in der Zahlungsoberfläche eine Ladeanzeige und blockiert weitere Eingaben. So kannst du in Ruhe asynchron beim Server Versandkosten berechnen lassen.
Wichtig: updateWith() muss synchron im Event-Handler aufgerufen werden, also bevor der Handler zurückkehrt. Ein Aufruf nach einem await kommt zu spät. Die asynchrone Arbeit gehört deshalb in das Promise, das du übergibst. Pro Event darf die Methode nur einmal aufgerufen werden.
Über die Felder error, shippingAddressErrors oder paymentMethodErrors meldest du ungültige Eingaben. Setzt du shippingOptions auf ein leeres Array, kann an die gewählte Adresse nicht geliefert werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $details Pflicht | PaymentDetailsUpdate | Promise<PaymentDetailsUpdate> | Die neuen Details bzw. ein Promise darauf. Mögliche Felder: total, displayItems, shippingOptions, modifiers, error, shippingAddressErrors, payerErrors, paymentMethodErrors. Nicht angegebene Felder bleiben unverändert. |
Rückgabewert
undefined).Beispiele
Versandkosten nach Adressänderung asynchron neu berechnen
const details = {
total: { label: 'Summe', amount: { currency: 'EUR', value: '49.00' } },
displayItems: [{ label: 'Kopfhörer', amount: { currency: 'EUR', value: '49.00' } }],
shippingOptions: []
};
const request = new PaymentRequest(
[{ supportedMethods: 'https://google.com/pay' }],
details,
{ requestShipping: true }
);
const berechneVersand = async (adresse) => {
const res = await fetch('/api/versand', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ land: adresse.country, plz: adresse.postalCode })
});
const { kosten } = await res.json();
const gesamt = (49 + kosten).toFixed(2);
return {
displayItems: [
...details.displayItems,
{ label: 'Versand', amount: { currency: 'EUR', value: kosten.toFixed(2) } }
],
shippingOptions: [{
id: 'standard', label: 'Standardversand', selected: true,
amount: { currency: 'EUR', value: kosten.toFixed(2) }
}],
total: { label: 'Summe', amount: { currency: 'EUR', value: gesamt } }
};
};
request.addEventListener('shippingaddresschange', (event) => {
// Synchron aufrufen und Promise übergeben!
event.updateWith(berechneVersand(request.shippingAddress));
});
const response = await request.show();
await response.complete('success');
Nicht belieferbare Adresse ablehnen
request.addEventListener('shippingaddresschange', (event) => {
const { country } = request.shippingAddress;
if (!['DE', 'AT', 'CH'].includes(country)) {
event.updateWith({
shippingOptions: [],
error: 'Wir liefern nur nach Deutschland, Österreich und in die Schweiz.',
shippingAddressErrors: { country: 'Land wird nicht beliefert.' }
});
return;
}
event.updateWith({
shippingOptions: [{ id: 'dach', label: 'DACH-Versand', selected: true,
amount: { currency: 'EUR', value: '4.90' } }],
total: { label: 'Summe', amount: { currency: 'EUR', value: '53.90' } }
});
});
Gesamtbetrag bei Wechsel der Versandart anpassen
const preise = { standard: 4.9, express: 12.9 };
request.addEventListener('shippingoptionchange', (event) => {
const option = request.shippingOption; // z. B. 'express'
const versand = preise[option];
event.updateWith({
shippingOptions: Object.entries(preise).map(([id, preis]) => ({
id,
label: id === 'express' ? 'Express' : 'Standard',
selected: id === option,
amount: { currency: 'EUR', value: preis.toFixed(2) }
})),
total: { label: 'Summe', amount: { currency: 'EUR', value: (49 + versand).toFixed(2) } }
});
});
// Wichtig · Fallstricke
- Synchron aufrufen: Kommt der Aufruf erst nach einem
awaitoder in einemsetTimeout, wirft er einenInvalidStateErroroder wird ignoriert. Asynchrone Logik gehört immer in das übergebene Promise. - Ein zweiter Aufruf für dasselbe Event wirft einen
InvalidStateError. Das gilt auch, wenn das Event nicht vertrauenswürdig ist (isTrusted === false). - Wird das Promise abgelehnt oder sind die Daten ungültig (z. B. ein negativer
total), bricht der Browser die gesamte Zahlung ab undshow()wird mit einemAbortErrorabgelehnt. - Wählst du bei
shippingOptionsdie Option mitselected: trueaus, dann müssen auchtotalunddisplayItemsdazu passen. Der Browser gleicht das nicht selbst ab. - Sicherheit: Preise im Client sind nur zur Anzeige da. Den endgültigen Betrag musst du immer auf dem Server prüfen. Die Payment Request API gibt es nur in sicheren Kontexten (HTTPS).
- Kompatibilität: Chromium-Browser und Safari unterstützen die Methode. In Firefox ist die Payment Request API standardmäßig deaktiviert. Die Unterstützung von
shippingaddresschangewurde in Chrome teilweise eingeschränkt, deshalb brauchst du einen Fallback im Checkout.