> ## 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.

# Fastify アダプタ

> Dodo Payments を Fastify アプリルーター プロジェクトに統合する方法を学びます。チェックアウト、カスタマーポータル、Webhook、および安全な環境設定をカバーします。

<CardGroup cols={2}>
  <Card title="Checkout Handler" icon="cart-shopping" href="#checkout-route-handler">
    Dodo Payments のチェックアウトを Fastify アプリに統合します。
  </Card>

  <Card title="Customer Portal" icon="user" href="#customer-portal-route-handler">
    顧客がサブスクリプションや詳細を管理できるようにします。
  </Card>

  <Card title="Webhooks" icon="bell" href="#webhook-route-handler">
    Dodo Payments の webhook イベントを受信して処理します。
  </Card>
</CardGroup>

## インストール

<Steps>
  <Step title="Install the package">
    Run the following command in your project root:

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

  <Step title="Set up environment variables">
    Create a <code>.env</code> file in your project root:

    ```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>
      Never commit your <code>.env</code> file or secrets to version control.
    </Warning>
  </Step>
</Steps>

## ルートハンドラーの例

<Info>
  All examples assume you are using the Fastify App Router.
</Info>

<Tabs>
  <Tab title="Checkout Handler">
    <Info>
      このハンドラを使用して Dodo Payments のチェックアウトを Fastify アプリに統合します。静的 (GET)、動的 (POST)、セッション (POST) の支払いフローに対応しています。
    </Info>

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

        const fastify = Fastify({})
        const checkoutGet = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'static'
        });

        const checkoutPost = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'dynamic'
        });

        const checkoutSession = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'session'
        });

        fastify.get('/api/checkout', checkoutGet.getHandler);
        fastify.post('/api/checkout', checkoutPost.postHandler);
        fastify.post('/api/checkout-session', checkoutSession.postHandler);
      ```
    </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-session \
      --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>
      このハンドラを使用して、Dodo Payments のカスタマーポータルから顧客がサブスクリプションや詳細を管理できるようにします。
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
      // route.ts
      import { CustomerPortal } from "@dodopayments/fastify";
      import Fastify from 'fastify'

      const fastify = Fastify({})
      const customerPortalHandler = CustomerPortal({
          bearerToken: process.env.DODO_PAYMENTS_API_KEY,
          environment: process.env.DODO_PAYMENTS_ENVIRONMENT
      });
      fastify.get('/api/customer-portal', customerPortalHandler);
      ```
    </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>
      このハンドラを使用して Fastify アプリで Dodo Payments の webhook イベントを安全に受信・処理します。
    </Info>

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

      const fastify = Fastify({})
      fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
          done(null, body)
      })

      fastify.post('/api/webhooks', Webhooks({
      webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
      onPayload: async (payload) => {
          // Handle Payload Here
          console.log(payload)
      }
      }));

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

## チェックアウトルートハンドラー

<Info>
  Dodo Payments はウェブサイトへの支払い統合のために 3 種類の支払いフローをサポートしており、このアダプターはすべての支払いフローに対応しています。
</Info>

* **静的支払いリンク:** すぐに共有可能な URL で、迅速かつノーコードでの支払い収集が可能です。
* **動的支払いリンク:** API または SDK を使用して、カスタム詳細を持つ支払いリンクをプログラムで生成します。
* **チェックアウトセッション:** 事前に設定された商品カートと顧客詳細を使用して、安全でカスタマイズ可能なチェックアウト体験を作成します。

<AccordionGroup>
  <Accordion title="Static Checkout (GET)">
    ### Supported Query Parameters

    <ParamField query="productId" type="string" required>
      商品識別子 (例: <code>?productId=pdt\_nZuwz45WAs64n3l07zpQR</code>)。
    </ParamField>

    <ParamField query="quantity" type="integer">
      商品の数量。
    </ParamField>

    <ParamField query="fullName" type="string">
      顧客のフルネーム。
    </ParamField>

    <ParamField query="firstName" type="string">
      顧客の名。
    </ParamField>

    <ParamField query="lastName" type="string">
      顧客の姓。
    </ParamField>

    <ParamField query="email" type="string">
      顧客のメールアドレス。
    </ParamField>

    <ParamField query="country" type="string">
      顧客の国。
    </ParamField>

    <ParamField query="addressLine" type="string">
      顧客の住所行。
    </ParamField>

    <ParamField query="city" type="string">
      顧客の市区町村。
    </ParamField>

    <ParamField query="state" type="string">
      顧客の州/都道府県。
    </ParamField>

    <ParamField query="zipCode" type="string">
      顧客の郵便番号。
    </ParamField>

    <ParamField query="disableFullName" type="boolean">
      フルネーム欄を無効化します。
    </ParamField>

    <ParamField query="disableFirstName" type="boolean">
      名欄を無効化します。
    </ParamField>

    <ParamField query="disableLastName" type="boolean">
      姓欄を無効化します。
    </ParamField>

    <ParamField query="disableEmail" type="boolean">
      メール欄を無効化します。
    </ParamField>

    <ParamField query="disableCountry" type="boolean">
      国欄を無効化します。
    </ParamField>

    <ParamField query="disableAddressLine" type="boolean">
      住所欄を無効化します。
    </ParamField>

    <ParamField query="disableCity" type="boolean">
      市区町村欄を無効化します。
    </ParamField>

    <ParamField query="disableState" type="boolean">
      州欄を無効化します。
    </ParamField>

    <ParamField query="disableZipCode" type="boolean">
      郵便番号欄を無効化します。
    </ParamField>

    <ParamField query="paymentCurrency" type="string">
      支払い通貨を指定します (例: <code>USD</code>)。
    </ParamField>

    <ParamField query="showCurrencySelector" type="boolean">
      通貨セレクターを表示します。
    </ParamField>

    <ParamField query="paymentAmount" type="integer">
      支払い額を指定します (例: \$10.00 の場合 <code>1000</code>)。
    </ParamField>

    <ParamField query="showDiscounts" type="boolean">
      割引欄を表示します。
    </ParamField>

    <ParamField query="metadata_*" type="string">
      <code>metadata\_</code> で始まるクエリパラメーターはすべてメタデータとして渡されます。
    </ParamField>

    <Warning>
      <code>productId</code> が欠けている場合、ハンドラは 400 レスポンスを返します。無効なクエリパラメータも 400 レスポンスとなります。
    </Warning>

    ### レスポンス形式

    静的チェックアウトは、チェックアウト URL を含む JSON レスポンスを返します:

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

  <Accordion title="Dynamic Checkout (POST)">
    * パラメータを POST リクエストの JSON ボディとして送信します。
    * 一回限りの支払いと継続課金の両方に対応しています。
    * 対応する POST ボディ項目の完全な一覧については、以下を参照してください:
      * [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)

    ### レスポンス形式

    動的チェックアウトは、チェックアウト URL を含む JSON レスポンスを返します:

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

  <Accordion title="Checkout Sessions (POST)">
    チェックアウトセッションはより安全なホスト型チェックアウト体験を提供し、一回限りの購入とサブスクリプションの両方に対して、完全なカスタマイズ制御で支払いフロー全体を処理します。

    詳細とサポートされているフィールドの完全なリストについては、[チェックアウトセッション統合ガイド](https://docs.dodopayments.com/developer-resources/checkout-session)を参照してください。

    ### レスポンス形式

    チェックアウトセッションは、チェックアウト URL を含む JSON レスポンスを返します:

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

## カスタマーポータルルートハンドラー

カスタマーポータルルートハンドラーを使用すると、Dodo Payments カスタマーポータルを Fastify アプリケーションにシームレスに統合できます。

### クエリパラメータ

<ParamField query="customer_id" type="string" required>
  ポータルセッションの顧客 ID (例: <code>?customer\_id=cus\_123</code>)。
</ParamField>

<ParamField query="send_email" type="boolean">
  <code>true</code> を指定すると、ポータルリンクを含むメールを顧客に送信します。
</ParamField>

<Warning>
  <code>customer\_id</code> が欠けている場合、400 を返します。
</Warning>

## Webhook ルートハンドラー

* **メソッド:** POST リクエストのみがサポートされています。他のメソッドは 405 を返します。
* **署名検証:** <code>webhookKey</code> を使用して Webhook 署名を検証します。検証に失敗した場合は 401 を返します。
* **ペイロード検証:** Zod で検証されます。無効なペイロードには 400 を返します。
* **エラーハンドリング:**
  * 401: 無効な署名
  * 400: 無効なペイロード
  * 500: 検証中の内部エラー
* **イベントルーティング:** ペイロードタイプに基づいて適切なイベントハンドラーを呼び出します。

### サポートされている Webhook イベントハンドラ

<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>

***

## LLM 用のプロンプト

```
あなたは専門の Fastify 開発者アシスタントです。あなたの仕事は、ユーザーが既存の Fastify プロジェクトに @dodopayments/fastify アダプタを統合する手助けをすることです。

