> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hono Adaptor

> Erfahren Sie, wie Sie Dodo Payments mit Ihrem Hono App Router-Projekt unter Verwendung unseres NextJS Adapters integrieren. Behandelt Checkout, Kundenportal, Webhooks und die Einrichtung einer sicheren Umgebung.

<CardGroup cols={2}>
  <Card title="Checkout Handler" icon="cart-shopping" href="#checkout-route-handler">
    Integriere den Dodo Payments Checkout in deine Hono-App.
  </Card>

  <Card title="Customer Portal" icon="user" href="#customer-portal-route-handler">
    Erlaube Kund:innen, Abonnements und Daten zu verwalten.
  </Card>

  <Card title="Webhooks" icon="bell" href="#webhook-route-handler">
    Empfange und verarbeite Dodo Payments Webhook-Ereignisse.
  </Card>
</CardGroup>

## Installation

<Steps>
  <Step title="Install the package">
    Führe im Stammverzeichnis deines Projekts den folgenden Befehl aus:

    ```bash theme={null}
    npm install @dodopayments/hono
    ```
  </Step>

  <Step title="Set up environment variables">
    Erstelle eine <code>.env</code>-Datei im Stammverzeichnis deines Projekts:

    ```env expandable theme={null}
    DODO_PAYMENTS_API_KEY=your-api-key
    DODO_PAYMENTS_RETURN_URL=https://yourapp.com/success
    DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
    DODO_PAYMENTS_ENVIRONMENT="test_mode" or "live_mode""
    ```

    <Warning>
      Committe deine <code>.env</code>-Datei oder Geheimnisse niemals in die Versionskontrolle.
    </Warning>
  </Step>
</Steps>

## Beispiele für Routenhandler

<Info>
  Alle Beispiele setzen voraus, dass du den Hono App Router verwendest.
</Info>

