Start · Sprachen · JavaScript · Referenz · MerchantValidationEvent.complete()

MerchantValidationEvent.complete()

Methode

Übergibt die vom Zahlungsdienstleister erhaltenen, händlerspezifischen Validierungsdaten (oder ein Promise darauf) an den Browser und schließt so die Händlervalidierung ab.

seit JavaScript Veraltet/experimentell – praktisch nur Safari (App deprecated seit ja Kategorie: webapi

Signatur

MerchantValidationEvent.prototype.complete(validationData)

Beschreibung

Einige Zahlungsmethoden, allen voran Apple Pay, verlangen vor dem Anzeigen des Zahlungsblatts, dass sich der Händler gegenüber dem Zahlungsdienstleister ausweist. Der Browser löst dazu am PaymentRequest das Ereignis merchantvalidation aus. Das Ereignisobjekt vom Typ MerchantValidationEvent enthält in validationURL die Adresse, an die der eigene Server eine signierte Anfrage schicken muss.

Die Antwort des Zahlungsdienstleisters (bei Apple Pay ein opakes „Merchant Session“-Objekt) wird anschließend mit complete() an den Browser zurückgereicht. Erst danach kann der Nutzer die Zahlung autorisieren. Statt der fertigen Daten darf auch ein Promise übergeben werden – das ist der übliche Weg, weil der Abruf über den eigenen Server asynchron ist.

Wichtig: complete() muss synchron innerhalb des Ereignis-Handlers aufgerufen werden. Ein await vor dem Aufruf ist daher falsch – stattdessen reicht man das noch ausstehende Promise direkt an complete() weiter.

Parameter

Name Typ Default Beschreibung
$validationData Pflicht object | Promise<object> Die vom Zahlungsdienstleister gelieferten, händlerspezifischen Validierungsdaten oder ein Promise, das mit diesen Daten erfüllt wird. Das Format bestimmt die jeweilige Zahlungsmethode (bei Apple Pay: das Merchant-Session-Objekt).

Beispiele

Händlervalidierung für Apple Pay mit Promise

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: 'Mein Shop', amount: { currency: 'EUR', value: '19.99' } }
};

const request = new PaymentRequest(methods, details);

request.addEventListener('merchantvalidation', (event) => {
  // Eigener Server fragt mit Händlerzertifikat bei validationURL an
  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: ${res.status}`);
    return res.json();
  });

  // Synchron aufrufen – das Promise wird direkt übergeben
  event.complete(sessionPromise);
});

const pay = async () => {
  try {
    const response = await request.show();
    await response.complete('success');
    console.log('Zahlung abgeschlossen');
  } catch (err) {
    console.error('Zahlung abgebrochen:', err.name);
  }
};

document.querySelector('#pay').addEventListener('click', pay);
Zahlung abgeschlossen

Variante mit der onmerchantvalidation-Eigenschaft

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' } } }
);

const fetchMerchantSession = async (validationURL) => {
  const res = await fetch(`/api/apple-pay/validate?url=${encodeURIComponent(validationURL)}`);
  return res.json();
};

request.onmerchantvalidation = (event) => {
  console.log('Validiere bei:', event.validationURL);
  event.complete(fetchMerchantSession(event.validationURL));
};
Validiere bei: https://apple-pay-gateway.apple.com/paymentservices/startSession

Typischer Fehler: await vor complete()

request.onmerchantvalidation = async (event) => {
  // FALSCH: Nach dem await ist der Handler bereits zurückgekehrt
  // const data = await fetchMerchantSession(event.validationURL);
  // event.complete(data);

  // RICHTIG: Promise synchron übergeben
  event.complete(fetchMerchantSession(event.validationURL));
};

// Wichtig · Fallstricke

  • Veraltet und kaum unterstützt: MerchantValidationEvent wurde aus der Payment-Request-Spezifikation entfernt. Chrome, Edge und Firefox haben das Ereignis nie ausgeliefert, nur Safari unterstützt es für Apple Pay. Für Apple Pay im Web ist ApplePaySession mit onvalidatemerchant / completeMerchantValidation() die verbreitetere Alternative. Vorher per 'onmerchantvalidation' in PaymentRequest.prototype prüfen.
  • InvalidStateError: Wird geworfen, wenn das Ereignis nicht vom Browser stammt (isTrusted === false, z. B. selbst erzeugt per new MerchantValidationEvent()) oder wenn complete() für dasselbe Ereignis ein zweites Mal aufgerufen wird.
  • Synchron aufrufen: complete() muss während der Ereignisverarbeitung aufgerufen werden, also vor jedem await. Asynchrone Arbeit gehört in das übergebene Promise.
  • Sicherheit: Die Anfrage an validationURL muss vom Server aus gestellt werden, denn sie braucht das Händlerzertifikat samt privatem Schlüssel. Der Schlüssel darf niemals im Client landen. Auf dem Server außerdem prüfen, dass validationURL zu einer bekannten Domain des Zahlungsdienstleisters gehört (sonst droht Server-Side Request Forgery, kurz SSRF).
  • Die Payment Request API funktioniert nur in sicheren Kontexten (HTTPS).