PLATFORM INTEGRATION · API V1

BindPact 平台接入说明

你的服务端创建一次性绑定会话,用户扫码确认;只有收到 SUCCEEDED 后才启用绑定。之后每次验证码都在你的平台本地验证。

BASE URL https://api.BindPact.com/api/v1
JSONHTTPSUTC
下载 OpenAPI 3.1 文件 →
01 · OVERVIEW

你只需要接入绑定流程

BindPact 不参与用户每次输入验证码时的验证。平台仍然是 TOTP Secret 的长期持有方和唯一验证方。

01平台后端创建会话
02BindPact App扫码确认
03平台本地验证六位码

调用频率很低:绑定阶段创建会话并查询一次结果;日常登录、提现或敏感操作无需请求 BindPact。

02 · CREDENTIALS

获取平台凭证

每个合作平台会获得三项独立凭证。请存入服务端 Secret Manager,不要下发到浏览器或移动端。

platform_id

平台在 BindPact 中的身份标识。

API Key

通过 X-Platform-Key 请求头鉴权,只显示一次。

Webhook Secret

配置 webhook 时签发,用于验证状态通知。

!

不要把 API Key、Webhook Secret 或 TOTP Secret 写入前端代码、二维码、URL、日志和分析系统。

03 · CREATE SESSION

生成 Secret 并创建绑定会话

  1. 生成并加密保存 Secret。使用 20 个密码学安全随机字节,编码为 32 位无填充 Base32。固定参数为 SHA1、6 位、30 秒。
  2. 保存一个稳定的幂等键。同一次用户操作发生网络重试时,必须复用完全相同的请求体和 Idempotency-Key。
  3. 从你的后端调用 BindPact。platform_user_id 使用平台内部稳定 ID;account_label 只传脱敏提示。
bash
curl -X POST 'https://api.BindPact.com/api/v1/platform/binding-sessions' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'X-Platform-Key: plt_REPLACE_ME' \
  -H 'Idempotency-Key: 68b81cf0-d781-4ad1-9d2e-213e5967d90e' \
  -d '{
    "platform_user_id": "user_12345",
    "account_label": "lin***@example.com",
    "totp_secret": "JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP"
  }'

成功响应

json
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "PENDING",
  "qr_url": "one-device-token://bind/550e8400-e29b-41d4-a716-446655440000",
  "expires_at": "2026-09-14T10:05:00+00:00",
  "totp_algorithm": "SHA1",
  "totp_digits": 6,
  "totp_period": 30
}

把响应中的 qr_url 原样编码为二维码。二维码中绝不能包含 otpauth://、Secret 或平台 API Key。

04 · BINDING RESULT

只在 SUCCEEDED 后启用绑定

你可以短轮询状态接口,也可以接收签名 webhook。轮询请求示例:

bash
curl 'https://api.BindPact.com/api/v1/platform/binding-sessions/550e8400-e29b-41d4-a716-446655440000' \
  -H 'Accept: application/json' \
  -H 'X-Platform-Key: plt_REPLACE_ME'
PENDING等待用户在 BindPact App 中确认
AWAITING_ACKSecret 已交给 App,但尚未确认安全保存
SUCCEEDED绑定成功,此时才可为账号启用 MFA
REJECTED违反唯一绑定规则或前次 ACK 未完成
EXPIRED会话过期,平台应保留原有安全状态
!

AWAITING_ACK 不是成功。它只表示 Secret 已下发;App 写入 Keychain 并完成 ACK 后,状态才会变成 SUCCEEDED。

05 · WEBHOOK

验证原始请求体签名

签名输入为 timestamp + "." + raw_body,算法为 HMAC-SHA256,小写十六进制结果加 v1= 前缀。

X-Webhook-Id事件唯一标识,用于幂等去重
X-Webhook-TimestampUnix 秒,建议只接受 ±300 秒
X-Webhook-Signaturev1=<64位小写hex>
php
<?php
$raw = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

if (!ctype_digit($timestamp) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(401); exit;
}

$expected = 'v1=' . hash_hmac(
    'sha256',
    $timestamp . '.' . $raw,
    $_ENV['BINDPACT_WEBHOOK_SECRET']
);

if (!hash_equals($expected, $signature)) {
    http_response_code(401); exit;
}

// 使用 X-Webhook-Id 做幂等去重,再处理 JSON。

在解析 JSON 前验签;已处理事件仍返回 2xx。只处理 binding.succeededbinding.rejectedbinding.expired

06 · LOCAL TOTP

日常验证码在平台本地验证

使用平台自己加密保存的 Secret 验证 RFC 6238 六位验证码。建议允许前后各一个时间窗口,并记录最后成功的 time-step 防止重放。

php
// 平台长期加密保存 Secret;验证时在本地完成
$counter = Totp::verifyAndGetCounter(
    secret: $secret,
    code: $sixDigitCode,
    window: 1,
);

// 必须拒绝已经成功使用过的 time-step
$valid = $counter !== null && $counter > $lastSuccessfulCounter;
算法SHA1
位数6
周期30 秒
容差±1 step
07 · PRODUCTION CHECKLIST

上线前检查

平台 API Key 与 Webhook Secret 只保存在服务端
TOTP Secret 加密持久化,日志和 APM 完成敏感字段脱敏
绑定请求保存稳定 Idempotency-Key,超时重试保持请求体不变
Webhook 先验签、再解析,并按 X-Webhook-Id 幂等处理
仅 SUCCEEDED 启用 MFA;失败不会覆盖用户原有安全状态
验证码验证限流、使用 NTP 对时,并拒绝已成功的旧 time-step
对提现、领取权益等业务继续叠加账号、支付和频率风控
准备开始联调?

先在测试平台创建一条绑定会话,完成真机扫码、ACK 和 webhook 全链路。

检查 API 状态 →