# x402 決済

マシン間決済に x402 を使用します。

アプリの[完全なソースコード](https://github.com/stripe-samples/machine-payments)は GitHub で確認できます。

[x402](https://x402.org) はインターネット決済のプロトコルです。クライアントが有料リソースをリクエストすると、サーバーは Stripe の入金アドレスを含む決済の詳細とともに HTTP `402` レスポンスを返します。クライアントは支払いを行い、オーソリを使用してリクエストを再試行します。ファシリテーターがオンチェーンで決済を確定した後、Stripe はそれを [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) として記録します。この機能は、ニューヨーク州を除く米国の全州および[30 カ国以上](https://docs.stripe.com/payments/machine.md)に物理的な拠点を持つビジネスにご利用いただけます。

> ステーブルコインでの支払いと並行してカード決済を受け付けるには、[Machine Payments Protocol (MPP)](https://docs.stripe.com/payments/machine/mpp.md) を実装する必要があります。

## Before you begin

> ステーブルコインによる支払いは、ニューヨーク州を除くアメリカの全州のビジネスで利用できます。アメリカ国外で事業を展開しているビジネスの場合は、[machine-payments@stripe.com](mailto:machine-payments@stripe.com) 宛てに Stripe アカウント ID を添えてメールを送信し、30 カ国以上でのステーブルコインによる支払いへのアクセスをリクエストしてください。

ステーブルコイン決済の受け付けを開始するには、以下のようにします:

1. [Stripe アカウントを設定](https://dashboard.stripe.com/register)していることを確認してください。
2. ダッシュボードの[決済手段](https://dashboard.stripe.com/settings/payment_methods)の設定に移動し、**ステーブルコインと暗号資産**の決済手段をリクエストします。[マシン決済](https://docs.stripe.com/payments/machine.md)についてのみステーブルコインまたは暗号資産による支払いを受け付ける場合は、マシン決済専用の個別の[決済手段の設定](https://docs.stripe.com/payments/payment-method-configurations.md)を作成します。
3. Stripe はアクセスリクエストを審査し、必要に応じてさらなる詳細のご提供をお願いする場合があります。リクエストが審査されている間、当該決済手段は **保留中** と表示されます。
4. リクエストが承認されると、ダッシュボードで **ステーブルコインおよび暗号資産** という決済手段が有効になります。

## 決済ライフサイクル

このガイドではサーバーを構築します。サーバーは支払いが必要であることを示し、支払いが成功した後にコンテンツを返します。支払いを完了するために、Stripe およびファシリテーターと連携します。

クライアント、サーバー、ファシリテーター、および Stripe 間の x402 決済フローを示す図 (See full diagram at https://docs.stripe.com/payments/machine/x402)

```text
[クライアント] -- 支払いなしで有料リソースをリクエスト --> [サーバー]
[サーバー] -- 支払い要件と入金アドレスが含まれた HTTP 402 --> [クライアント]
[クライアント] -- 署名済みの支払い承認を付与してリクエストを再試行 --> [サーバー]
[サーバー] -- 支払いの確認 --> [ファシリテーター]
[ファシリテーター] -- オンチェーンで取引を決済確定する --> [ファシリテーター]
[ファシリテーター] -- 支払いが確認される --> [サーバー]
[サーバー] -- transaction_verification を使用する POST /v1/payment_intents --> [Stripe]
[Stripe] -- 確定済みの PaymentIntent を返す --> [サーバー]
[サーバー] -- リクエストされたリソースを返す --> [クライアント]
```

## コーディングエージェントを使用する

コーディングエージェントへの単一のプロンプトで、x402 を使用する API を構築できます:

```bash
Read https://docs.stripe.com/payments/machine/x402.md?lang=node, and create an API that uses x402 to charge for access using the Base network for crypto.
```

以下のステップバイステップガイドもご参照ください。

## Coinbase 開発者アカウントを作成する

x402 メインネットの決済は、Coinbase 開発者プラットフォーム (CDP) のファシリテーターを通じて確定されます。[Coinbase 開発者プラットフォームアカウント](https://portal.cdp.coinbase.com/)に登録し、API キーを作成してファシリテータークライアントを認証します。

詳細については、Coinbase 開発者プラットフォームの[メインネットでの実行](https://docs.cdp.coinbase.com/x402/quickstart-for-sellers#running-on-mainnet)に関するガイドをご覧ください。

## Stripe の入金アドレスを作成する

サーバーを設定する前に、暗号資産の入金アドレスを作成します。これは、Base の決済が送信されるオンチェーンアドレスです。

```bash
curl https://api.stripe.com/v1/crypto/deposit_addresses \
  -u "$STRIPE_SECRET_KEY:" \
  -H "Stripe-Version: 2026-05-27.preview" \
  -d network=base
```

返されたアドレスを `DEPOSIT_ADDRESS` 環境変数として保存します。

入金アドレスは何度でも作成できますが、これらの呼び出しをコアリクエストパスから除外することをお勧めします。

## 依存関係のインストール

必要な依存関係をインストールします。

```bash
npm install @x402/core @x402/evm @x402/hono @coinbase/x402 hono @hono/node-server stripe
```

## エンドポイントを作成する

x402 決済の検証を行うようにサーバーを設定します。前のステップの入金アドレスを、静的な `payTo` の宛先として使用します。

の例では、`/paid` へのリクエストごとに、USDC 建てで 0.01 米ドル相当の決済が必要です。

#### Node.js

```node
import { createFacilitatorConfig } from "@coinbase/x402";
import { HTTPFacilitatorClient } from "@x402/core/server";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { paymentMiddleware, x402ResourceServer } from "@x402/hono";
import { serve } from "@hono/node-server";
import { Hono } from "hono";

const DEPOSIT_ADDRESS = process.env.DEPOSIT_ADDRESS!.toLowerCase();

const app = new Hono();

const facilitatorClient = new HTTPFacilitatorClient(
  createFacilitatorConfig(process.env.CDP_API_KEY_ID!, process.env.CDP_API_KEY_SECRET!),
);

const resourceServer = new x402ResourceServer(facilitatorClient).register(
  "eip155:8453",
  new ExactEvmScheme(),
);

// Register the payment middleware — requires $0.01 in USDC on Base per request.
app.use(
  paymentMiddleware(
    {
      "GET /paid": {
        accepts: [
          {
            scheme: "exact",
            price: "$0.01",
            network: "eip155:8453",
            payTo: DEPOSIT_ADDRESS,
          },
        ],
        description: "Data retrieval endpoint",
        mimeType: "application/json",
      },
    },
    resourceServer,
  ),
);

// This endpoint is only accessible after valid payment is verified and settled.
app.get("/paid", (c) => {
  return c.json({ foo: "bar" });
});

serve({ fetch: app.fetch, port: 4242 });
```

## PaymentIntent を作成する

入金アドレスを事前に作成しているため、Base で受信した支払いはその固定アドレスに送信されます。x402 ファシリテーターで決済が確定した後、`transaction_verification` モードを使用して、オンチェーン取引を [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) として記録します。

> #### API バージョン
> 
> この機能には `2026-05-27.preview` API バージョンが必要です。Stripe クライアントを初期化する際に、`Stripe-Version` ヘッダーを `2026-05-27.preview` に設定します。

#### Node.js

```node
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: "2026-05-27.preview",
});

// Record settled on-chain payments as Stripe PaymentIntents using transaction_verification mode.
resourceServer.onAfterSettle(async ({ result, requirements }) => {
  const txHash = result.transaction;
  if (!txHash || !result.success) return;

  // requirements.amount is in atomic USDC units (6 decimals).
  // $0.01 = 10000 atomic units. Convert to cents for Stripe.
  const amountInCents = Math.round(Number(requirements.amount) / 10000);
  if (amountInCents < 1) return;

  const pi = await stripe.paymentIntents.create(
    {
      amount: amountInCents,
      currency: "usd",
      confirm: true,
      payment_method_data: { type: "crypto" },
      payment_method_types: ["crypto"],
      payment_method_options: {
        crypto: {
          mode: "transaction_verification",
          transaction_verification_options: {
            network: "base",
            transaction_hash: txHash,
          },
        },
      },
    },
    { idempotencyKey: txHash },
  );

  console.log(`Recorded PaymentIntent ${pi.id} for tx ${txHash}`);
});
```

## エンドポイントをテストする

適格なクライアントなしでサーバーにリクエストを送信し、`402` ステータスコードが返されることを確認します。レスポンスヘッダーを確認するには、`-iv` を使用します。

```bash
curl -iv http://localhost:4242/paid
```

レスポンスには、base64 でエンコードされた決済要件のペイロードを含む `payment-required` ヘッダーが含まれます。

```
> GET /paid HTTP/1.1
< HTTP/1.1 402 Payment Required
< payment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiO...
```

次に、対象のクライアントを使用してリクエストを行います。本番環境で入金アドレスを作成したため、このリクエストでは実際に資金が移動します。コマンドラインからテストするには、Stripeの [purl](https://github.com/stripe/purl) を使用してください。

```bash
purl http://localhost:4242/paid
```

決済が完了すると、サーバーがコンテンツを返します。[ダッシュボード](https://dashboard.stripe.com)で **Payments** に移動して取引を確認します。

## トークンとネットワークサポート

`mode: transaction_verification` で `crypto` 決済手段を使用する `PaymentIntent` は、以下のネットワークで USDC に対応しています。

| Network | トークン | トークンコントラクトアドレス |
| --- | --- | --- |
| Tempo | USDC | `0x20c0000000000000000000000000b9537d11c60e8b50` |
| Base | USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| Solana | USDC | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |
