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

# x402 ステーブルコイン決済

> x402 プロトコルで AI エージェントからの USDC ステーブルコイン決済を受け入れる：加盟店ホスト型 402 と Waffo ホスト型の 2 つの統合モードの完全ガイド。

x402 は HTTP 402 ステータスコードに基づくオープンな決済プロトコルです。サーバーは未決済のリクエストに対して 402 challenge を返し、支払い側（通常は AI エージェント）はオンチェーンのステーブルコイン承認署名を付けてリクエストを再送し、決済完了後にリソースを取得します。Waffo は x402 を標準的な決済受け入れ機能として提供しており、注文・Webhook・照合は既存の Waffo 統合と完全に同一で、オンチェーンの検証と決済は Waffo が行います。

本ページは 2 種類の読者を対象としています。主対象は**加盟店開発者**（統合モードの選択、Waffo API の呼び出し、リソース提供の判定）です。**AI エージェント開発者**は 402 challenge の構造と `PAYMENT-SIGNATURE` の送信方法を中心にお読みください。エージェント側のやり取りに加盟店の API キーは不要です。

## 2 つの統合モード

<CardGroup cols={2}>
  <Card title="モード 1：加盟店ホスト型 402" icon="server">
    加盟店サーバー自身が x402 server として動作します。エージェントに 402 challenge を返し、署名を受け取り、`order/create` で署名を Waffo に引き渡して決済します。エージェントを自社 API 上に留めたい、x402 プロトコルの詳細を自前で実装できる加盟店に適しています。
  </Card>

  <Card title="モード 2：Waffo ホスト型 402" icon="cloud">
    加盟店は注文を作成し、Waffo が返すホスト型 URL をエージェントに渡すだけです。402 challenge、署名の受け取り、決済はすべて Waffo キャッシャーが行います。x402 プロトコルの詳細に触れず迅速にリリースしたい加盟店に適しています。
  </Card>
</CardGroup>

両モードは同一の [`order/create`](/docs/api-reference/order-create/create-new-order) エンドポイントを共用します。区別はただ一つ、リクエストの `x402Info` に **`paymentSignatureHeader` を含むかどうか**です。署名ありはモード 1、署名なしはモード 2 になります。

## 前提条件

<Note>
  x402 決済の受け入れには、Waffo 導入チームを通じて以下 2 点の開通が必要です。

  1. 加盟店契約で **CRYPTO / USDC 決済プロダクト**を有効化する
  2. Waffo 側で**オンチェーン受取パラメータ**を設定する

  設定が完了していない場合、`wallet/inquiry` と `order/create` はエラーコード `A0010`（加盟店契約で許可されていない操作）を返します。
</Note>

## 現在のサポート範囲

<Warning>
  以下は現行バージョンの確定した境界です。この前提で開発し、他の機能を想定しないでください。

  * **通貨**：`USDC` のみ。`orderCurrency` は必ず `USDC`（同一通貨での受け入れ、為替換算なし）
  * **ネットワーク**：Base のみ（本番は `eip155:8453`、サンドボックスは Base Sepolia `eip155:84532`）
  * **scheme**：`exact` のみ（challenge の金額どおりに決済）
  * **承認回数**：EIP-3009 の承認はオンチェーンで 1 回のみ消費されます。1 つの署名で決済できるのは 1 回だけで、「1 回の承認で複数回請求」はサポートされません
  * **冪等性**：`paymentRequestId` は必須です。同一注文への `order/create` 再実行は既存注文の実際のステータスを返し、再決済は行われません（[冪等性](/docs/ja/developer-docs/core-concepts/idempotency)を参照）
</Warning>

## オンチェーン受取パラメータの取得

モード 1 で 402 challenge を構築する前に、[`POST /api/v1/wallet/inquiry`](/docs/api-reference/wallet-inquiry/wallet-inquiry) で受取パラメータを取得します。このエンドポイントは照会のみで、注文の作成も金額の検証も行いません。