<Tabs>
  <Tab title="Checkout Handler">
    <Info>
      Verwende diesen Handler, um den Dodo Payments Checkout in deine Hono-App zu integrieren. Unterstützt statische (GET), dynamische (POST) und Session-(POST-)Flows.
    </Info>

    <CodeGroup>
      ```typescript Hono Route Handler expandable theme={null}
        // route.ts
        import { Checkout } from '@dodopayments/hono';
        import Hono from 'hono'

        const app = new Hono()

        app.get(
        "/api/checkout",
        Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'static'
        })
        );

        app.post(
        "/api/checkout",
        Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'dynamic'
        })
        );
        
        app.post(
        "/api/checkout",
        Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'session'
        })
        );
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Static Checkout Curl example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/api/checkout?productId=pdt_fqJhl7pxKWiLhwQR042rh' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Dynamic Checkout Curl example expandable theme={null}
      curl --request POST \
      --url https://example.com/api/checkout \
      --header 'Content-Type: application/json' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test \
      --data '{
      "billing": {
        "city": "Texas",
        "country": "US",
        "state": "Texas",
        "street": "56, hhh",
        "zipcode": "560000"
      },
      "customer": {
        "email": "test@example.com",
        	"name": "test"
      },
      "metadata": {},
      "payment_link": true,
        "product_id": "pdt_QMDuvLkbVzCRWRQjLNcs",
        "quantity": 1,
        "billing_currency": "USD",
        "discount_codes": ["IKHZ23M9GQ"],
        "return_url": "https://example.com",
        "trial_period_days": 10
      }'
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Checkout Session Curl example expandable theme={null}
      curl --request POST \
      --url https://example.com/api/checkout \
      --header 'Content-Type: application/json' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test \
      --data '{
      "product_cart": [
        {
          "product_id": "pdt_QMDuvLkbVzCRWRQjLNcs",
          "quantity": 1
        }
      ],
      "customer": {
        "email": "test@example.com",
        "name": "test"
      },
      "return_url": "https://example.com/success"
      }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Customer Portal Handler">
    <Info>
      Verwende diesen Handler, damit Kund:innen ihre Abonnements und Daten über das Dodo Payments Kundenportal verwalten können.
    </Info>

    <CodeGroup>
      ```typescript Hono Route Handler expandable theme={null}
      // route.ts
      import { Checkout } from '@dodopayments/hono';
      import Hono from 'hono'

      const app = new Hono()
      app.get(
          "/api/customer-portal",
          CustomerPortal({
              bearerToken: process.env.DODO_PAYMENTS_API_KEY,
              environment: process.env.DODO_PAYMENTS_ENVIRONMENT
          })
      );
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Customer Portal Curl example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/api/customer-portal?customer_id=cus_9VuW4K7O3GHwasENg31m&send_email=true' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Webhook Handler">
    <Info>
      Verwende diesen Handler, um Dodo Payments Webhook-Ereignisse sicher in deiner Hono-App zu empfangen und zu verarbeiten.
    </Info>

    <CodeGroup>
      ```typescript Hono Route Handler expandable theme={null}
      // route.ts
      import Hono from 'hono'
      import { Webhooks } from '@dodopayments/hono'

      const app = new Hono()
      app.post(
      "/api/webhooks",
          Webhooks({
              webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
              onPayload: async (payload) => {
              // Handle Payload Here
              console.log(payload)
              }
          })
      );

      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Checkout Route Handler

<Info>
  Dodo Payments unterstützt drei Arten von Zahlungsflüssen zur Integration von Zahlungen auf deiner Website; dieser Adapter unterstützt alle Typen.
</Info>

* **Statische Zahlungslinks:** Sofort teilbare URLs zur schnellen, codefreien Zahlungsabwicklung.
* **Dynamische Zahlungslinks:** Programmgesteuertes Erstellen von Zahlungslinks mit benutzerdefinierten Details über die API oder SDKs.
* **Checkout-Sitzungen:** Erstellen Sie sichere, anpassbare Checkout-Erlebnisse mit vorkonfigurierten Produktkörben und Kundendetails.

<AccordionGroup>
  <Accordion title="Static Checkout (GET)">
    ### Unterstützte Abfrageparameter

    <ParamField query="productId" type="string" required>
      Produktkennzeichen (z. B. <code>?productId=pdt\_nZuwz45WAs64n3l07zpQR</code>).
    </ParamField>

    <ParamField query="quantity" type="integer">
      Menge des Produkts.
    </ParamField>

    <ParamField query="fullName" type="string">
      Vollständiger Name der Kund:innen.
    </ParamField>

    <ParamField query="firstName" type="string">
      Vorname der Kund:innen.
    </ParamField>

    <ParamField query="lastName" type="string">
      Nachname der Kund:innen.
    </ParamField>

    <ParamField query="email" type="string">
      E-Mail-Adresse der Kund:innen.
    </ParamField>

    <ParamField query="country" type="string">
      Land der Kund:innen.
    </ParamField>

    <ParamField query="addressLine" type="string">
      Adresszeile der Kund:innen.
    </ParamField>

    <ParamField query="city" type="string">
      Stadt der Kund:innen.
    </ParamField>

    <ParamField query="state" type="string">
      Bundesland/Provinz der Kund:innen.
    </ParamField>

    <ParamField query="zipCode" type="string">
      Postleitzahl der Kund:innen.
    </ParamField>

    <ParamField query="disableFullName" type="boolean">
      Deaktiviere das Feld für den vollständigen Namen.
    </ParamField>

    <ParamField query="disableFirstName" type="boolean">
      Deaktiviere das Feld für den Vornamen.
    </ParamField>

    <ParamField query="disableLastName" type="boolean">
      Deaktiviere das Feld für den Nachnamen.
    </ParamField>

    <ParamField query="disableEmail" type="boolean">
      Deaktiviere das E-Mail-Feld.
    </ParamField>

    <ParamField query="disableCountry" type="boolean">
      Deaktiviere das Länderfeld.
    </ParamField>

    <ParamField query="disableAddressLine" type="boolean">
      Deaktiviere das Feld für die Adresszeile.
    </ParamField>

    <ParamField query="disableCity" type="boolean">
      Deaktiviere das Stadtfeld.
    </ParamField>

    <ParamField query="disableState" type="boolean">
      Deaktiviere das Feld für das Bundesland.
    </ParamField>

    <ParamField query="disableZipCode" type="boolean">
      Deaktiviere das Feld für die Postleitzahl.
    </ParamField>

    <ParamField query="paymentCurrency" type="string">
      Gib die Zahlungswährung an (z. B. <code>USD</code>).
    </ParamField>

    <ParamField query="showCurrencySelector" type="boolean">
      Währungsselector anzeigen.
    </ParamField>

    <ParamField query="paymentAmount" type="integer">
      Gib den Zahlungsbetrag an (z. B. <code>1000</code> für 10,00 \$).
    </ParamField>

    <ParamField query="showDiscounts" type="boolean">
      Rabattfelder anzeigen.
    </ParamField>

    <ParamField query="metadata_*" type="string">
      Jeder Abfrageparameter, der mit <code>metadata\_</code> beginnt, wird als Metadaten übergeben.
    </ParamField>

    <Warning>
      Fehlt <code>productId</code>, liefert der Handler eine 400-Antwort. Ungültige Abfrageparameter führen ebenfalls zu einer 400-Antwort.
    </Warning>

    ### Antwortformat

    Der statische Checkout gibt eine JSON-Antwort mit der Checkout-URL zurück:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Dynamic Checkout (POST)">
    * Sende Parameter als JSON-Body in einer POST-Anfrage.
    * Unterstützt sowohl Einmalzahlungen als auch wiederkehrende Zahlungen.
    * Eine vollständige Liste der unterstützten POST-Body-Felder findest du unter:
      * [Request body for a One Time Payment Product](https://docs.dodopayments.com/api-reference/payments/post-payments)
      * [Request body for a Subscription Product](https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions)

    ### Antwortformat

    Der dynamische Checkout gibt eine JSON-Antwort mit der Checkout-URL zurück:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Checkout Sessions (POST)">
    Checkout-Sessions bieten ein sichereres, gehostetes Checkout-Erlebnis, das den vollständigen Zahlungsfluss sowohl für Einmalkäufe als auch Abonnements mit voller Anpassungskontrolle übernimmt.

    Siehe [Checkout Sessions Integration Guide](https://docs.dodopayments.com/developer-resources/checkout-session) für weitere Details und eine vollständige Liste der unterstützten Felder.

    ### Antwortformat

    Checkout-Sitzungen geben eine JSON-Antwort mit der Checkout-URL zurück:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/session/..."
    }
    ```
  </Accordion>
