Bat dau nhanh

5 buoc hoan thanh tich hop thanh toan

1

Dang ky va nhan API Key

Dang ky tai khoan thuong nhan, tao du an tren bang dieu khien, nhan Access Key va Secret Key.

2

Cau hinh dia chi thong bao khong dong bo

Cau hinh URL nhan thong bao khong dong bo trong cai dat du an, he thong se gui thong bao khi trang thai don hang thay doi.

3

Goi API tao don hang

Goi POST /payments voi chu ky HMAC-SHA256 de nhan dia chi thu tien va lien ket trang thanh toan.

4

Xu ly thong bao khong dong bo

Nhan thong bao khong dong bo, xac minh chu ky X-BS-Signature roi cap nhat trang thai don hang cuc bo.

5

Kiem thu va ra mat

Hoan thanh kiem thu toan bo quy trinh trong moi truong sandbox, xac nhan xong thi chuyen sang moi truong san xuat.

🔑

Xac thuc chu ky HMAC-SHA256

Moi yeu cau can mang theo Access Key, timestamp, Nonce ngau nhien va chu ky HMAC, dam bao yeu cau khong the gia mao.

🔔

Thong bao khong dong bo (Webhook)

Ho tro 8 loai su kien bao gom payment.completed, order.expired, payment.underpaid, bao phu toan bo vong doi thanh toan.

🔄

May trang thai don hang 12 trang thai

PENDING → PAID_UNCONFIRMED → CONFIRMED → COMPLETED, bao gom nhanh ngoai le (thanh toan thieu/thua/het han/kiem soat rui ro), luong trang thai ro rang va kiem soat duoc.

🔒

Idempotency va chong phat lai

Nonce chong phat lai, merchant_order_no chong tao trung lap, event_id chong xu ly trung lap, bao dam idempotency ba lop.

Phuong thuc xac thuc API

Tat ca yeu cau API thuong nhan deu can xac thuc chu ky HMAC-SHA256

Header yeu cau (Required Headers)

Header说明示例
X-BS-Access-Key商户 Access Key(公钥),标识商户身份ak_live_xxxxxxxxxxxx
X-BS-Timestamp请求时间戳(秒级 Unix 时间),与服务器时间偏差不超过 5 分钟1704067200
X-BS-Nonce随机字符串(UUID),防止重放攻击,每次请求唯一550e8400-e29b-41d4-a716-446655440000
X-BS-SignatureHMAC-SHA256 签名(Hex 编码)a1b2c3d4e5f6...
Content-Type固定为 JSON 格式application/json

Thuat toan chu ky

signature.txt
// 1. Construct signature body
signature_body = "{timestamp}" + "." + "{nonce}" + "." + "{request_body}"

// 2. Compute HMAC-SHA256 with Secret Key
signature = HMAC-SHA256(signature_body, secret_key)

// 3. Convert signature to Hex string, set as X-BS-Signature header
X-BS-Signature = hex(signature)

// Example:
// timestamp  = "1704067200"
// nonce      = "550e8400-e29b-41d4-a716-446655440000"
// body       = '{"merchant_order_no":"ORD-001","fiat_amount":"100.00",...}'
// secret_key = "sk_live_your_secret_key"
// signature_body = "1704067200.550e8400-e29b-41d4-a716-446655440000.{...json...}"
安全提示:Secret Key 仅在创建时展示一次,请妥善保存。请勿在前端代码中暴露 Secret Key,所有签名计算应在服务端完成。

Tai lieu giao dien API

Base URL: https://api.blocksettler.com/api/v1/merchant

POST/payments创建支付订单

请求参数 (Request Body)

字段类型必填说明
merchant_order_nostring商户订单号,同一应用下唯一(最长 64 字符)
titlestring订单标题,展示给付款方(最长 128 字符)
descriptionstring订单描述(最长 512 字符)
fiat_amountstring法币金额,如 "100.00"
fiat_currencystring法币币种,如 "USD", "CNY"
pay_chainstring支付链:POLYGON / TRON / ETH / BSC / SOLANA,不传则使用项目默认值
pay_tokenstring支付代币:USDT / USDC,不传则使用项目默认值
notify_urlstring异步通知地址,不传则使用项目配置的默认地址
return_urlstring支付完成后前端跳转地址
expires_inint订单有效期(秒),范围 300~86400,默认 1800(30分钟)
metadataobject商户自定义数据,原样返回在异步通知中

响应参数 (Response Body)

字段类型说明
platform_order_nostring平台订单号(BlockSettler 生成的唯一标识)
merchant_order_nostring商户订单号(请求时传入)
statusstring订单状态,创建时为 "PENDING"
fiat_amountstring法币金额
fiat_currencystring法币币种
pay_amountstring应付加密货币金额(系统按实时汇率计算)
paid_amountstring已付加密货币金额(创建时为 0)
pay_chainstring支付链名称
pay_tokenstring支付代币
pay_addressstring收款地址(付款方需向此地址转账)
expired_atstring订单过期时间(ISO 8601 格式)
created_atstring创建时间