<CodeGroup>
  ```bash リクエスト theme={null}
  curl -X POST https://api-sandbox.waffo.com/api/v1/wallet/inquiry \
    -H "Content-Type: application/json" \
    -H "X-API-KEY: YOUR_API_KEY" \
    -H "X-SIGNATURE: YOUR_RSA_SIGNATURE" \
    -d '{
      "paymentRequestId": "x402-order-10001",
      "merchantInfo": { "merchantId": "M000001" },
      "orderCurrency": "USDC"
    }'
  ```

  ```json レスポンス theme={null}
  {
    "code": "0",
    "msg": "Success",
    "data": {
      "network": "eip155:84532",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "payTo": "0xc15Ea3D0b7A29c41F8b26aD5c30F49E20e510e71"
    }
  }
  ```
</CodeGroup>

| フィールド     | 説明                                                                                                  |
| --------- | --------------------------------------------------------------------------------------------------- |
| `network` | CAIP-2 ネットワーク識別子。サンドボックスは Base Sepolia `eip155:84532`、本番は Base メインネット `eip155:8453` を返します           |
| `asset`   | USDC トークンのコントラクトアドレス（環境とネットワークにより異なり、本番の Base メインネットは `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`） |
| `payTo`   | Waffo プラットフォームの受取アドレス。Waffo がオンチェーンで受け取り、契約に基づいて加盟店に精算します                                           |

<Note>
  3 つのフィールドはいずれも Waffo の設定値です。challenge の構築にはそのまま使用してください。`payTo` を自社のウォレットアドレスに置き換えてはいけません。エージェントの署名内の受取アドレスと金額は、決済前にオンチェーンで厳密に検証されます。
</Note>

## モード 1：加盟店ホスト型 402

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant A as AI エージェント
    participant M as 加盟店サーバー
    participant W as Waffo
    participant B as Base チェーン

    A->>M: 有料リソースをリクエスト
    M->>W: POST /api/v1/wallet/inquiry
    W-->>M: network / asset / payTo
    M-->>A: HTTP 402（challenge は JSON body）
    A->>A: EIP-3009 承認に署名
    A->>M: PAYMENT-SIGNATURE を付けて元のリクエストを再送
    M->>W: POST /api/v1/order/create（x402Info.paymentSignatureHeader）
    W->>B: verify + settle（オンチェーン送金）
    B-->>W: トランザクション結果（txHash）
    W-->>M: orderStatus（PAY_SUCCESS 時は x402Response 付き）
    alt orderStatus = PAY_SUCCESS
        M-->>A: 200 + リソース + PAYMENT-RESPONSE
    else orderStatus = PAY_IN_PROGRESS
        M-->>A: 202 処理中。Webhook / inquiry の確定後に提供
    else orderStatus = ORDER_CLOSE
        M-->>A: 決済失敗。リソースは提供しない
    end
