{
  "lang": "ja",
  "ページ": "https://x402-catalog-history.ai-business-surface.workers.dev/ja/x402-billing-implementation",
  "title": "x402 課金 実装 — 402 に何を書き、どこで無料で止めるか（3経路の実測）",
  "h1": "x402 課金 実装 — 402 に何を書き、どこで無料で止めるか（3経路の実測）",
  "description": "x402 の課金を実装するとき、402 に何を書くかを実測しました。2026-10-19 時点で /openapi.json は 200・159,606 B・54 paths、/product.json は 200・627,189 B・45有料経路・9種類の価格（0.001〜3 USDC）、/ja は 200・67,842 B。未払いGETの /price は 402・28,113 B・0.02 USDC（ヘッダ 6,888 B）、/gas?chains=base,eth は 402・21,774 B・0.001 USDC（5,464 B）、/check は 402・28,091 B・0.05 USDC（5,664 B）。本文は x402Version=1・accepts[0] 10項目、ヘッダは x402Version=2。形式エラーは 400・271 B で課金前に返り、402 本文の約104分の1でした。",
  "検索語": "x402 課金 実装 / x402 billing implementation",
  "読者の問い": "x402 の課金を自分で実装したい。402 に何を書き、価格をどこに置き、どこで無料で止めれば、買い手のクライアントに読まれるのか。",
  "実測日": "2026-10-19 JST",
  "実測": {
    "caption": "x402 課金実装の実測（2026-10-19 JST・公開URL・支払いなしGET・各1回）",
    "columns": [
      "面",
      "条件",
      "応答",
      "本文",
      "価格",
      "読み取れること"
    ],
    "rows": [
      [
        "/openapi.json",
        "無料",
        "200",
        "159,606 B",
        "0",
        "54 paths"
      ],
      [
        "/product.json",
        "無料",
        "200",
        "627,189 B",
        "0",
        "45有料経路・9価格帯"
      ],
      [
        "/ja",
        "無料（HTML）",
        "200",
        "67,842 B",
        "0",
        "日本語の入口"
      ],
      [
        "/gas?chains=base,eth",
        "未払い",
        "402",
        "21,774 B",
        "0.001 USDC",
        "ヘッダ 5,464 B"
      ],
      [
        "/price",
        "未払い",
        "402",
        "28,113 B",
        "0.02 USDC",
        "ヘッダ 6,888 B"
      ],
      [
        "/check",
        "未払い",
        "402",
        "28,091 B",
        "0.05 USDC",
        "ヘッダ 5,664 B"
      ],
      [
        "/check?url=not-a-url",
        "形式エラー",
        "400",
        "271 B",
        "0",
        "課金前に拒否"
      ]
    ],
    "note": "3本の402は本文 x402Version=1・accepts[0] 10項目、レスポンスヘッダの payment-required は x402Version=2。価格は本文 maxAmountRequired が atomic 整数（0.02 = 20000、0.001 = 1000、0.05 = 50000）、ヘッダ accepts[0].amount も同じ値でした。応答は curl の実測で 0.44〜0.54 秒（各1回）。"
  },
  "見出し": [
    "結論: 課金実装は3点に分かれる",
    "実測: 無料3面と402 3経路",
    "402 に書くもの: 本文11キー・accepts 10項目",
    "無料で止める境界を先に作る",
    "価格表と実装を一致させる",
    "未確認"
  ],
  "本文": [
    {
      "見出し": "結論: 課金実装は3点に分かれる",
      "html": "<p>x402 の課金実装で決めることは、<strong>「402 を返す」だけではありません</strong>。①<strong>価格をどこに宣言するか</strong>、②<strong>未払いのときに何を返すか</strong>、③<strong>課金しない境界をどこに置くか</strong>の3点です。当方の公開URLを 2026-10-19 に実測すると、無料3面は合計 <strong>854,637 B</strong> で支払い0、有料3経路の402は本文合計 <strong>77,978 B</strong>・ヘッダ合計 <strong>18,016 B</strong> でした。</p><p>価格は <strong>0.001〜0.05 USDC</strong> の範囲で、/gas が 0.001、/price が 0.02、/check が 0.05。<strong>同じ価格を本文（V1・atomic 整数）とヘッダ（V2）の両方に置く</strong>のが実装の要点で、本文だけ・ヘッダだけでは買い手のクライアントによっては読めません。</p>"
    },
    {
      "見出し": "実測: 無料3面と402 3経路",
      "html": "<table>\n<thead><tr><th>面</th><th>条件</th><th>応答</th><th>本文</th><th>価格</th><th>読み取れること</th></tr></thead>\n<tbody>\n<tr><td><code>/openapi.json</code></td><td>無料</td><td>200</td><td>159,606 B</td><td>0</td><td>54 paths</td></tr>\n<tr><td><code>/product.json</code></td><td>無料</td><td>200</td><td>627,189 B</td><td>0</td><td>45有料経路・9価格帯</td></tr>\n<tr><td><code>/ja</code></td><td>無料（HTML）</td><td>200</td><td>67,842 B</td><td>0</td><td>日本語の入口</td></tr>\n<tr><td><code>/gas?chains=base,eth</code></td><td>未払い</td><td>402</td><td>21,774 B</td><td>0.001 USDC</td><td>ヘッダ 5,464 B</td></tr>\n<tr><td><code>/price</code></td><td>未払い</td><td>402</td><td>28,113 B</td><td>0.02 USDC</td><td>ヘッダ 6,888 B</td></tr>\n<tr><td><code>/check</code></td><td>未払い</td><td>402</td><td>28,091 B</td><td>0.05 USDC</td><td>ヘッダ 5,664 B</td></tr>\n<tr><td><code>/check?url=not-a-url</code></td><td>形式エラー</td><td>400</td><td>271 B</td><td>0</td><td>課金前に拒否</td></tr>\n</tbody>\n</table>\n<p class=\"facts\">応答時間は curl で /price 0.524 秒、/gas 0.443 秒、/check 0.536 秒（各1回・同時刻ではない）。</p>"
    },
    {
      "見出し": "402 に書くもの: 本文11キー・accepts 10項目",
      "html": "<p>未払いGETの402本文は、3経路とも<strong>同じ11のトップレベルキー</strong>を持っていました: <code>price</code> <code>x402Version</code> <code>error</code> <code>accepts</code> <code>resource</code> <code>extensions</code> <code>payment_required_v2</code> <code>receive</code> <code>what_you_get</code> <code>try_before_you_pay</code> <code>terms</code>。<code>accepts[0]</code> は<strong>10項目</strong>で、価格は <code>maxAmountRequired</code> に <strong>atomic 整数</strong>で入ります。</p><ul><li><strong>0.001 USDC</strong> → <code>maxAmountRequired=1000</code>（/gas）</li><li><strong>0.02 USDC</strong> → <code>maxAmountRequired=20000</code>（/price）</li><li><strong>0.05 USDC</strong> → <code>maxAmountRequired=50000</code>（/check）</li></ul><p>レスポンスヘッダの <code>payment-required</code> は<strong>x402Version=2</strong> で、<code>accepts[0].amount</code> が本文と同じ <strong>20000</strong> でした。<strong>本文のキー名は maxAmountRequired、ヘッダは amount</strong> と違うので、実装では<strong>同じ値を両方に出す</strong>関数を1つにまとめるのが安全です。</p><p>402本文は 21,774〜28,113 B と大きめです。これは<code>what_you_get</code> <code>try_before_you_pay</code> <code>terms</code> まで含むためで、<strong>買い手は払わずに納品内容と無料の試し方を読めます</strong>。実装では「402＝エラー」ではなく<strong>商品説明つきの見積もり</strong>として設計します。</p>"
    },
    {
      "見出し": "無料で止める境界を先に作る",
      "html": "<p>課金実装で見落としやすいのが<strong>不正な入力を402より前に返す</strong>ことです。<code>/check?url=not-a-url</code> は <strong>400・271 B</strong> で返り、402本文 <strong>28,091 B</strong> の<strong>約104分の1</strong>でした。上流呼び出しも課金も起きないので、<strong>形式エラーは無料</strong>にするのが自然です。</p><p>一方で <code>/price?pair=nope</code> は <strong>402</strong> でした。つまり<strong>入力の検証は経路ごとに違います</strong>。「この経路は無料で止まる」と決め打ちせず、<strong>実装した経路ごとに 400 を返す条件を1つずつ決める</strong>のが安全です。当方の実測では、/check はURL形式を課金前に見ますが、/price はパラメータの妥当性を課金前に見ていません。</p>"
    },
    {
      "見出し": "価格表と実装を一致させる",
      "html": "<p>無料の <code>/product.json</code> は <strong>627,189 B・45有料経路</strong>を持ち、価格は <strong>9種類</strong>でした: <strong>0.001 / 0.002 / 0.003 / 0.005 / 0.01 / 0.02 / 0.05 / 0.25 / 3 USDC</strong>。3経路の402と突き合わせると、/gas 0.001・/price 0.02・/check 0.05 は<strong>一致</strong>しています。</p><p>実装では、<strong>価格の正本を1か所（定数）に置き、402本文・ヘッダ・product.json を同じ値から生成する</strong>のがよいです。当方の <code>/openapi.json</code> は <strong>54 paths</strong> で、402 の形もここから読めます。<strong>価格を変えたときに3か所のどれかが古い</strong>のが典型的な事故なので、<strong>デプロイ時に3か所を突き合わせるテスト</strong>を1本置きます。</p>"
    },
    {
      "見出し": "未確認",
      "html": "<p><strong>支払い後の200本文は取得していません</strong>（支払い・SMS・KYCを伴う操作はしない制約）。したがって<strong>納品の中身・鮮度・返金・失敗時の再試行</strong>は未確認です。数字はすべて「402が返るところ、無料の200が返るところ」までの実測で、<strong>product.json の45経路と価格は宣言値</strong>であり、45本の402と1本ずつ突き合わせたわけではありません。</p><p>実装の最小構成は <a href=\"https://x402-catalog-history.ai-business-surface.workers.dev/ja/x402-implementation-example\"><code>/ja/x402-implementation-example</code></a>、買い手側の順序は <a href=\"https://x402-catalog-history.ai-business-surface.workers.dev/ja/x402-usage\"><code>/ja/x402-usage</code></a>、価格の相場は <a href=\"https://x402-catalog-history.ai-business-surface.workers.dev/ja/price-benchmark\"><code>/ja/price-benchmark</code></a> に実測でまとめています。仕様の全体は無料の <a href=\"https://x402-catalog-history.ai-business-surface.workers.dev/openapi.json\"><code>/openapi.json</code></a>（54 paths）で読めます。</p>"
    }
  ],
  "一覧": "https://x402-catalog-history.ai-business-surface.workers.dev/ja"
}
