Zum Hauptinhalt springen
Wenn eine Zahlung fehlschlägt, teilt Ihnen Dodo Payments warum mit durch einen standardisierten error_code und eine lesbare error_message. Dieser Leitfaden zeigt, wie diese Felder gelesen werden, entschieden wird, ob ein neuer Versuch sinnvoll ist, und wie die Zahlung wiederhergestellt wird, ohne sensible Informationen an Kunden weiterzugeben.

Wie Dodo Payments einen Ausfall meldet

Jede fehlgeschlagene Zahlung – sei es ein einmaliger Kauf oder eine Abonnementverlängerung – enthält dieselben Fehlerfelder im Zahlungsobjekt:
FeldTypBeschreibung
statusstringfailed für eine fehlgeschlagene Zahlung. Andere Nicht-Erfolgszustände umfassen cancelled, requires_customer_action und requires_payment_method.
error_codestring | nullDer standardisierte Grund des Fehlers, zum Beispiel INSUFFICIENT_FUNDS oder PROCESSING_ERROR. Siehe die Transaction Failures Referenz für die vollständige Liste.
error_messagestring | nullEine lesbare Erklärung des Fehlers.
retry_attemptinteger0 für die ursprüngliche Belastung. 1 oder höher identifiziert einen geplanten Abonnementverlängerungsversuch.
error_code und error_message sind null, bis eine Zahlung tatsächlich fehlschlägt. Überprüfen Sie zuerst status, und dann lesen Sie die Fehlerfelder.

Der payment.failed Webhook

Der zuverlässigste Weg, einen Fehler zu erkennen, ist der payment.failed Webhook. Das Ereignis umfasst das gesamte Zahlungsobjekt in data:
payment.failed payload
{
  "business_id": "bus_P3SXLcppjXgagmHS",
  "type": "payment.failed",
  "timestamp": "2025-08-04T05:36:41.609359Z",
  "data": {
    "payload_type": "Payment",
    "payment_id": "pay_2IjeQm4hqU6RA4Z4kwDee",
    "status": "failed",
    "error_code": "PROCESSING_ERROR",
    "error_message": "An error occurred while processing your card. Try again in a little bit.",
    "retry_attempt": 0,
    "subscription_id": null,
    "currency": "USD",
    "total_amount": 400,
    "payment_method": "card",
    "card_last_four": "0119",
    "card_network": "VISA",
    "payment_link": "https://test.checkout.dodopayments.com/cbq",
    "customer": {
      "customer_id": "cus_8VbC6JDZzPEqfB",
      "email": "test@acme.com",
      "name": "Test user"
    }
  }
}
Ein minimaler Handler liest error_code und leitet darauf weiter:
import { Webhook } from "standardwebhooks";
import express from "express";

const app = express();
// Mount the raw body parser so the exact payload is available for verification
app.use(express.raw({ type: "application/json" }));

const webhook = new Webhook(process.env.DODO_PAYMENTS_WEBHOOK_KEY);

app.post("/webhooks/dodo", async (req, res) => {
  // Verify the signature against the raw body before trusting the payload
  const payload = req.body.toString();
  await webhook.verify(payload, req.headers);

  const event = JSON.parse(payload);

  if (event.type === "payment.failed") {
    const payment = event.data;

    console.log(
      `Payment ${payment.payment_id} failed: ${payment.error_code} (${payment.error_message})`
    );

    if (payment.subscription_id) {
      // Subscription renewal — Dodo retries soft declines for you
      await flagSubscriptionPaymentIssue(payment.subscription_id, payment.error_code);
    } else {
      // One-time payment — prompt the customer to try again
      await notifyCustomerOfFailedPayment(payment.customer.customer_id, payment.error_code);
    }
  }

  res.json({ received: true });
});
Verifizieren Sie immer die Webhook-Signatur, bevor Sie fortfahren. Siehe den Webhooks-Leitfaden für die vollständige Einrichtung, einschließlich Signaturprüfung und Idempotenz.

Entscheiden, ob ein neuer Versuch unternommen werden soll: Weiche vs. harte Ablehnungen