```

加盟店側で行うことは 4 つです。

1. `wallet/inquiry` で `network` / `asset` / `payTo` を取得し、価格設定に基づいて 402 challenge を構築（金額はアトミック単位、`scheme` は `exact` 固定）してエージェントに返す
2. エージェントの再送リクエストヘッダー `PAYMENT-SIGNATURE` から署名を取り出し、**そのまま** `order/create` の `x402Info.paymentSignatureHeader` に設定する（デコードして再構築しない）
3. 同期レスポンスの `orderStatus` で提供可否を判定する：`PAY_SUCCESS` は提供、`PAY_IN_PROGRESS` は [Webhook](/docs/ja/developer-docs/webhook/overview) または [`order/inquiry`](/docs/api-reference/order-inquiry/order-inquiry) の最終ステータスを待つ、`ORDER_CLOSE` は拒否
4. 提供時にレスポンスの `x402Info.x402Response` を `PAYMENT-RESPONSE` ヘッダーとしてエージェントに返す。これが x402 準拠の決済レシートです

<CodeGroup>
  ```bash リクエスト theme={null}
  curl -X POST https://api-sandbox.waffo.com/api/v1/order/create \
    -H "Content-Type: application/json" \
    -H "X-API-KEY: YOUR_API_KEY" \
    -H "X-SIGNATURE: YOUR_RSA_SIGNATURE" \
    -d '{
      "paymentRequestId": "x402-order-10001",
      "merchantOrderId": "x402-order-10001",
      "orderCurrency": "USDC",
      "orderAmount": "9.99",
      "orderDescription": "API usage credits",
      "notifyUrl": "https://merchant.example.com/webhook/waffo",
      "merchantInfo": { "merchantId": "M000001" },
      "userInfo": { "userId": "agent_7f3e", "userTerminal": "WEB" },
      "paymentInfo": { "productName": "ONE_TIME_PAYMENT", "payMethodName": "USDC" },
      "x402Info": {
        "x402Request": true,
        "paymentSignatureHeader": "eyJ4NDAyVmVyc2lvbiI6Miwic2NoZW1lIjoiZXhhY3QiLC4uLn0="
      }
    }'
  ```

  ```json レスポンス（決済成功） theme={null}
  {
    "code": "0",
    "msg": "Success",
    "data": {
      "paymentRequestId": "x402-order-10001",
      "merchantOrderId": "x402-order-10001",
      "acquiringOrderId": "A202607060001",
      "orderStatus": "PAY_SUCCESS",
      "x402Info": {
        "x402Request": true,
        "paymentSignatureHeader": "eyJ4NDAyVmVyc2lvbiI6Miwic2NoZW1lIjoiZXhhY3QiLC4uLn0=",
        "x402Response": "eyJzdWNjZXNzIjp0cnVlLCJ0cmFuc2FjdGlvbiI6IjB4Li4uIn0="
      }
    }
  }
  ```
</CodeGroup>

その他の必須フィールド（`goodsInfo`、`orderRequestedAt` など）は通常のワンタイム決済の注文作成と同一です。[API Reference](/docs/api-reference/ja/introduction) を参照してください。

`paymentSignatureHeader` は base64 エンコードされた x402 PaymentPayload です。デコード後の構造は以下のとおりです（エージェント側の x402 SDK が生成するため、加盟店が構築する必要はありません）。

```json theme={null}
{
  "x402Version": 2,
  "scheme": "exact",
  "network": "eip155:84532",
  "payload": {
    "signature": "0x<65 バイトの EIP-712 署名>",
    "authorization": {
      "from": "0x<エージェントのウォレットアドレス>",
      "to": "0xc15Ea3D0b7A29c41F8b26aD5c30F49E20e510e71",
      "value": "9990000",
      "validAfter": "0",
      "validBefore": "1783340000",
      "nonce": "0x<32 バイトのランダム nonce（リプレイ防止、非連番）>"
    }
  }
}
```

<Warning>
  署名内の `authorization.to` は `wallet/inquiry` が返した `payTo` と一致し、`authorization.value` は `orderAmount` のアトミック単位表現と一致しなければなりません（換算ルールは後述の「金額と小数位」を参照）。いずれかが不一致の場合、決済前の検証で失敗し、注文は `ORDER_CLOSE` になります。したがって 402 challenge でエージェントに提示する価格は `order/create` の `orderAmount` と一致している必要があります。
</Warning>

`x402Response` は base64 エンコードされた決済レシート（x402 SettlementResponse）で、`orderStatus = PAY_SUCCESS` の場合のみ返されます。デコード後：

```json theme={null}
{
  "success": true,
  "transaction": "0x8f4e2b7c9d1a4f6e8b3c5d7a9e1f2b4c6d8e0a2c4e6f8a0b2c4d6e8f0a1b3c5d",
  "network": "eip155:84532",
  "payer": "0x51E2aF03D0A5c3C7dF83Db9F4b0a2E51D8c19aC3"
}
```

`transaction` はオンチェーンのトランザクションハッシュで、照合とオンチェーン検証に使用できます。`payer` はエージェントの支払いウォレットアドレスです。

## モード 2：Waffo ホスト型 402

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant A as AI エージェント
    participant M as 加盟店サーバー
    participant W as Waffo API
    participant C as Waffo キャッシャー

    A->>M: 有料リソースをリクエスト
    M->>W: POST /api/v1/order/create（x402Request=true、署名なし）
    W-->>M: AUTHORIZATION_REQUIRED + orderAction.webUrl
    M-->>A: HTTP 302 Location: webUrl
    A->>C: GET webUrl（ホスト型 x402 エンドポイント）
    C-->>A: HTTP 402（challenge は JSON body）
    A->>A: EIP-3009 承認に署名
    A->>C: PAYMENT-SIGNATURE を付けて同一 URL に再送
    C->>W: 署名を送信し、オンチェーンの verify + settle を実行
    W-->>C: orderStatus
    C-->>A: HTTP 302（successRedirectUrl / failedRedirectUrl）
    W--)M: Webhook で最終ステータスを通知（PAY_SUCCESS 時は x402Response 付き）
    M-->>A: PAY_SUCCESS を確認後にリソースを提供
```

