# MPP 支払い マシン間支払いには MPP を使用してください。 [MPP (Machine Payments Protocol)](https://mpp.dev) は、インターネット決済のプロトコルです。クライアントが有料リソースをリクエストすると、サーバーは決済の詳細を含む HTTP `402` レスポンスを返します。クライアントは支払いを承認し、リクエストを再試行して支払い、有料リソースへのアクセス権と領収書を取得します。 MPP は、次の 2 つの決済手段をサポートしています。 - **暗号資産決済**: 暗号資産入金アドレスを使用した直接のオンチェーン決済 - **法定通貨決済**: [Shared Payment Token (SPT)](https://docs.stripe.com/agentic-commerce/concepts/shared-payment-tokens.md) が対応しているカード、ウォレット、およびその他の決済手段。 アプリの[ソースコード全体](https://github.com/stripe-samples/machine-payments)は GitHub で確認できます。 ## Before you begin アカウントでマシン決済を有効にする必要があります。 > 顧客は世界中でステーブルコインを決済に利用できますが、ステーブルコインの決済を受け付けることができるのはアメリカ企業のみです。 ステーブルコイン決済の受け付けを開始するには、以下のようにします: 1. [Stripe アカウントを設定](https://docs.stripe.com/get-started/account/set-up.md)していることを確認してください。 1. ダッシュボードの[決済手段](https://dashboard.stripe.com/settings/payment_methods)設定に移動し、**ステーブルコインと暗号資産**の決済手段をリクエストします。[機械決済](https://docs.stripe.com/payments/machine.md)のみにステーブルコインまたは暗号資産による決済を受け付ける場合は、マシン決済専用の別の[決済方法設定](https://docs.stripe.com/payments/payment-method-configurations.md)を作成することをお勧めします。 1. Stripe はアクセスリクエストを審査し、必要に応じて詳細をご連絡する場合があります。リクエストを審査する間、決済手段は**保留中**と表示されます。 1. リクエストが承認されると、ダッシュボードで**ステーブルコインと暗号資産**が有効になります。 ## 決済ライフサイクル このガイドではサーバーを構築します。サーバーは決済が必要であることを示し、決済が正常に完了した後にコンテンツを返します。 #### 暗号資産 クライアント、サーバー、Stripe 間の MPP 暗号資産決済フローを示す図 (See full diagram at https://docs.stripe.com/payments/machine/mpp) 暗号資産決済では、Stripe は入金アドレスを処理し、資金がオンチェーンで確定されるときに [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) を自動的に *キャプチャーします* (Another way to say that you receive payment for a charge is to say that you "capture" the charge. Capturing the charge is often asynchronous and takes place after authorization. The capture is what transfers the money from the customer to you)。 #### SPT クライアント、サーバー、Stripe 間の MPP SPT 決済フローを示す図 (See full diagram at https://docs.stripe.com/payments/machine/mpp) [Shared Payment Token (SPT)](https://docs.stripe.com/agentic-commerce/concepts/shared-payment-tokens.md) 決済では、まずクライアントが SPT を作成します。サーバーはそのトークンを使用して `PaymentIntent` を作成し、Stripe の決済ネットワークを通じて決済を完了させます。 ## 各方法を使用するタイミング | 決済方法 | 最適な選択 | 売上処理 | | -------- | ------------------------------ | ------------- | | **暗号資産** | 少額の取引 | オンチェーン売上処理 | | **SPT** | 従来の決済手段、カード、ウォレット、より幅広い決済手段に対応 | Stripe の決済レール | ## エンドポイントを作成する エンドポイントに決済ミドルウェアを追加して、決済を要求します。 #### 暗号資産 この例では、`tempo.charge` メソッドを使用して、リクエストごとに [pathUSD](https://docs.tempo.xyz/protocol/exchange/quote-tokens#pathusd) で 0.01 USD の決済が必要です。 #### Node.js ```node import crypto from 'crypto'; import { Mppx, tempo } from 'mppx/server' const PATH_USD = '0x20c0000000000000000000000000000000000000'; const mppSecretKey = crypto.randomBytes(32).toString('base64'); export async function handler(request: Request) { const recipientAddress = await createPayToAddress(request); const mppx = Mppx.create({ methods: [ tempo.charge({ currency: PATH_USD, recipient: recipientAddress, testnet: true, }), ], secretKey: mppSecretKey, }); const response = await mppx.charge({ amount: '0.01', recipient: recipientAddress, })(request); if (response.status === 402) return response.challenge; return response.withReceipt(Response.json({ data: '...' })); } ``` #### SPT この例では、SPT を使用する `stripe.charge` メソッドで 1 USD が必要です。このメソッドでは、チャレンジの生成、認証情報の確認、`PaymentIntent` の作成、領収書の生成が処理されます。 #### Node.js ```node import crypto from 'crypto'; import { Mppx, stripe } from 'mppx/server' // Secret used to secure payment challenges // https://mpp.dev/protocol/challenges#challenge-binding const mppSecretKey = crypto.randomBytes(32).toString('base64'); const mppx = Mppx.create({ methods: [ stripe.charge({ networkId: 'internal', paymentMethodTypes: ['card', 'link'], secretKey: process.env.STRIPE_SECRET_KEY!, }), ], secretKey: mppSecretKey }); export async function handler(request: Request) { const result = await mppx.charge({ amount: '1', currency: 'usd', decimals: 2, description: 'Premium API access', })(request); if (result.status === 402) return result.challenge; return result.withReceipt(Response.json({ data: '...' })); } ``` ## PaymentIntent を作成する #### 暗号資産 暗号資産決済を処理するには、`crypto` *決済手段* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) を受け付ける [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) を作成します。前述の `recipient` メソッドを使用してください。 > #### API バージョン > > この機能には `2026-03-04.preview` API バージョンが必要です。Stripe クライアントの初期化時に `Stripe-Version` ヘッダーを `2026-03-04.preview` に設定します。 #### Node.js ```node import Stripe from 'stripe'; import { Credential } from 'mppx'; import NodeCache from 'node-cache'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: '2026-03-04.preview', }); // In-memory cache for deposit addresses (TTL: 5 minutes) // NOTE: For production, use a distributed cache like Redis instead of node-cache const paymentCache = new NodeCache({ stdTTL: 300, checkperiod: 60 }); async function createPayToAddress(request: Request): Promise<`0x${string}`> { const authHeader = request.headers.get('authorization'); if (authHeader && Credential.extractPaymentScheme(authHeader)) { const credential = Credential.fromRequest(request); const toAddress = credential.challenge.request.recipient as `0x${string}`; if (!toAddress) { throw new Error( 'PaymentIntent did not return expected crypto deposit details' ); } if (!paymentCache.has(toAddress)) { throw new Error('Invalid payTo address: not found in server cache'); } return toAddress; } const decimals = 6; const amountInCents = Number(10000) / 10 ** (decimals - 2); const paymentIntent = await stripe.paymentIntents.create({ amount: amountInCents, currency: 'usd', payment_method_types: ['crypto'], payment_method_data: { type: 'crypto', }, payment_method_options: { crypto: { mode: 'deposit', deposit_options: { networks: ['tempo'], }, } as Stripe.PaymentIntentCreateParams.PaymentMethodOptions.Crypto, }, confirm: true, }); if ( !paymentIntent.next_action || !('crypto_display_details' in paymentIntent.next_action) ) { throw new Error( 'PaymentIntent did not return expected crypto deposit details' ); } const depositDetails = paymentIntent.next_action .crypto_display_details as unknown as { deposit_addresses?: Record; }; const payToAddress = depositDetails.deposit_addresses?.tempo?.address; if (!payToAddress) { throw new Error( 'PaymentIntent did not return expected crypto deposit details' ); } console.log( `Created PaymentIntent ${paymentIntent.id} for $${( amountInCents / 100 ).toFixed(2)} -> ${payToAddress}` ); paymentCache.set(payToAddress, true); return payToAddress as `0x${string}`; } ``` この関数は、クライアントが受け取り、決済に使用する暗号資産の入金アドレスを返します。 [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) のレスポンスには、`supported_tokens` で指定された入金アドレスが含まれます。これには、各ネットワークで受け付けられるトークンとそのコントラクトアドレスがリストされています。 ```json { "id": "pi_123", "amount": 5000, "currency": "usd", "status": "requires_action", "next_action": { "type": "crypto_display_details", "crypto_display_details": { "deposit_addresses": { "tempo": { "address": "0xtempo_address", "supported_tokens": [ { "token_currency": "usdc", "token_contract_address": "0x…" } ] } } } } } ``` > #### 暗号資産 PaymentIntents > > 入金アドレス、決済ライフサイクル、サポートされるネットワークなど、暗号資産 PaymentIntents の仕組みの詳細については、[入金モード組み込みガイド](https://docs.stripe.com/payments/deposit-mode-stablecoin-payments.md)をご覧ください。 #### SPT SPT 決済では、サーバーがクライアントから有効な SPT 認証情報を受信すると、PaymentIntent が自動的に作成されます。`stripe.charge` メソッドは、クライアントから提供された SPT を使用して PaymentIntent の作成を処理します。 PaymentIntent には以下が含まれます。 - チャレンジの金額と通貨 - SPT からの決済手段 - `stripe.charge` メソッドで設定されたメタデータ - Stripe の決済レールによる売上処理 PaymentIntent を別途作成する必要はありません。`stripe.charge` は、認証情報を検証する際に PaymentIntent を作成します。 ## エンドポイントをテストする エンドポイントで、Stripe がサポートするマシン決済を受け付ける準備が整いました。決済認証情報なしでリクエストを行い、導入が機能することを確認します。サーバーは `402` ステータスコードと決済要件で応答する必要があります。 ```bash curl http://localhost:4242/paid | jq ``` 決済の詳細とともに `402` ステータスコードと決済の詳細が表示されます。 ```json { "type": "https://paymentauth.org/problems/payment-required", "title": "Payment Required", "status": 402, "detail": "Payment is required.", "challengeId": "..." } ``` 有効な決済によるリクエストをシミュレーションします。 #### 暗号資産 コマンドラインでテストするには、 [mppx](https://www.npmjs.com/package/mppx) を使用します。 ```bash npx mppx account create npx mppx account fund npx mppx http://localhost:4242/paid ``` > #### サンドボックスとテストネット > > [サンドボックス](https://docs.stripe.com/sandboxes.md)で作成する[PaymentIntents](https://docs.stripe.com/api/payment_intents/object.md)は暗号資産テストネットを監視しないため、送信されたテストネット取引を自動的に検出できません。サンドボックス `PaymentIntents` をテストするには、[テストヘルパーエンドポイント](https://docs.stripe.com/api/payment_intents/simulate_crypto_deposit.md?api-version=2026-03-04.preview)を使用して暗号資産の入金をシミュレーションします。[インテグレーションのテストの詳細](https://docs.stripe.com/payments/deposit-mode-stablecoin-payments.md#test-your-integration)をご確認ください。 ウォレットを接続した場合、サーバーはコンテンツを返し、決済を確認できます。[Stripe ダッシュボード](https://dashboard.stripe.com)で **Payments** に移動して取引を確認してください。 #### SPT [サンドボックス](https://docs.stripe.com/sandboxes.md) で実装をテストするには、Stripe プロフィールを設定します。アカウントの [Stripe プロフィールを作成](https://docs.stripe.com/get-started/account/profile.md) し、その `profile_test_` ID を `networkId` として使用します。テスト用シークレットキーを使用してテスト決済を作成します。 #### Node.js ```node const mppx = Mppx.create({ methods: [ stripe.charge({ networkId: 'profile_test_...', paymentMethodTypes: ['card', 'link'], secretKey: process.env.STRIPE_SANDBOX_SECRET_KEY!, }), ], secretKey: mppSecretKey }); ``` [link-cli](https://link.com/agents) を使用して、お客様のアカウントのテスト SPT を発行できます。`link-cli` は、Link アカウントを使用してワンタイムの Shared Payment Token 認証情報をプロビジョニングできるツールです。[link.com/agents](https://link.com/agents) に記載されている手順に従って、`link-cli` スキルをインストールするか、希望するエージェントで MCP サーバーとして登録してください。 `link-cli` を使用して手動でテストするには、そのコマンドを直接実行できます。 1. 個人用の Link アカウントにログインするか、アカウントがない場合は[登録](https://app.link.com)してください。 ```bash npx @stripe/link-cli auth login ``` 1. 使用する決済手段を選択してください。まだお持ちでない場合は、[決済手段を追加](https://app.link.com/wallet)できます。 ```bash npx @stripe/link-cli payment-methods list ``` 1. テスト支出リクエストを作成して、1 回限りのテスト SPT を発行します。テスト認証情報を作成するには`--test` を渡し、テスト用の `profile_test_` ID を指定するには`--network-id` を渡します。 ```bash npx @stripe/link-cli spend-request create \ --payment-method-id csmrpd_xxx \ --context "Test machine payments integration with Shared Payment Tokens, your test Stripe profile, and the link-cli" \ --amount 100 \ --credential-type shared_payment_token \ --network-id profile_test_... \ --test \ --request-approval ``` 1. 決済を実行します。`--method` フラグと`--data` フラグは、実装形態によって異なります。 ```bash npx @stripe/link-cli mpp pay https://your-endpoint.com/resource \ --spend-request-id lsrq_xxx \ --method POST \ --data '{ ... }' ``` [Stripe ダッシュボード](https://dashboard.stripe.com)で **決済** に移動して、取引を確認します。 ## メインネットと本番環境のトランザクションを実行する #### 暗号資産 メインネット取引を実行するには、Tempo の USDC を `0x20c000000000000000000000b9537d11c60e8b50` でターゲットし、`tempo.charge` を呼び出す際に `testnet: true` を削除してください。 #### Node.js ```node import crypto from 'crypto'; import { Mppx, tempo } from 'mppx/server' const TEMPO_USD = '0x20c000000000000000000000b9537d11c60e8b50'; const mppSecretKey = crypto.randomBytes(32).toString('base64'); export async function handler(request: Request) { const recipientAddress = await createPayToAddress(request); const mppx = Mppx.create({ methods: [ tempo.charge({ currency: TEMPO_USD, recipient: recipientAddress }), ], secretKey: mppSecretKey, }); ... } ``` #### SPT 実装のテスト完了後、[本番環境で Stripe プロフィールを作成](https://docs.stripe.com/get-started/account/profile.md)し、`profile_` ID をそれに応じて更新します。MPP 設定で本番用の Stripe シークレットキーに切り替えます。これにより、クライアントが SPT を作成する際に本番環境の `profile_` ID を指定できます。 #### Node.js ```node const mppx = Mppx.create({ methods: [ stripe.charge({ networkId: 'profile_...', paymentMethodTypes: ['card', 'link'], secretKey: process.env.STRIPE_SECRET_KEY!, }), ], secretKey: mppSecretKey }); ``` `profile_` ID を更新したら、`--test` フラグなしで新しい支出リクエストを作成し、本番環境の SPT を発行します: ```bash npx @stripe/link-cli spend-request create \ --payment-method-id csmrpd_xxx \ --context "Use machine payments integration with Shared Payment Tokens in live mode, your live Stripe profile, and the link-cli" \ --amount 100 \ --credential-type shared_payment_token \ --network-id profile_... \ --request-approval ``` 次に、本番環境のエンドポイントに対して `mpp pay` コマンドを再実行します: ```bash npx @stripe/link-cli mpp pay https://your-endpoint.com/resource \ --spend-request-id lsrq_xxx \ --method POST \ --data '{ ... }' ```