# Coinbase Commerce 互換 API

> Coinbase Commerce から blockwallets へ、SDK のベース URL とキーの変更だけで切り替え:対応する charge エンドポイント、Webhook と署名、相違点。
>
> HTML: https://blockwallets.io/docs/coinbase-commerce?lang=ja · English: https://blockwallets.io/docs/coinbase-commerce.md?lang=en

## Coinbase Commerce 互換 API

charge のエンドポイント、`X-CC-Api-Key` ヘッダー、charge オブジェクト、`X-CC-Webhook-Signature` で署名される Webhook は Coinbase Commerce のドキュメントに従うため、公式 SDK は 1 行変えるだけで動きます。Coinbase Commerce は 2026-03-31 に、米国とシンガポール以外の加盟店へのサービス提供を終了しました。ほかのサービスからの移行ですか?[移行の概要](https://blockwallets.io/docs/migrate?lang=ja)をご覧ください。

内部では通常の blockwallets の請求です。受取アドレスはあなたのもの、決済ページは当社のホスト型決済ページで、支払いはオンチェーンで承認され、2つ目のノードでも照合されて初めて有効になります。以下では、3つのステップに続けて、各 API の対応範囲と**元のサービスとの違い**を説明します。実装していないパラメーターは、黙って無視されることなくエラーを返します。

### 3つのステップ

- 加盟店アカウントを取得し([トップページから申し込み](https://blockwallets.io/?lang=ja#join))、管理画面「開発者 › 連携とキー」の「サイトのドメイン」にドメインを追加します。コールバック URL(`ipn_callback_url`)とリダイレクト URL(`success_url` / `cancel_url` / `redirect_url`)は、これらのドメイン上、またはコールバック URL のドメイン上である必要があります。キーが漏えいしても、Webhook を別の場所に向けることはできません。

- 加盟店管理画面の「開発者 › 連携とキー」で互換の認証情報を発行します。本番用とテスト用が1組ずつあり、NOWPayments は **API key + IPN secret**、Coinbase Commerce は **API key + webhook shared secret** です。表示は一度だけで、当社にはハッシュ / 暗号文だけを保存します。

- コードを下記のベース URL に向け、新しいキーを使います。まずテスト用の認証情報でテストネット上で動かし、そのあと本番に切り替えてください。

| 移行前 | 移行後 | 認証ヘッダー | Webhook 署名 |
| --- | --- | --- | --- |
| `https://api.commerce.coinbase.com` | `https://blockwallets.io/coinbase/` | `X-CC-Api-Key` | `X-CC-Webhook-Signature`(HMAC-SHA256) |

### Coinbase Commerce

公式 SDK はどれもベース URL を指定できます。1 行変えるだけです(末尾の `/` に注意):

```sdk
// Node(coinbase-commerce-node)
const { Client } = require("coinbase-commerce-node");
- Client.init(process.env.COINBASE_COMMERCE_API_KEY);
+ Client.init(process.env.COINBASE_COMMERCE_API_KEY, "https://blockwallets.io/coinbase/");

# Python(coinbase-commerce)
- client = Client(api_key=API_KEY)
+ client = Client(api_key=API_KEY, base_api_uri="https://blockwallets.io/coinbase/")

// PHP(coinbase/coinbase-commerce)
- ApiClient::init($apiKey);
+ ApiClient::init($apiKey, 'https://blockwallets.io/coinbase/');
```

```curl
curl -X POST https://blockwallets.io/coinbase/charges \
  -H "X-CC-Api-Key: $COINBASE_COMMERCE_API_KEY" -H "X-CC-Version: 2018-03-22" \
  -H "content-type: application/json" \
  -d '{"name":"Order #12345","description":"Pro plan","pricing_type":"fixed_price",
       "local_price":{"amount":"100.00","currency":"USD"},
       "redirect_url":"https://shop.example/success","cancel_url":"https://shop.example/cancel",
       "metadata":{"order_id":"12345"}}'
# → 201 {"data": {"id": "…", "code": "7C7V5ECK", "hosted_url": "https://blockwallets.io/pay/inv_…", "timeline": [{"status": "NEW", …}], …}}
```

#### 対応エンドポイント

| エンドポイント | 備考 |
| --- | --- |
| `POST /charges` | チャージを作成。`hosted_url` は当社のホスト型決済ページで、有効期間は 1 時間 |
| `GET /charges/:code_or_id` | 8 文字のコードまたは id で検索 |
| `GET /charges` | 一覧:`limit`(100 以下)/ `starting_after` / `ending_before` / `order`。`pagination` オブジェクトも同じ |
| `POST /charges/:code_or_id/cancel` | まだ支払いを検知していないチャージをキャンセル |

非対応:`/charges/:code/resolve`(400 — 不足払いのチャージは管理画面で対応してください)、`/checkouts`、`/events`、`/invoices`(404)。

#### Webhook

Coinbase の Webhook はアカウント単位で、当社も同じです。管理画面で設定した**コールバック URL** に送信されます(テスト用の認証情報で作成したチャージはテスト用のコールバック URL に送信)。ボディは Coinbase 形式の `{id, scheduled_for, attempt_number, event: {id, type, api_version, created_at, data}}` で、`data` にチャージの全内容が入ります。`X-CC-Webhook-Signature` = HMAC-SHA256(shared secret, 生のボディ) なので、SDK の `Webhook.verifyEventBody` がそのまま使えます。再試行では `event.id` は同じままで `attempt_number` が増えます。`event.id` で重複を排除してください。

```nodejs
import crypto from "node:crypto";

// Same as the SDK's Webhook.verifySigHeader: HMAC-SHA256(shared secret, raw body)
function verifyWebhook(rawBody, sig, sharedSecret) {
  const hmac = crypto.createHmac("sha256", sharedSecret).update(rawBody, "utf8").digest("hex");
  return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(sig || ""));
}
// verifyWebhook(rawBody, req.headers["x-cc-webhook-signature"], process.env.COINBASE_WEBHOOK_SECRET)
// or with the official SDK:Webhook.verifyEventBody(rawBody, signature, sharedSecret)
```

| イベント | タイミング | 最後のタイムライン項目 |
| --- | --- | --- |
| `charge:confirmed` | 支払済み(オンチェーンで承認され、照合済み。超過払いも含む) | `COMPLETED` |
| `charge:failed` | 未払いのまま期限切れ / あなたがキャンセル / 不足のまま期限切れ | `EXPIRED` / `CANCELED` / `UNRESOLVED`(コンテキスト `UNDERPAID`) |

照会すると `NEW`(支払い待ち)と `PENDING`(オンチェーンで支払いを検知、承認待ち)も確認できます。**`charge:confirmed` で履行してください**。`charge:created`、`charge:pending`、`charge:delayed`、`charge:resolved` は送信しません。

#### Coinbase Commerce との相違点

- `pricing_type` は `fixed_price` である必要があり、`local_price.currency` は USD でなければなりません(USDC / USDT は 1:1)。`no_price` とほかの法定通貨は 400 を返します。

- アドレスは、お客様が決済ページで通貨とネットワークを選んだ時点で現れます。`addresses` には選んだネットワークだけが入り、`pricing` は選択後に `local` と `settlement` だけが入ります。`exchange_rates`、`checkout`、ブランディング関連のフィールドはありません。

- `metadata` はそのまま保存して返します(最大 4 KB)。

- 返金はタイムラインに表示されません。管理画面で確認してください。

### テストモード

テスト用の認証情報で作成したチャージと決済は各チェーンのテストネットで動き、その Webhook はテスト用の IPN secret / shared secret で署名されます。本番とは完全に分離されており、テスト用のキーから本番の決済は見えません。

そのほか(決済ページ、承認、ネットワークと最低額、返金)は[メインのドキュメント](https://blockwallets.io/docs/cryptomus?lang=ja)のとおりに動作します。
