Signatur
Beschreibung
Das Interface MerchantValidationEvent gehört zur Payment Request API. Manche Zahlungsanbieter, allen voran Apple Pay, verlangen vor der Zahlung eine Händlervalidierung. Dabei beweist der Händler, dass er für die Zahlungsmethode registriert ist. Dafür löst der Browser am PaymentRequest-Objekt das Ereignis merchantvalidation aus, nachdem show() aufgerufen wurde.
Das Ereignisobjekt enthält zwei Werte: den Bezeichner der Zahlungsmethode in methodName und die Adresse des Validierungsservers in validationURL. Die Validierung läuft fast immer über den eigenen Server, weil dort Händlerzertifikat und geheime Schlüssel liegen. Der Server fragt bei der validationURL eine Händlersitzung an und schickt sie an den Client zurück.
Diese Sitzung übergibt man mit event.complete(promise). Das Argument ist ein Promise oder ein fertiges Objekt, das sich zur Händlersitzung auflöst. Erst danach setzt der Browser den Zahlungsvorgang fort. Wird complete() nicht (rechtzeitig) aufgerufen, bricht der Browser die Zahlung ab.
MerchantValidationEvent.methodName(nur lesbar): Bezeichner der Zahlungsmethode, z. B."https://apple.com/apple-pay".MerchantValidationEvent.validationURL(nur lesbar): Adresse, über die der Server die Händlersitzung anfordert.MerchantValidationEvent.complete(merchantSessionPromise): übergibt die Händlersitzung an den Browser.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Name des Ereignisses, in der Praxis immer "merchantvalidation" (nur beim Konstruktor new MerchantValidationEvent()). |
|
| $options | object | {} | Optionales Wörterbuch mit methodName (string, Standard "") und validationURL (string, Standard "") sowie den üblichen EventInit-Feldern wie bubbles und cancelable. |
Rückgabewert
MerchantValidationEvent. Normalerweise erzeugt der Browser das Ereignis selbst und übergibt es an den merchantvalidation-Handler.Beispiele
Händlervalidierung mit addEventListener und eigenem Server
const methods = [{
supportedMethods: 'https://apple.com/apple-pay',
data: {
version: 3,
merchantIdentifier: 'merchant.net.programmierung.shop',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
countryCode: 'DE'
}
}];
const details = {
total: { label: 'Bestellung #1042', amount: { currency: 'EUR', value: '49.90' } }
};
const request = new PaymentRequest(methods, details);
request.addEventListener('merchantvalidation', (event) => {
console.log('Methode:', event.methodName);
// Der eigene Server holt die Händlersitzung beim Anbieter ab
const sessionPromise = fetch('/api/apple-pay/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ validationURL: event.validationURL })
}).then((res) => {
if (!res.ok) throw new Error('Validierung fehlgeschlagen');
return res.json();
});
event.complete(sessionPromise);
});
const buyButton = document.querySelector('#buy');
buyButton.addEventListener('click', async () => {
try {
const response = await request.show();
await response.complete('success');
} catch (err) {
console.error('Zahlung abgebrochen:', err);
}
});
Handler über die Eigenschaft onmerchantvalidation
const request = new PaymentRequest(
[{ supportedMethods: 'https://apple.com/apple-pay', data: { version: 3, merchantIdentifier: 'merchant.net.programmierung.shop', merchantCapabilities: ['supports3DS'], supportedNetworks: ['visa'], countryCode: 'DE' } }],
{ total: { label: 'Abo', amount: { currency: 'EUR', value: '9.99' } } }
);
request.onmerchantvalidation = (event) => {
const getSession = async () => {
const res = await fetch(`/api/validate?url=${encodeURIComponent(event.validationURL)}`);
return res.json();
};
event.complete(getSession());
};
// Handler später wieder entfernen
// request.onmerchantvalidation = null;
Ereignis manuell erzeugen (z. B. für Tests)
if ('MerchantValidationEvent' in window) {
const evt = new MerchantValidationEvent('merchantvalidation', {
methodName: 'https://apple.com/apple-pay',
validationURL: 'https://apple-pay-gateway.apple.com/paymentservices/startSession'
});
console.log(evt.type, evt.methodName);
console.log(evt.validationURL);
} else {
console.log('MerchantValidationEvent wird nicht unterstützt');
}
// Wichtig · Fallstricke
Veraltet und kaum unterstützt: MerchantValidationEvent und onmerchantvalidation wurden aus der Payment-Request-Spezifikation entfernt. Chrome, Edge und Firefox liefern das Interface nicht aus. Nur Safari nutzt es für Apple Pay über PaymentRequest. Prüfen Sie die Unterstützung vorher, z. B. mit 'MerchantValidationEvent' in window. Als Alternative bietet sich die Apple-spezifische ApplePaySession mit onvalidatemerchant an.
- Sicherheit: Händlerzertifikate und private Schlüssel dürfen nie im Client-Code stehen. Die Anfrage an die
validationURLmuss immer über den eigenen Server laufen. - URL prüfen: Der Server sollte die übergebene
validationURLmit einer Liste erlaubter Adressen (Allowlist) der offiziellen Anbieter-Domains abgleichen. Sonst kann ein Angreifer den Server dazu bringen, Anfragen an beliebige Adressen zu schicken (SSRF). - Zeitlimit:
complete()muss synchron im Handler aufgerufen werden, am besten gleich mit einem Promise. Wer erst nach einemawaitaufruft, riskiert einenInvalidStateErroroder einen Abbruch durch den Browser. complete()darf nur einmal pro Ereignis aufgerufen werden. Ein zweiter Aufruf wirft einenInvalidStateError.- Die Payment Request API funktioniert nur in sicheren Kontexten (HTTPS).