加盟店側で行うことは 3 つです。

1. `order/create` に `x402Info: { "x402Request": true }`（署名なし）と `successRedirectUrl` / `failedRedirectUrl` を設定する
2. レスポンスの `orderAction`（JSON 文字列）を解析して `webUrl` を取り出し、エージェントを 302 リダイレクトする。以降の 402 challenge、署名の受け取り、決済はすべて Waffo キャッシャー側で行われます
3. [Webhook](/docs/ja/developer-docs/webhook/overview) または `order/inquiry` が返す `orderStatus` に基づいてリソースを提供する

<CodeGroup>
  ```bash リクエスト theme={null}
  curl -X POST https://api-sandbox.waffo.com/api/v1/order/create \
    -H "Content-Type: application/json" \
    -H "X-API-KEY: YOUR_API_KEY" \
    -H "X-SIGNATURE: YOUR_RSA_SIGNATURE" \
    -d '{
      "paymentRequestId": "x402-order-10002",
      "merchantOrderId": "x402-order-10002",
      "orderCurrency": "USDC",
      "orderAmount": "9.99",
      "orderDescription": "API usage credits",
      "notifyUrl": "https://merchant.example.com/webhook/waffo",
      "successRedirectUrl": "https://merchant.example.com/x402/return",
      "failedRedirectUrl": "https://merchant.example.com/x402/failed",
      "merchantInfo": { "merchantId": "M000001" },
      "userInfo": { "userId": "agent_7f3e", "userTerminal": "WEB" },
      "paymentInfo": { "productName": "ONE_TIME_PAYMENT", "payMethodName": "USDC" },
      "x402Info": { "x402Request": true }
    }'
  ```

  ```json レスポンス theme={null}
  {
    "code": "0",
    "msg": "Success",
    "data": {
      "paymentRequestId": "x402-order-10002",
      "merchantOrderId": "x402-order-10002",
      "acquiringOrderId": "A202607060002",
      "orderStatus": "AUTHORIZATION_REQUIRED",
      "orderAction": "{\"actionType\":\"WEB\",\"webUrl\":\"https://cashier.waffo.com/cashier/api/v1/x402/7sKq9WfR2mXt\"}"
    }
  }
  ```
</CodeGroup>

エージェントが `webUrl` にアクセスすると HTTP 402 を受け取ります。challenge は**レスポンスボディ**にあります（x402 プロトコルでは challenge はボディに置かれ、専用のレスポンスヘッダーはありません）。

```json theme={null}
{
  "x402Version": 2,
  "error": "PAYMENT-SIGNATURE header is required",
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:84532",
      "maxAmountRequired": "9990000",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "payTo": "0xc15Ea3D0b7A29c41F8b26aD5c30F49E20e510e71",
      "maxTimeoutSeconds": 600,
      "extra": { "name": "USDC", "version": "2" }
    }
  ]
}
```

署名後、エージェントは**初回アクセスと同じ HTTP メソッド**で同一 URL に再送し、署名を `PAYMENT-SIGNATURE` リクエストヘッダー（x402 仕様の `X-PAYMENT` に相当）に設定します。加盟店の認証情報は一切不要です。

