認証
InfraIO Pay には認証モデルの異なる 2 つの API サーフェス があります。 呼び出し主体に合わせて選択してください:
| サーフェス | パスプレフィックス | 想定対象 | 認証方式 |
|---|---|---|---|
| マーチャント B2B | /b2b/v1/* | あなたのサーバー | HMAC-SHA256 リクエスト署名 |
| ダッシュボード | マーチャントダッシュボードが使用 | マーチャントダッシュボードのブラウザセッション | Bearer JWT |
本ページは API キーペアを使ってサーバーから呼び出す B2B サーフェスを 扱います。ダッシュボードサーフェスは InfraIO Pay マーチャントダッシュボードが 使用するもので、公開された連携用サーフェスではありません。
/b2b プレフィックスを含めたフルパスを送信し、同じパスに署名して
ください (下記参照)。
エンドポイント
| 環境 | ベース URL |
|---|---|
| Test | https://api-dev.infraio.xyz |
| Live | https://api.infraio.xyz |
URL パターンは同じです — 環境は URL ではなく キーのプレフィックス
(pk_test_… vs pk_live_…) で制御します。
キーペア
マーチャントダッシュボード (Developers → API keys → + Add key) から 2 つの値を取得します:
- Publishable key (
pk_test_…またはpk_live_…) — あなたの アカウントを識別します。X-Client-IDとして送信。ブラウザバンドルに 埋め込んでも安全です (SDK は既にそうしています)。 - Secret key (
sk_test_…またはsk_live_…) — HMAC 署名鍵。 サーバー限定。データベースパスワードと同じ扱いをしてください。
シークレットキーがブラウザバンドル、Git リポジトリ、ログ行、 共有チャットなどに混入した場合 — 直ちに ダッシュボードから 失効させてください。失効は即時で、オーバーラップウィンドウはありません。 新しいキーを発行して再デプロイしてください。
リクエストの署名
/b2b/v1/* への各呼び出しは 3 つのヘッダーを伴います:
X-Client-ID: pk_live_70d0becbd7a53047b0dfe88a960d10ad
X-Timestamp: 1715990400
X-Signature: 9a8b7c6d… (hex HMAC-SHA256)署名は canonical 文字列に対して計算されます:
METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODYMETHOD— 大文字の HTTP 動詞 (POST、GETなど)。PATH—/b2bプレフィックスを含めた リクエストパス、ホストと クエリ文字列を除く (例:/b2b/v1/checkout-sessions/quick)。 プレフィックスは必須です。クエリパラメータは 署名対象に 含めません —GET …?cursor=…&limit=20ではパスのみに署名し、?…部分には署名しません。TIMESTAMP— Unix 秒の 10 進文字列 (例:"1715990400")、X-Timestampと完全一致させてください。BODY— 生のリクエストボディバイト。GET/DELETEでは空文字。
シークレット キーで HMAC-SHA256 署名し、hex で出力:
Node / TS
import { createHmac } from "node:crypto";
function sign({ method, path, body, secret }: {
method: string; path: string; body: string; secret: string;
}) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const input = [method.toUpperCase(), path, timestamp, body].join("\n");
const signature = createHmac("sha256", secret).update(input).digest("hex");
return { timestamp, signature };
}なぜ Bearer ではなく HMAC か
素の Bearer トークン API は、リクエストごとにあなたの唯一のシークレットを ネットワーク越しに送信します。TLS 終端プロキシのログを 1 つでも捕捉 されれば、アカウントの鍵がそのまま渡ります。HMAC 署名なら、シークレット 自体は移動せず、そこから導出された署名 (そのリクエストとその分にだけ バインドされた一回限りの値) だけが流れます。
トレードオフ: 呼び出しごとに署名を計算する必要があります。サーバー SDK はまだありませんが、上記のヘルパーは言語あたり 15 行程度です。
タイムスタンプの許容範囲
許容範囲は ±5 分 (300 秒) です。このウィンドウ外のリクエストは
401 invalid_signature で拒否されます。2 つの含意:
- サーバー時計を NTP で同期 してください。時計がずれた長時間 稼働の cron は断続的に失敗します。
- 署名を事前計算してキューに入れないでください。 リトライキューで
5 分滞留すると、その署名は期限切れになります。
キーのスコープ
シークレットキーは以下のスコープバンドルを 1 つ以上保持します:
| スコープ | 想定用途 |
|---|---|
read | 注文、セッション、返金の一覧 / 読み取り |
write_order | チェックアウトセッション、注文の作成 |
write_refund | 返金の発行、返金リクエストトークンの発行 |
webhook_manage | Webhook エンドポイントの作成 / 更新 / 削除 |
ダッシュボードはデフォルトで「フルアクセス」キー (4 つすべて) を 発行します。Developers → API keys → + Add key から、統合に必要な スコープだけにチェックを入れた制限付きスコープキーを発行できます。
スコープはまだ強制されていません。 スコープはキーに記録されダッシュボードに
表示されますが、有効な sk_… キーであれば、あなたのマーチャントのどの
/b2b/v1/* エンドポイントでも呼び出せます。スコープをセキュリティ境界として
頼らないでください。アクセスを制限するにはキーをローテーションまたは失効
させてください。
検証に失敗した場合
署名、X-Client-ID、またはタイムスタンプが無効な場合、リクエストは API に
到達する前に 401 INVALID_SIGNATURE で拒否されます。この方式で署名される
のは /b2b/v1/* リクエストのみです。Webhook は別のスキームを使用します
(下記参照)。
次に
- エラー — 4xx/5xx 時のレスポンス形式。
- セキュリティ → API キー — ローテーション、 失効、シークレットが漏れたときの対処。
- Webhook → 署名検証
— 異なる HMAC スキームを使用 (ヘッダーは
X-Signature: sha256=…、 署名対象はX-Timestamp + "." + raw_body、24 時間のローテーション猶予 ウィンドウ中は任意でX-Signature-Prev)。スキームを混同しないで ください — ハッシュアルゴリズムは共通ですが、署名対象バイトと シークレットファミリ (whsec_…vssk_…) は異なります。