@dodopayments/fastify アダプタは、Dodo Payments のチェックアウト、カスタマーポータル、および Webhook 機能のためのルートハンドラーを提供し、Fastify アプリに直接接続できるように設計されています。

まず、必要なパッケージをインストールします。ユーザーのプロジェクトに適したパッケージマネージャー (npm、yarn、または bun) を使用してください:

npm install @dodopayments/fastify

---

以下のように応答を構成してください:

1. ユーザーに統合したい機能を尋ねます。

"@dodopayments/fastify アダプタのどの部分をプロジェクトに統合したいですか？次の中から 1 つ以上を選択できます:

- チェックアウトルートハンドラー (商品チェックアウトの処理用)
- カスタマーポータルルートハンドラー (顧客のサブスクリプション/詳細の管理用)
- Webhook ルートハンドラー (Dodo Payments の Webhook イベントの受信用)
- すべて (3 つすべてを統合)"

---

2. ユーザーの選択に基づいて、各選択された機能の詳細な統合手順を提供します。

---

**チェックアウトルートハンドラーが選択された場合:**

**目的**: このハンドラーは、ユーザーを Dodo Payments のチェックアウトページにリダイレクトします。

**統合**:
Fastify アプリに静的 (GET) と動的 (POST) のチェックアウト用の 2 つのルートを作成します。

