← 返回商户后台商户 API 接入文档
更新:2026-09-20。依据当前 B 服务实现整理。
接入地址与凭证
服务地址:https://nyshanghu.com。商户程序仅调用 B,所有商户共用 URL,通过独立凭证隔离数据。
管理员开通商户时交付 api_key_id、api_secret、webhook_secret。后两项仅创建时展示,应保存在商户服务器安全配置中,不能放入网页、App 或日志。管理员令牌不是商户 API 密钥。
开通前请提供商户的 HTTPS 回调完整 URL(443 端口);其域名需由平台加入允许名单。回调 URL 是商户接收通知的接口,与平台地址申请 API 不同。
当前服务器自动任务及主网广播未启用;接口接入完成不代表充值监听、通知投递和归集已正式上线。请与平台确认启用状态。
申请客户固定充值地址
POST https://nyshanghu.com/v1/addresses
{"customer_id":"user_10001"}
customer_id:商户自身已登录用户的固定编号,1–100 位 ASCII 字母、数字或 _.:@-。不要每次点击充值生成新编号,不传 merchant_id。首次分配地址,同商户同客户重复请求返回原地址;不同客户独立地址。
响应字段包括 id、merchant_id、customer_id、network、asset、address、created_at。当前主网 network 为 tron-mainnet,asset 为 USDT。将 address 显示给客户;不返回私钥。申请成功不代表已充值。
请求签名
所有商户接口使用以下请求头:
| 请求头 | 值 |
| Content-Type | application/json |
| X-Key-Id | 商户 api_key_id |
| X-Timestamp | 当前 Unix 秒数,十进制字符串 |
| X-Nonce | 每次请求新的随机串,16–100 位 ASCII 字符 |
| X-Signature | 使用 api_secret 计算的 HMAC-SHA256 小写十六进制 |
签名原文由五段组成,以真实换行符连接,末尾无额外换行:
timestamp
nonce
大写HTTP方法
请求路径及原始查询字符串
SHA256(原始请求体字节)的小写十六进制
路径不含域名;例如 /v1/deposits?limit=50&offset=0,查询顺序、编码必须与实际请求一致。GET 请求体为空字节。时间允许偏差 ±300 秒,nonce 不可重用。超时重试重新生成时间戳和 nonce、重新签名,但 customer_id 保持不变。序列化后的 JSON 必须与实际发送字节完全相同。
Python 地址申请示例
仅依赖标准库。通过环境变量设置:
- DEPOSIT_API_URL:
https://nyshanghu.com/v1/addresses - DEPOSIT_API_KEY_ID:平台交付的 Key ID
- DEPOSIT_API_SECRET:平台交付的 API Secret
保存下方代码为 merchant_client.py,运行 python merchant_client.py user_10001。
"""商户服务器端地址申请示例;仅依赖标准库。"""
import hashlib
import hmac
import json
import os
import secrets
import sys
import time
import urllib.request
def get_address(customer_id):
"""Use the authenticated user's stable ID, not an ID supplied by another user."""
url = os.environ['DEPOSIT_API_URL']
from urllib.parse import urlsplit
parsed = urlsplit(url)
if parsed.scheme not in ('http', 'https') or parsed.path != '/v1/addresses' or parsed.query or parsed.fragment or parsed.username or parsed.password:
raise ValueError('DEPOSIT_API_URL must be the full /v1/addresses endpoint')
if parsed.scheme != 'https' and parsed.hostname not in ('127.0.0.1', 'localhost'):
raise ValueError('Remote connections require HTTPS')
body = json.dumps({'customer_id': customer_id}, separators=(',', ':')).encode()
timestamp, nonce = str(int(time.time())), secrets.token_hex(16)
message = '\n'.join([timestamp, nonce, 'POST', parsed.path, hashlib.sha256(body).hexdigest()])
signature = hmac.new(os.environ['DEPOSIT_API_SECRET'].encode(), message.encode(), hashlib.sha256).hexdigest()
request = urllib.request.Request(url, data=body, method='POST', headers={
'Content-Type': 'application/json', 'X-Key-Id': os.environ['DEPOSIT_API_KEY_ID'],
'X-Timestamp': timestamp, 'X-Nonce': nonce, 'X-Signature': signature,
})
# Do not forward signed requests or credentials to redirect targets.
class NoRedirect(urllib.request.HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
with urllib.request.build_opener(NoRedirect).open(request, timeout=15) as response:
return json.load(response)
if __name__ == '__main__':
if len(sys.argv) != 2:
raise SystemExit('Usage: python examples/merchant_client.py <stable_customer_id>')
print(json.dumps(get_address(sys.argv[1]), ensure_ascii=False))
查询及补发接口
下表路径均相对于服务地址,均需上述签名。
| 方法与路径 | 功能及参数 |
| GET /v1/addresses | 地址列表;limit、offset、customer_id |
| GET /v1/deposits | 充值列表;limit、offset、customer_id、state |
| GET /v1/deposits/{id} | 本商户单笔充值 |
| GET /v1/summary | 累计确认金额、地址数等统计 |
| GET /v1/ledger | 账本分录;limit、offset |
| GET /v1/webhooks | 通知投递记录;limit、offset、state |
| POST /v1/webhooks/{id}/retry | 请求重试本商户通知;空请求体 |
| GET /v1/reconciliation | 本商户账本一致性检查 |
列表响应为 {items,limit,offset,total}。limit 默认50、范围1–200;offset 默认0、非负。接口只能读取本商户记录,不能靠提交 merchant_id 切换身份。
金额以 amount_raw 十进制字符串为准,USDT decimals=6;1000000 表示1 USDT。使用整数或精确小数计算,不使用浮点金额。充值入账以 confirmed 状态为准。
充值到账 Webhook
B 将 JSON 以 POST 发送到商户配置的回调 URL。事件含:event_id、event_type=deposit.confirmed、deposit_id、merchant_id、customer_id、network、asset、contract、address、txid、log_index、amount_raw、amount、decimals=6、status=confirmed。
请求头:X-Webhook-Timestamp、X-Webhook-Signature。
验签算法与商户请求签名不同:
expected = hmac.new(
webhook_secret.encode(),
timestamp.encode() + b'.' + raw_request_body,
hashlib.sha256,
).hexdigest()
valid = hmac.compare_digest(expected, received_signature)
使用独立 webhook_secret;必须针对原始请求体验签,不能先解析再序列化。验证时间戳合理性(建议±300秒)、事件类型、商户归属、网络/合约及金额格式后,在数据库事务中按 event_id/deposit_id 去重并入账。成功提交后返回 HTTP 2xx;重复通知验证后直接返回2xx,不得重复加款。超时或非2xx会重试,不能假设通知仅送一次。
错误处理
| HTTP状态 | 含义 |
| 401 | 凭证或签名无效、时间戳异常 |
| 403 | 商户停用或入口禁止访问 |
| 404 | 不存在或不属于本商户 |
| 409 | nonce重放、幂等冲突或状态冲突 |
| 422 | 请求字段或配置不符合要求 |
| 429 | 请求过于频繁 |
| 502 / 503 | 依赖暂不可用 |
不要将 HTTP 200 当作到账证明,必须检查业务状态。
在线文档入口
商户接入文档: https://nyshanghu.com/docs 。此页面提供商户接口说明,不需要管理员令牌;业务 API 仍须商户签名认证。