開発者ドキュメント

支払い通知の署名を検証

タイムスタンプと Webhook 本文原文に対する HMAC-SHA256 で通知の署名を検証します。時刻の有効性、注文と支払情報、重複を確認し、イベントを保存してから HTTP 2xx を返します。

これらの注文 API (作成、クエリ、再送信) は、HMAC-SHA256 署名を使用します。 GET /api/v1/ping には、API キーのみが必要です。支払いコールバックには署名も含まれます。 HMAC は、API キーではなく、販売者の Webhook シークレットを使用します。

01.ヘッダー仕様

01. 注文 API リクエストを送信する

Client to Server

リクエストの作成、クエリ、再送信にも X-Bolt-Key が必要です。 timestamp はサーバー クロックから 5 分以内になければなりません。再試行時に新しい timestamp と署名を生成します。

Unix ミリ秒 timestamp必須
X-Bolt-Timestamp
HMAC-SHA256 16 進署名必須
X-Bolt-Signature

02. 支払いコールバックの受信

Server to Merchant

BoltUtil はコールバックのタイムスタンプと署名を生成します。受信者は生の本文を検証し、timestamp ウィンドウを確認し、イベントとビジネス オーダーを冪等に処理する必要があります。

Unix ミリ秒 timestamp必須
X-Bolt-Webhook-Timestamp
HMAC-SHA256 16 進署名必須
X-Bolt-Webhook-Signature

02.署名の計算

1

署名付きコンテンツを構築する

ヘッダーのタイムスタンプ、ピリオド、正確な元の本文を連結します:timestamp + "." + raw_body。UTF-8 を使い、本文が空でもピリオドを残してください。

// 1. Construct payload: timestamp + "." + body
String payload = timestamp + "." + body;
2

HMAC-SHA256を計算する

販売者 Webhook 設定のシークレットを使用します。署名に使用される本文は、API リクエストで送信された本文と正確に一致する必要があります。

// JDK standard library: javax.crypto.Mac and SecretKeySpec
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
3

小文字の 16 進数としてエンコードする

32 バイトのダイジェストを 64 文字の小文字の十六進表記に変換します。API リクエストでは X-Bolt-Signature に設定します。通知は X-Bolt-Webhook-Signature と定時間比較で検証してください。

// JDK 17+: java.util.HexFormat
String signature = HexFormat.of().formatHex(hash);

03.検証メモ

  • 検証前に JSON を解析して再シリアル化しないでください。空白、改行、キーの順序、エンコーディングはすべて署名に影響します。
  • HMAC はコンテンツの整合性を検証しますが、それ自体による再生は妨げられません。 timestamp の鮮度を確認し、イベントの重複を削除します。
  • 有効な署名は履行が完了したことを意味するものではありません。注文の関連付け、支払いステータス、金額、通貨、決済タイプを確認します。
コールバック処理を表示 →
signature / cURL
# Calculate a request signature without sending a request.
# BOLTUTIL_WEBHOOK_SECRET is your merchant Webhook secret, not API Key.
: "${BOLTUTIL_WEBHOOK_SECRET:?Set your Webhook secret}"
timestamp=$(python3 -c 'import time; print(int(time.time()*1000))')
body='{"externalOrderId":"INV-20260209-99281"}'
signature=$(printf '%s.%s' "$timestamp" "$body" | openssl dgst -sha256 -hmac "$BOLTUTIL_WEBHOOK_SECRET" | awk '{print $NF}')
printf 'X-Bolt-Timestamp: %s\nX-Bolt-Signature: %s\n' "$timestamp" "$signature"
# Send this SAME body with the above headers and X-Bolt-Key.
# Callback header names are X-Bolt-Webhook-Timestamp and
# X-Bolt-Webhook-Signature. Verify raw bytes before parsing JSON.

アドレス、トランザクション ハッシュ、注文は例です。これらを独自のテスト data に置き換えます。

Base URL

PROD
https://api.boltutil.com