</AccordionGroup>

## Customer Portal Route Handler

Der Customer Portal Route Handler ermöglicht es Ihnen, das Dodo Payments Kundenportal nahtlos in Ihre Hono-Anwendung zu integrieren.

### Abfrageparameter

<ParamField query="customer_id" type="string" required>
  Die Kunden-ID für die Portal-Session (z. B. <code>?customer\_id=cus\_123</code>).
</ParamField>

<ParamField query="send_email" type="boolean">
  Ist der Wert auf <code>true</code> gesetzt, wird dem Kunden eine E-Mail mit dem Portal-Link zugesendet.
</ParamField>

<Warning>
  Gibt 400 zurück, wenn <code>customer\_id</code> fehlt.
</Warning>

## Webhook Route Handler

* **Methode:** Nur POST-Anfragen werden unterstützt. Andere Methoden geben 405 zurück.
* **Signaturverifizierung:** Überprüft die Webhook-Signatur mit <code>webhookKey</code>. Gibt 401 zurück, wenn die Verifizierung fehlschlägt.
* **Payload-Validierung:** Wird mit Zod validiert. Gibt 400 für ungültige Payloads zurück.
* **Fehlerbehandlung:**
  * 401: Ungültige Signatur
  * 400: Ungültige Payload
  * 500: Interner Fehler während der Verifizierung
* **Ereignisweiterleitung:** Ruft den entsprechenden Ereignishandler basierend auf dem Payload-Typ auf.

### Unterstützte Webhook-Ereignishandler