Der error_code sagt Ihnen, ob ein neuer Versuch mit derselben Zahlungsmethode sinnvoll ist.
AblehnungstypWas es bedeutetWas zu tun ist
Weiche AblehnungVorübergehend oder korrigierbar (zum Beispiel INSUFFICIENT_FUNDS, PROCESSING_ERROR, NETWORK_ERROR, TRY_AGAIN_LATER).Wiederholen – nach einer Verzögerung oder sobald der Kunde seine Eingabe korrigiert – kann erfolgreich sein.
Harte AblehnungEndgültig (zum Beispiel STOLEN_CARD, LOST_CARD, DO_NOT_HONOR, FRAUDULENT).Wiederholen Sie nicht dieselbe Karte. Bitten Sie den Kunden um eine andere Zahlungsmethode.
Die Transaction Failures Referenz listet den Ablehnungstyp und die empfohlene Maßnahme für jeden error_code auf.

Umgang mit Ausfällen beim Checkout vs. bei der Verlängerung

Wie Sie sich erholen, hängt davon ab, ob der Kunde anwesend ist.
Der Kunde ist aktiv beim Checkout. Zeigen Sie eine klare Nachricht an und lassen Sie ihn sofort erneut versuchen oder eine andere Karte verwenden.
  • requires_payment_method — der Kunde hat keine Zahlungsmethode angegeben: Er hat keine Kartendetails eingegeben oder wurde aufgefordert, eine anzugeben, und hat keine Aktion unternommen. Dies ist normalerweise ein Checkout-Abbruch, keine Ablehnung — holen Sie den Kunden zurück, um die Zahlung abzuschließen (siehe Abandoned Cart Recovery).
  • requires_customer_action — zusätzliche Authentifizierung (z. B. 3DS) ist erforderlich; lassen Sie den Kunden diese abschließen. Siehe 3D Secure Handling.

Erneuerung einer fehlgeschlagenen Zahlung

  • Abonnements: Aktivieren Sie Subscription Payment Retries, um weiche Ablehnungen ohne Integrationsarbeit wiederherzustellen. Sie können die Wiederherstellung auch auslösen, indem der Kunde seine Zahlungsmethode über die Update Payment Method API aktualisiert, die alle ausstehenden Gebühren belastet.
  • Einmalige Zahlungen: Senden Sie den Checkout oder payment_link erneut, damit der Kunde es erneut mit einer anderen Methode versuchen kann. Es gibt keinen automatischen Wiederholungsversuch für einmalige Zahlungen.
Versuchen Sie nicht, harte Ablehnungen gegen dieselbe Karte zu wiederholen. Kartennetzwerke können wiederholte Ablehnungen als missbräuchlich kennzeichnen, was Ihre Autorisierungsrate beeinträchtigt.

Fehler sicher an Kunden übermitteln

Zeigen Sie Kunden eine freundliche Nachricht an — niemals den rohen error_code.
Customer-facing messaging
const CUSTOMER_MESSAGES = {
  INSUFFICIENT_FUNDS: "Your card has insufficient funds. Please use another card.",
  EXPIRED_CARD: "Your card has expired. Please use a card with a valid expiry date.",
  INCORRECT_CVC: "The security code (CVC) is incorrect. Please re-enter it.",
};

function customerMessage(errorCode) {
  // Sensitive declines must never reveal the real reason
  const SENSITIVE = ["STOLEN_CARD", "LOST_CARD", "PICKUP_CARD", "FRAUDULENT"];
  if (SENSITIVE.includes(errorCode)) {
    return "Your card was declined. Please contact your bank or use another card.";
  }
  return CUSTOMER_MESSAGES[errorCode] ?? "Your payment could not be processed. Please try another card.";
}
Offenbaren Sie niemals den echten Grund für STOLEN_CARD, LOST_CARD, PICKUP_CARD, oder FRAUDULENT. Die Anzeige dieser Gründe kann einen Betrüger warnen. Zeigen Sie eine allgemeine Ablehnungsnachricht an und speichern Sie nur den spezifischen error_code intern.

Verwandt

Transaction Failures

Jeder Ablehnungs-Code, sein Typ und die empfohlene Aktion.

Error Codes

API- und Geschäftslogikfehler, die keine Kartenablehnungen sind.

Subscription Payment Retries

Automatische Wiederherstellung von weichen Ablehnungen bei Abonnementverlängerungen.

Subscription Dunning

E-Mail-Sequenzen, die harte Ablehnungen wiederherstellen.

Payment Webhooks

Vollständiges Payload-Schema für Zahlungsereignisse.

Testing Failures

Testkarten, die Ablehnungen und Verlängerungsausfälle simulieren.
Zuletzt geändert am 18. Juni 2026