開発者向け

ウェブフック

請求書のステータスが変化すると、CryBitは加盟店のウェブフックURLに対して、署名付きのPOSTリクエスト(JSON形式)を送信します。

設定

加盟店設定の連携タブで、ウェブフックURLを設定し、通知するイベント(paid、expired、refunded、cancelled)にチェックを入れます。URLはポート80、443、8080、8443のいずれかを使用する、公開されたHTTPまたはHTTPSアドレスである必要があります。リダイレクトは追跡されません。この設定は請求書のリクエストではなく、加盟店単位で行います。

ヘッダー

ヘッダー値
X-CryBit-Eventイベント名(例: payment.paid)。
X-CryBit-Signaturet=<unix time>,v1=<hex>: 署名シークレットを用いた"<t>.<raw body>"のHMAC-SHA256。

署名を検証する

署名シークレットは、加盟店設定のウェブフックURLの隣に表示されます。生のリクエストボディに対して署名を計算し、一定時間で比較したうえで、5分より古いリクエストは拒否してください。

PHP

$secret = getenv('CRYBIT_WEBHOOK_SECRET');
$body   = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_CRYBIT_SIGNATURE'] ?? '';

parse_str(str_replace(',', '&', $header), $p);   // t=…&v1=…
$t = (int) ($p['t'] ?? 0);
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);

if (abs(time() - $t) > 300 || !hash_equals($expected, $p['v1'] ?? '')) {
    http_response_code(400);
    exit;
}
// the request is genuine: store the event, answer 200, do the rest later
http_response_code(200);

Node.js

import crypto from 'node:crypto'

export function verify(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')))
  const t = Number(parts.t)
  const expected = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex')
  const ok = parts.v1 && parts.v1.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))
  return ok && Math.abs(Date.now() / 1000 - t) <= 300
}

配信とリトライ

  • 速やかに2xxのステータスで応答してください。CryBitは約12秒待機します。
  • 応答がない場合、CryBitは15秒後、1分後、5分後、15分後、30分後、その後2時間後、6時間後、24時間後にリトライします。
  • 429を除く4xxの応答があった場合、リトライは停止します。
  • 同じイベントが複数回届くことがあるため、order_idまたは請求書のuuidをキーとして冪等に処理してください。
  • ウェブフックを受け損ねた場合は、GET /api/v1/payments/{uuid}でステータスを確認してください。これが常に正となる情報源です。

FAQ

配信内容を確認できますか?

はい。加盟店アカウントのAPIログページでは、リクエストとウェブフックの配信履歴を、ステータスコードとボディとともに確認できます。

もっと見る

APIキーを取得する