Signatur
Beschreibung
Das Ereignis merchantvalidation wird von der Payment Request API an ein PaymentRequest-Objekt gesendet, nachdem show() aufgerufen wurde und der gewählte Zahlungsanbieter eine Händlervalidierung verlangt. Dabei muss der Händler nachweisen, dass er diese Zahlungsmethode nutzen darf. Das bekannteste Beispiel ist Apple Pay. Dort muss der Server des Händlers mit seinem Händlerzertifikat eine Händlersitzung (Merchant Session) beim Apple-Server anfordern.
Der Handler erhält ein MerchantValidationEvent. Die Eigenschaft validationURL enthält die Adresse, an die das eigene Backend die Validierungsanfrage schicken muss. methodName nennt die Zahlungsmethode, z. B. "https://apple.com/apple-pay". Danach ruft man event.complete() mit einem Promise auf, das die vom Anbieter gelieferten, undurchsichtigen Sitzungsdaten liefert. Erst dann zeigt der Browser das Zahlungsformular an.
Einen Handler meldet man mit addEventListener("merchantvalidation", …) an oder weist ihn der Eigenschaft onmerchantvalidation zu. Wichtig: Die Validierung darf nie im Client stattfinden. Zertifikate und private Schlüssel gehören ausschließlich auf den Server.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "merchantvalidation". |
|
| $handler Pflicht | (event: MerchantValidationEvent) => void | Funktion, die ein MerchantValidationEvent erhält. Wichtige Bestandteile: event.validationURL (string), event.methodName (string) und event.complete(merchantSessionPromise). |
|
| $options | boolean | AddEventListenerOptions | false | Übliche Listener-Optionen wie once oder signal. |
Rückgabewert
addEventListener gibt nichts zurück. Das Ergebnis der Validierung wird über event.complete() an den Browser übergeben.Beispiele
Apple-Pay-Händlervalidierung mit addEventListener
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', amount: { currency: 'EUR', value: '19.99' } } };
const request = new PaymentRequest(methods, details);
request.addEventListener('merchantvalidation', (event) => {
console.log('Validierung für', event.methodName);
// Das eigene Backend fordert mit dem Händlerzertifikat eine Sitzung an
const session = fetch('/api/applepay/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(session);
});
document.querySelector('#pay').addEventListener('click', async () => {
try {
const response = await request.show();
await response.complete('success');
} catch (err) {
console.error('Zahlung abgebrochen:', err.name);
}
});
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: '4.99' } } }
);
request.onmerchantvalidation = (event) => {
event.complete(
fetch(`/api/applepay/validate?url=${encodeURIComponent(event.validationURL)}`)
.then((res) => res.json())
);
};
Funktionsprüfung und Entfernen des Listeners
const onValidate = (event) => {
event.complete(fetch('/api/applepay/validate', {
method: 'POST',
body: JSON.stringify({ validationURL: event.validationURL })
}).then((r) => r.json()));
};
if ('onmerchantvalidation' in PaymentRequest.prototype) {
const request = new PaymentRequest(
[{ supportedMethods: 'https://apple.com/apple-pay', data: {} }],
{ total: { label: 'Test', amount: { currency: 'EUR', value: '1.00' } } }
);
request.addEventListener('merchantvalidation', onValidate);
// Nach Abschluss oder Abbruch aufräumen:
request.removeEventListener('merchantvalidation', onValidate);
console.log('merchantvalidation wird unterstützt');
} else {
console.log('Nicht unterstützt – z. B. Apple Pay JS (ApplePaySession) verwenden');
}
// Wichtig · Fallstricke
- Veraltet und nicht standardisiert: Das Ereignis und
MerchantValidationEventwurden aus der Spezifikation der Payment Request API entfernt. Nur Safari unterstützt sie (für Apple Pay). Chrome, Edge und Firefox haben sie nie ausgeliefert. Für neue Projekte sollte man vorher die Unterstützung prüfen ('onmerchantvalidation' in PaymentRequest.prototype) oder direkt Apple Pay JS mitApplePaySessionundonvalidatemerchantverwenden. - Sicherheit: Die Validierung muss auf dem Server laufen. Händlerzertifikat und Schlüssel dürfen nie in den Client gelangen. Der Server sollte außerdem prüfen, dass die
validationURLwirklich zu einer Apple-Domain gehört (*.apple.com). Sonst kann ein Angreifer den Server Anfragen an beliebige Adressen schicken lassen (SSRF). event.complete()muss synchron im Handler aufgerufen werden, und zwar mit einem Promise, nicht mit den fertigen Daten nach einemawait. Wird es zu spät oder gar nicht aufgerufen, bricht die Zahlung mit einer Zeitüberschreitung ab. Ein zweiter Aufruf löst einenInvalidStateErroraus.- Nur in sicheren Kontexten (HTTPS) verfügbar. Die Domain muss beim Zahlungsanbieter registriert und verifiziert sein.
- Wird das Promise abgelehnt, schließt der Browser das Zahlungsformular und
show()wird abgelehnt.