请求示例

POST /api/v1/merchant/payments
// Request Body
{
  "merchant_order_no": "ORD-20250415-0001",
  "title": "Premium Plan - 1 Month",
  "description": "Premium membership subscription",
  "fiat_amount": "99.00",
  "fiat_currency": "USD",
  "pay_chain": "TRON",
  "pay_token": "USDT",
  "notify_url": "https://your-site.com/api/payment/notify",
  "return_url": "https://your-site.com/payment/success",
  "expires_in": 1800,
  "metadata": {
    "user_id": "U-10086",
    "plan": "premium"
  }
}

响应示例

Response 200 OK
{
  "code": 200,
  "message": "success",
  "data": {
    "platform_order_no": "BS2025041500000001",
    "merchant_order_no": "ORD-20250415-0001",
    "status": "PENDING",
    "fiat_amount": "99.00",
    "fiat_currency": "USD",
    "pay_amount": "99.000000000000000000",
    "paid_amount": "0.000000000000000000",
    "pay_chain": "TRON",
    "pay_token": "USDT",
    "pay_address": "TN7gK3Wfxy4RDXG5DPGnXmkJJPqozvMBkR",
    "return_url": "https://your-site.com/payment/success",
    "expired_at": "2025-04-15T11:30:00Z",
    "created_at": "2025-04-15T11:00:00Z"
  }
}
GET/payments/:order_no查询订单详情

通过平台订单号查询订单最新状态。 :order_no = platform_order_no

响应示例(支付完成后)

Response 200 OK
{
  "code": 200,
  "message": "success",
  "data": {
    "platform_order_no": "BS2025041500000001",
    "merchant_order_no": "ORD-20250415-0001",
    "status": "COMPLETED",
    "fiat_amount": "99.00",
    "fiat_currency": "USD",
    "pay_amount": "99.000000000000000000",
    "paid_amount": "99.000000000000000000",
    "pay_chain": "TRON",
    "pay_token": "USDT",
    "pay_address": "TN7gK3Wfxy4RDXG5DPGnXmkJJPqozvMBkR",
    "expired_at": "2025-04-15T11:30:00Z",
    "paid_at": "2025-04-15T11:05:32Z",
    "confirmed_at": "2025-04-15T11:06:45Z",
    "completed_at": "2025-04-15T11:06:45Z",
    "created_at": "2025-04-15T11:00:00Z"
  }
}
POST/payments/:order_no/close关闭订单

关闭一个待支付的订单。仅 PENDING、UNDERPAID、OVERPAID、LATE_PAID 状态的订单可关闭。

请求参数

字段类型必填说明
reasonstring关闭原因(最长 128 字符)
INFO统一响应格式与错误码

所有接口返回统一 JSON 结构:

response_format.json
// Success response
{ "code": 200, "message": "success", "data": { ... } }

// Invalid parameters
{ "code": 400, "message": "invalid fiat_amount", "data": null }

// Authentication failed (invalid signature / Access Key / expired timestamp)
{ "code": 401, "message": "invalid signature", "data": null }

// Resource not found
{ "code": 404, "message": "order not found", "data": null }

// Internal server error
{ "code": 500, "message": "internal error", "data": null }

Thong bao khong dong bo (Webhook)

Khi trang thai don hang thay doi, BlockSettler gui yeu cau HTTP POST den dia chi callback ma thuong nhan da cau hinh

Cac loai su kien duoc ho tro

event_type触发时机说明
payment.confirmed链上确认数达标交易已确认,可发货或交付服务
payment.completed订单完成结算订单流程正常完结
order.expired订单超时未支付超过有效期仍未收到足额支付
order.closed订单被关闭商户主动关闭或系统关闭
payment.underpaid实付金额不足收到的金额少于应付金额
payment.overpaid实付金额超额收到的金额超过应付金额
payment.late_paid过期后到账订单已过期,但仍收到了链上支付
payment.failed支付失败风控审核拒绝等异常

Dinh dang thong diep thong bao

系统向商户 notify_url 发送 POST 请求,Content-Type 为 application/json。

通知请求头

Header说明
Content-Typeapplication/json
X-BS-Event-ID事件唯一 ID,用于幂等去重
X-BS-Event-Type事件类型,如 payment.completed
X-BS-Timestamp通知发送的时间戳(秒级 Unix 时间)
X-BS-SignatureHMAC-SHA256 签名(用于验证通知来源)

通知 Body 示例(payment.completed)