```bash theme={null}
curl "https://cashier.waffo.com/cashier/api/v1/x402/7sKq9WfR2mXt" \
  -H "PAYMENT-SIGNATURE: eyJ4NDAyVmVyc2lvbiI6Miwic2NoZW1lIjoiZXhhY3QiLC4uLn0="
```

決済完了後、キャッシャーは 302 でエージェントを加盟店の `successRedirectUrl` または `failedRedirectUrl` に戻します。ホスト型 URL はブラウザアクセス（チェックアウトページを表示）と x402 クライアントアクセス（プロトコルレスポンスを返す）の両方に対応しています。

<Warning>
  302 リダイレクトはフローの接続のためだけのもので、**支払いの証明ではありません**。「支払い済み」の判定は、Webhook 通知または `order/inquiry` で確認した `orderStatus = PAY_SUCCESS` のみに基づいてください。リダイレクトは偽造・消失の可能性があり、リダイレクト時点では決済が確定していないこともあります。
</Warning>

決済成功後、Webhook 通知と `order/inquiry` レスポンスには `x402Info.x402Response`（構造はモード 1 と同一）が付加されます。それ以外の通知構造は通常の注文と同じです。[Webhook イベントタイプ](/docs/ja/developer-docs/webhook/event-types)を参照してください。

## モード比較

| 項目                             | モード 1：加盟店ホスト型 402                           | モード 2：Waffo ホスト型 402                |
| ------------------------------ | ------------------------------------------- | ----------------------------------- |
| x402 server の役割（402 の発行、署名の受領） | 加盟店サーバー                                     | Waffo キャッシャー                        |
| x402 プロトコル詳細の実装が必要か            | 必要（challenge 構築、署名ヘッダーの解析）                  | 不要                                  |
| `order/create` に署名を含むか         | 含む（`x402Info.paymentSignatureHeader`）       | 含まない                                |
| 注文作成レスポンス                      | 最終ステータスまたは `PAY_IN_PROGRESS` を直接返す          | `AUTHORIZATION_REQUIRED` + ホスト型 URL |
| リダイレクト                         | なし（エージェントは終始加盟店 API と通信）                    | 加盟店 302 → キャッシャー 302 で戻る            |
| リソース提供の判定基準                    | 同期レスポンス / Webhook / inquiry の `orderStatus` | Webhook / inquiry の `orderStatus`   |
| 適した加盟店                         | x402 サービスを自前で構築し深くカスタマイズしたい場合               | プロトコル詳細に触れず迅速にリリースしたい場合             |

注文ステータスの意味（`PAY_IN_PROGRESS`、`AUTHORIZATION_REQUIRED` など）は他の決済手段と共通です。[決済ライフサイクル](/docs/ja/developer-docs/core-concepts/payment-lifecycle)を参照してください。

## 金額と小数位（2 層の単位）

同一の取引に 2 層の金額表現があります。混同しないでください。

| 層                    | フィールド                       | 表現方式                                   | 例（9.99 USDC） |
| -------------------- | --------------------------- | -------------------------------------- | ------------ |
| Waffo API 層          | `orderAmount`               | String、小数 2 桁まで                        | `"9.99"`     |
| オンチェーン / x402 プロトコル層 | `value`、`maxAmountRequired` | String、アトミック単位の整数（USDC のオンチェーン精度は 6 桁） | `"9990000"`  |

換算ルール：アトミック単位 = 金額 × 10<sup>6</sup>。[通貨と金額](/docs/ja/developer-docs/core-concepts/currency)における USDC の小数 2 桁は Waffo API 層の `orderAmount` を指します。402 challenge と EIP-3009 署名内の金額は常にアトミック単位です。モード 1 では両層の金額が同一の値を表す必要があり、不一致の場合は決済検証で失敗します。

## エラーコード

x402 は Waffo の既存の外部エラーコードを再利用します。`msg` に具体的な理由が示されます。

