Signatur
Beschreibung
Die Eigenschaft validationURL des MerchantValidationEvent liefert eine schreibgeschützte URL als Zeichenkette. Unter dieser Adresse stellt der Zahlungsdienst (payment handler), etwa Apple Pay, die Daten bereit, mit denen sich der Händler ausweist. Das Ereignis wird im Rahmen der Payment Request API als merchantvalidation auf dem PaymentRequest-Objekt ausgelöst, sobald der Zahlungsdienst einen Nachweis verlangt, dass der Händler berechtigt ist, Zahlungen anzunehmen.
Üblicherweise läuft das so ab: Der Browser-Code reicht validationURL an das eigene Backend weiter. Dieses ruft die URL mit den Händler-Zugangsdaten auf (z. B. über TLS-Client-Zertifikat), erhält eine Händlersitzung (merchant session) und gibt sie zurück. Diese Antwort wird als Promise an event.complete() übergeben, danach kann der Zahlungsdialog weiterlaufen.
Die URL selbst ist also nur eine Zwischenstation. Sie sollte niemals direkt aus dem Browser mit geheimen Zugangsdaten aufgerufen werden. Außerdem sollte das Backend vor der Anfrage prüfen, ob die Domain zum erwarteten Zahlungsdienst gehört.
Rückgabewert
USVString), unter der die zahlungsdienstspezifischen Validierungsdaten abgerufen werden können.Beispiele
validationURL an das eigene Backend weiterreichen
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.onmerchantvalidation = (event) => {
console.log('Validierungs-URL:', event.validationURL);
// Das Backend ruft die URL mit den Händler-Zugangsdaten auf
const sessionPromise = fetch('/api/merchant-validation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ validationURL: event.validationURL })
}).then((res) => res.json());
event.complete(sessionPromise);
};
const response = await request.show();
await response.complete('success');
Mit addEventListener und Fehlerbehandlung
const request = new PaymentRequest(methods, details);
request.addEventListener('merchantvalidation', (event) => {
const url = new URL(event.validationURL);
console.log('Host:', url.hostname);
event.complete(
fetch('/api/merchant-validation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ validationURL: url.href })
}).then((res) => {
if (!res.ok) throw new Error(`Validierung fehlgeschlagen: ${res.status}`);
return res.json();
})
);
});
Serverseitig: nur vertrauenswürdige Hosts zulassen (Node.js)
const ALLOWED_HOSTS = new Set([
'apple-pay-gateway.apple.com',
'apple-pay-gateway-cert.apple.com'
]);
const isTrustedValidationURL = (value) => {
try {
const url = new URL(value);
return url.protocol === 'https:' && ALLOWED_HOSTS.has(url.hostname);
} catch {
return false;
}
};
console.log(isTrustedValidationURL('https://apple-pay-gateway.apple.com/paymentservices/startSession'));
console.log(isTrustedValidationURL('https://evil.example/steal'));
// Wichtig · Fallstricke
- Veraltet:
MerchantValidationEventsamtvalidationURLwurde aus der Payment-Request-Spezifikation entfernt und ist in aktuellen Browsern praktisch nicht mehr verfügbar. Für Apple Pay im Web nutzt man stattdessenApplePaySessionmitonvalidatemerchant(Eigenschaftevent.validationURLaufApplePayValidateMerchantEvent). Vorher per Feature-Erkennung prüfen, z. B.'MerchantValidationEvent' in window. - Sicherheit (SSRF): Die URL kommt vom Client und kann manipuliert sein. Das Backend darf sie nur aufrufen, wenn Protokoll (
https:) und Host auf einer Positivliste stehen. Sonst lassen sich interne Dienste über Ihren Server ansprechen. - Händlerzertifikate und Schlüssel gehören ausschließlich auf den Server, niemals in den Browser-Code.
event.complete()muss synchron im Ereignis-Handler aufgerufen werden (mit einem Promise). Eine verspätete Antwort führt zum Abbruch des Zahlungsdialogs.- Die Eigenschaft ist schreibgeschützt. Zuweisungen werden stillschweigend ignoriert bzw. werfen im Strict Mode einen Fehler.