<CodeGroup>
  ```typescript Typescript expandable theme={null}
  onPayload?: (payload: WebhookPayload) => Promise<void>;
  onPaymentSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onPaymentFailed?: (payload: WebhookPayload) => Promise<void>;
  onPaymentProcessing?: (payload: WebhookPayload) => Promise<void>;
  onPaymentCancelled?: (payload: WebhookPayload) => Promise<void>;
  onRefundSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onRefundFailed?: (payload: WebhookPayload) => Promise<void>;
  onDisputeOpened?: (payload: WebhookPayload) => Promise<void>;
  onDisputeExpired?: (payload: WebhookPayload) => Promise<void>;
  onDisputeAccepted?: (payload: WebhookPayload) => Promise<void>;
  onDisputeCancelled?: (payload: WebhookPayload) => Promise<void>;
  onDisputeChallenged?: (payload: WebhookPayload) => Promise<void>;
  onDisputeWon?: (payload: WebhookPayload) => Promise<void>;
  onDisputeLost?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionActive?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionOnHold?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionRenewed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionPlanChanged?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionCancelled?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionFailed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionExpired?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionUpdated?: (payload: WebhookPayload) => Promise<void>;
  onLicenseKeyCreated?: (payload: WebhookPayload) => Promise<void>;
  onAbandonedCheckoutDetected?: (payload: WebhookPayload) => Promise<void>;
  onAbandonedCheckoutRecovered?: (payload: WebhookPayload) => Promise<void>;
  onDunningStarted?: (payload: WebhookPayload) => Promise<void>;
  onDunningRecovered?: (payload: WebhookPayload) => Promise<void>;
  onCreditAdded?: (payload: WebhookPayload) => Promise<void>;
  onCreditDeducted?: (payload: WebhookPayload) => Promise<void>;
  onCreditExpired?: (payload: WebhookPayload) => Promise<void>;
  onCreditRolledOver?: (payload: WebhookPayload) => Promise<void>;
  onCreditRolloverForfeited?: (payload: WebhookPayload) => Promise<void>;
  onCreditOverageCharged?: (payload: WebhookPayload) => Promise<void>;
  onCreditManualAdjustment?: (payload: WebhookPayload) => Promise<void>;
  onCreditBalanceLow?: (payload: WebhookPayload) => Promise<void>;
  ```
</CodeGroup>

***

## Prompt for LLM