| コード     | 意味               | x402 での主な発生原因                                               |
| ------- | ---------------- | ----------------------------------------------------------- |
| `A0003` | パラメータ検証失敗        | challenge / 署名の scheme が `exact` でない。`paymentRequestId` の欠落 |
| `A0007` | サポートされない取引通貨     | `orderCurrency` が `USDC` でない。または利用可能な同一通貨 USDC 契約がない        |
| `A0010` | 加盟店契約で許可されていない操作 | CRYPTO/USDC 決済プロダクトが未開通、またはオンチェーン受取パラメータが未設定                |

完全な一覧は[エラーコードリファレンス](/docs/ja/developer-docs/tools-and-references/developer-tools/error-codes)を参照してください。

## よくある質問

<AccordionGroup>
  <Accordion title="サンドボックス環境はどのチェーンを使いますか？">
    サンドボックスは Base Sepolia テストネット（`eip155:84532`）で、USDC コントラクトアドレスは `0x036CbD53842c5426634e7929541eC2318f3dCF7e` です。本番は Base メインネット（`eip155:8453`）で、USDC コントラクトアドレスは `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` です。どちらの環境でも `network` / `asset` / `payTo` は `wallet/inquiry` の実際の返り値に従ってください。
  </Accordion>

  <Accordion title="他の通貨やネットワークはサポートされますか？">
    現在は USDC + Base ネットワークのみです。`orderCurrency` に他の通貨を指定すると `A0007` が返ります。
  </Accordion>

  <Accordion title="1 回の承認で複数回請求できますか？">
    できません。x402 の `exact` scheme は EIP-3009 `transferWithAuthorization` に基づいており、その nonce は USDC コントラクト側で 1 回のみ消費されます。署名は一度決済されると無効になり、再送信はオンチェーンで直接失敗します。サブスクリプション型や従量制の複数回請求は x402 の対象範囲外です。
  </Accordion>

  <Accordion title="orderStatus が PAY_IN_PROGRESS のとき、先にリソースを提供してもよいですか？">
    いけません。`PAY_IN_PROGRESS` はオンチェーン処理中を意味するだけで、最終的に成功も失敗もあり得ます。リソースを提供できるのは `orderStatus = PAY_SUCCESS` のみで、最終ステータスは Webhook または `order/inquiry` で確定します。
  </Accordion>

  <Accordion title="402 challenge はレスポンスヘッダーとボディのどちらにありますか？">
    レスポンスボディ（JSON）にあります。challenge を運ぶヘッダーはありません。x402 のやり取りにおける唯一のプロトコルリクエストヘッダーは、エージェントが署名を送信する `PAYMENT-SIGNATURE`（x402 仕様の `X-PAYMENT` に相当）です。決済レシートは `x402Info.x402Response` フィールドで返され、仕様の `X-PAYMENT-RESPONSE` に相当します。
  </Accordion>

  <Accordion title="「AI 統合ツール（waffo-integrate）」と同じものですか？">
    違います。[AI 統合ツール](/docs/ja/developer-docs/integration/ai-integration)は AI コーディングツールで Waffo SDK の統合コードを生成するものです。本ページは AI エージェントが**支払い側**としてステーブルコインで加盟店のサービスを購入する仕組みです。併用できますが、解決する課題は異なります。
  </Accordion>
</AccordionGroup>

## 関連ドキュメント

* [決済ライフサイクル](/docs/ja/developer-docs/core-concepts/payment-lifecycle)：注文ステートマシンと最終ステータスの確定
* [通貨と金額](/docs/ja/developer-docs/core-concepts/currency)：金額フォーマットと小数位ルール
* [冪等性](/docs/ja/developer-docs/core-concepts/idempotency)：`paymentRequestId` の冪等性セマンティクス
* [Webhook 概要](/docs/ja/developer-docs/webhook/overview)：署名検証とリトライポリシー
* [API Reference](/docs/api-reference/ja/introduction)：[`order/create`](/docs/api-reference/order-create/create-new-order)、[`order/inquiry`](/docs/api-reference/order-inquiry/order-inquiry)、[`wallet/inquiry`](/docs/api-reference/wallet-inquiry/wallet-inquiry) の完全なフィールド定義