webhook_payload.json
{
  "event_id": "evt_8f14e45f-ceea-4a4d-a8e0-3c2b5d4e9f01",
  "event_type": "payment.completed",
  "timestamp": "2025-04-15T11:06:45Z",
  "platform_order_no": "BS2025041500000001",
  "status": "COMPLETED",
  "payment": {
    "fiat_amount": "99.00",
    "fiat_currency": "USD",
    "pay_amount": "99.000000",
    "paid_amount": "99.000000",
    "pay_chain": "TRON",
    "pay_token": "USDT",
    "pay_address": "TN7gK3Wfxy4RDXG5DPGnXmkJJPqozvMBkR",
    "tx_hash": "6a1b2c3d4e5f...abc123def456"
  }
}

Xac minh chu ky

商户收到通知后,必须验证 X-BS-Signature 以确认通知来源可信。验证方式:

verify_signature.txt
// 1. Get timestamp and signature from request headers
timestamp  = request.headers["X-BS-Timestamp"]
signature  = request.headers["X-BS-Signature"]

// 2. Read the raw request body (JSON string)
raw_body   = request.body

// 3. Construct signature body and compute HMAC-SHA256
expected   = HMAC-SHA256(timestamp + "." + raw_body, your_webhook_secret)

// 4. Use constant-time comparison to verify signature (prevent timing attacks)
is_valid   = constant_time_equal(hex(expected), signature)

Co che thu lai

成功标准

商户接口返回 HTTP 2xx 状态码视为成功

重试策略

指数退避:1s → 5s → 30s → 5m → 30m → 2h,最多 6 次

幂等处理

请根据 event_id 做幂等判断,同一事件可能被投递多次

最佳实践:收到通知后应先返回 200 OK,再异步处理业务逻辑。若处理耗时过长(>5s),可能导致超时触发重试。

Vi du ma nguon

Vi du day du bao gom tao don hang (co chu ky) va nhan thong bao khong dong bo

create_order.sh
# ====== Create Payment Order ======

TIMESTAMP=$(date +%s)
NONCE=$(uuidgen)
BODY='{"merchant_order_no":"ORD-20250415-0001","title":"Premium Plan","fiat_amount":"99.00","fiat_currency":"USD","pay_chain":"TRON","pay_token":"USDT","notify_url":"https://your-site.com/api/notify"}'

# Compute signature: HMAC-SHA256(timestamp.nonce.body, secret_key)
SIGN_BODY="${TIMESTAMP}.${NONCE}.${BODY}"
SIGNATURE=$(echo -n "${SIGN_BODY}" | openssl dgst -sha256 -hmac "sk_live_xxxx" | awk '{print $2}')

curl -X POST https://api.blocksettler.com/api/v1/merchant/payments \
  -H "Content-Type: application/json" \
  -H "X-BS-Access-Key: ak_live_xxxxxxxxxxxx" \
  -H "X-BS-Timestamp: ${TIMESTAMP}" \
  -H "X-BS-Nonce: ${NONCE}" \
  -H "X-BS-Signature: ${SIGNATURE}" \
  -d "${BODY}"

# ====== Query Order ======
curl -X GET https://api.blocksettler.com/api/v1/merchant/payments/BS2025041500000001 \
  -H "X-BS-Access-Key: ak_live_xxxxxxxxxxxx" \
  -H "X-BS-Timestamp: ${TIMESTAMP}" \
  -H "X-BS-Nonce: $(uuidgen)" \
  -H "X-BS-Signature: {computed_signature}"

Luong trang thai don hang

BlockSettler su dung may trang thai 12 trang thai de quan ly vong doi don hang

CREATED已创建
PENDING待支付
PAID_UNCONFIRMED已支付待确认
CONFIRMED已确认
COMPLETED已完成
EXPIRED已过期
CLOSED已关闭
UNDERPAID少付
OVERPAID多付
LATE_PAID过期到账
RISK_REVIEW风控审核
FAILED失败
order_status_flow.txt
                         Normal Payment Flow
CREATED ──> PENDING ──> PAID_UNCONFIRMED ──> CONFIRMED ──> COMPLETED
                │
                │          Exception Branches
                ├──> EXPIRED          Timed out without payment
                ├──> CLOSED           Closed by merchant
                ├──> UNDERPAID        Paid < Required
                ├──> OVERPAID         Paid > Required
                └──> LATE_PAID        Payment after expiry

EXPIRED ──> LATE_PAID                Payment received after expiry
PAID_UNCONFIRMED ──> RISK_REVIEW   Risk control triggered
RISK_REVIEW ──> CONFIRMED / FAILED  Approved / Rejected

San sang bat dau tich hop?

Dang ky tai khoan nhan API Key, kiem thu trong moi truong sandbox, trung binh 1 ngay ra mat