```
Sie sind ein Experte für Hono-Entwicklung. Ihre Aufgabe ist es, einen Benutzer durch die Integration des @dodopayments/hono-Adapters in sein bestehendes Hono-Projekt zu führen.

Der @dodopayments/hono-Adapter bietet Routenhandler für die Checkout-, Kundenportal- und Webhook-Funktionalitäten von Dodo Payments, die direkt in eine Hono-App integriert werden können.

Zuerst installieren Sie das erforderliche Paket. Verwenden Sie den für das Projekt des Benutzers geeigneten Paketmanager (npm, yarn oder bun):

npm install @dodopayments/hono

---

So sollten Sie Ihre Antwort strukturieren:

1. Fragen Sie den Benutzer, welche Funktionalitäten er integrieren möchte.

"Welche Teile des @dodopayments/hono-Adapters möchten Sie in Ihr Projekt integrieren? Sie können eine oder mehrere der folgenden Optionen wählen:

- Checkout Route Handler (zum Verarbeiten von Produkt-Checkouts)
- Customer Portal Route Handler (zum Verwalten von Kundenabonnements/Details)
- Webhook Route Handler (zum Empfangen von Dodo Payments Webhook-Ereignissen)
- Alle (alle drei integrieren)"

---

2. Basierend auf der Auswahl des Benutzers geben Sie detaillierte Integrationsschritte für jede gewählte Funktionalität an.

---

**Wenn der Checkout Route Handler ausgewählt ist:**

**Zweck**: Dieser Handler leitet Benutzer zur Dodo Payments Checkout-Seite weiter.

**Integration**:
Erstellen Sie zwei Routen in Ihrer Hono-App — eine für statischen (GET) und eine für dynamischen (POST) Checkout.

import { Checkout } from '@dodopayments/hono';
import Hono from 'hono'

const app = new Hono()

app.get(
  "/api/checkout",
  Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'static'
  })
);

app.post(
  "/api/checkout",
  Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'session' // oder 'dynamic' für dynamischen Link
  })
);

Konfigurationsoptionen:

    bearerToken: Ihr Dodo Payments API-Schlüssel (empfohlen, in der Umgebungsvariablen DODO_PAYMENTS_API_KEY zu speichern).

    returnUrl (optional): URL, um den Benutzer nach erfolgreichem Checkout weiterzuleiten.

    environment: "test_mode" oder "live_mode"

    type: "static" (GET) oder "dynamic" (POST) oder "session" (POST)

GET (statischer Checkout) erwartet Abfrageparameter:

    productId (erforderlich)

    Menge, Kundenfelder (fullName, email usw.) und Metadaten (metadata_*) sind optional.

POST (dynamischer Checkout) erwartet einen JSON-Body mit Zahlungsdetails (einmalig oder Abonnement). Verweisen Sie auf die Dokumentation für das vollständige POST-Schema:

    Einmalige Zahlungen: https://docs.dodopayments.com/api-reference/payments/post-payments

    Abonnements: https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions

POST (Checkout-Sitzungen) - (Empfohlen) Ein anpassbareres Checkout-Erlebnis. Gibt JSON mit checkout_url zurück: Parameter werden als JSON-Body gesendet. Unterstützt sowohl einmalige als auch wiederkehrende Zahlungen. Gibt zurück: {"checkout_url": "https://checkout.dodopayments.com/session/..."}. Für eine vollständige Liste der unterstützten Felder siehe:

  Checkout Sessions Integration Guide: https://docs.dodopayments.com/developer-resources/checkout-session

Wenn der Customer Portal Route Handler ausgewählt ist:

Zweck: Diese Route ermöglicht es Kunden, ihre Abonnements über das Dodo Payments-Portal zu verwalten.

Integration:

import { Checkout } from '@dodopayments/hono';
import Hono from 'hono'

const app = new Hono()
app.get(
  "/api/customer-portal",
  CustomerPortal({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT
  })
);

Abfrageparameter:

    customer_id (erforderlich): z. B. ?customer_id=cus_123

    send_email (optional): wenn true, wird dem Kunden der Portal-Link per E-Mail gesendet

Gibt 400 zurück, wenn customer_id fehlt.

Wenn der Webhook Route Handler ausgewählt ist:

Zweck: Verarbeitet eingehende Webhook-Ereignisse von Dodo Payments, um Ereignisse in Ihrer App auszulösen.

Integration:

import Hono from 'hono'
import { Webhooks } from '@dodopayments/hono'

const app = new Hono()
app.post(
  "/api/webhooks",
  Webhooks({
    webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
    onPayload: async (payload) => {
      // Payload hier verarbeiten
      console.log(payload)
    }
  })
);

Funktionen:

    Nur die POST-Methode ist erlaubt — andere geben 405 zurück

    Die Signaturverifizierung erfolgt mit webhookKey. Gibt 401 zurück, wenn ungültig.

    Zod-basierte Payload-Validierung. Gibt 400 zurück, wenn das Schema ungültig ist.

    Alle Handler sind asynchrone Funktionen.

Unterstützte Webhook-Ereignishandler:

Sie können einen der folgenden Handler übergeben:

    onPayload

    onPaymentSucceeded

    onPaymentFailed

    onPaymentProcessing

    onPaymentCancelled

    onRefundSucceeded

    onRefundFailed

    onDisputeOpened, onDisputeExpired, onDisputeAccepted, onDisputeCancelled, onDisputeChallenged, onDisputeWon, onDisputeLost

    onSubscriptionActive, onSubscriptionOnHold, onSubscriptionRenewed, onSubscriptionPlanChanged, onSubscriptionCancelled, onSubscriptionFailed, onSubscriptionExpired, onSubscriptionUpdated

    onLicenseKeyCreated

    onAbandonedCheckoutDetected, onAbandonedCheckoutRecovered

    onDunningStarted, onDunningRecovered

    onCreditAdded, onCreditDeducted, onCreditExpired, onCreditRolledOver, onCreditRolloverForfeited, onCreditOverageCharged, onCreditManualAdjustment, onCreditBalanceLow

Einrichten von Umgebungsvariablen:

Stellen Sie sicher, dass Sie diese Umgebungsvariablen in Ihrem Projekt definieren:

DODO_PAYMENTS_API_KEY=your-api-key
DODO_PAYMENTS_RETURN_URL=https://yourapp.com/success
DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
DODO_PAYMENTS_ENVIRONMENT="test_mode" oder "live_mode"

Verwenden Sie diese in Ihrem Code als:

process.env.DODO_PAYMENTS_API_KEY
process.env.DODO_PAYMENTS_WEBHOOK_KEY

Sicherheitshinweis: Geheimnisse nicht in die Versionskontrolle einfügen. Verwenden Sie lokal .env-Dateien und Secret-Manager in Bereitstellungsumgebungen (z.B. AWS, Vercel, Heroku, etc.).
```