import { Checkout } from '@dodopayments/fastify';
import Fastify from 'fastify'

const fastify = Fastify({})
const checkoutGet = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'static'
});

const checkoutPost = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'dynamic'
});

const checkoutSession = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'session'
});

fastify.get('/api/checkout', checkoutGet.getHandler);
fastify.post('/api/checkout', checkoutPost.postHandler);
fastify.post('/api/checkout-session', checkoutSession.postHandler);

設定オプション:

    bearerToken: あなたの Dodo Payments API キー (DODO_PAYMENTS_API_KEY 環境変数に保存することを推奨)。

    returnUrl (オプション): チェックアウト成功後にユーザーをリダイレクトする URL。

    environment: "test_mode" または "live_mode"

    type: "static" (GET)、"dynamic" (POST)、または "session" (POST)

GET (静的チェックアウト) は次のクエリパラメータを期待します:

    productId (必須)

    quantity、顧客フィールド (fullName、email など)、およびメタデータ (metadata_*) はオプションです。

    戻り値: {"checkout_url": "https://checkout.dodopayments.com/..."}

POST (動的チェックアウト) は、支払い詳細 (一回限りまたはサブスクリプション) を含む JSON ボディを期待します。戻り値: {"checkout_url": "https://checkout.dodopayments.com/..."}。完全な POST スキーマについては、ドキュメントを参照してください:

    一回限りの支払い: https://docs.dodopayments.com/api-reference/payments/post-payments

    サブスクリプション: https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions

POST (チェックアウトセッション) - (推奨) よりカスタマイズ可能なチェックアウト体験。戻り値は JSON で checkout_url を含みます: パラメータは JSON ボディとして送信されます。一回限りの支払いと定期的な支払いの両方をサポートします。戻り値: {"checkout_url": "https://checkout.dodopayments.com/session/..."}。サポートされているフィールドの完全なリストについては、次を参照してください:

    チェックアウトセッション統合ガイド: https://docs.dodopayments.com/developer-resources/checkout-session

カスタマーポータルルートハンドラーが選択された場合:

目的: このルートは、顧客が Dodo Payments ポータルを介してサブスクリプションを管理できるようにします。

統合:

import { CustomerPortal } from "@dodopayments/fastify";
import Fastify from 'fastify'

const fastify = Fastify({})
const customerPortalHandler = CustomerPortal({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT
});
fastify.get('/api/customer-portal', customerPortalHandler);

クエリパラメータ:

    customer_id (必須): 例: ?customer_id=cus_123

    send_email (オプション): true の場合、顧客にポータルリンクがメールで送信されます。

customer_id が欠けている場合は 400 を返します。

Webhook ルートハンドラーが選択された場合:

目的: Dodo Payments からの受信 Webhook イベントを処理して、アプリ内のイベントをトリガーします。

統合:

import Fastify from 'fastify'
import { Webhooks } from '@dodopayments/fastify'

const fastify = Fastify({})
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
    done(null, body)
})

fastify.post('/api/webhooks', Webhooks({
  webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
  onPayload: async (payload) => {
    // ペイロードをここで処理
    console.log(payload)
  }
}));

機能:

    POST メソッドのみが許可されており、他は 405 を返します。

    署名検証は webhookKey を使用して行われます。無効な場合は 401 を返します。

    Zod ベースのペイロード検証。無効なスキーマの場合は 400 を返します。

    すべてのハンドラーは非同期関数です。

サポートされている Webhook イベントハンドラー:

次のいずれかのハンドラーを渡すことができます:

    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

環境変数のセットアップ：

プロジェクトでこれらの環境変数を定義してください：

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" または "live_mode"

コード内で以下のように使用します：

process.env.DODO_PAYMENTS_API_KEY
process.env.DODO_PAYMENTS_WEBHOOK_KEY

セキュリティノート：秘密情報をバージョン管理にコミットしないでください。ローカルでは .env ファイルを使用し、デプロイ環境ではシークレットマネージャー（例：AWS、Vercel、Heroku など）を使用してください。
```
