主题
01 · 接入指南
本文说明商户从 0 到上线需要完成的全部事项。
1. 核心概念
| 概念 | 说明 |
|---|---|
| 项目(Project) | 商户在 LinkePay 上的租户单位,由平台分配 project_uid(如 Ab3xY9Kq7Z)。所有接口路径都带这个值。 |
| 用户充值地址(Deposit Address) | 平台为商户的每个终端用户分配的专属链上地址。用户往这个地址转账 = 一笔充值。 |
| 归集地址(Consolidation Address) | 每个项目 + 每条网络一个。用户充值资金会按归集策略自动汇集到这里,提现也从这里出金。 |
| 商户密钥对 | 商户自持的 secp256k1 密钥对。私钥用于给写请求签名,公钥登记到平台。私钥绝不上传平台。 |
| 平台公钥 | 平台的 secp256k1 公钥。用于验证回调报文和响应体的 sig,确认报文确实来自 LinkePay。 |
| API Key | 一串随机字符串,用于查询类接口的鉴权(X-API-Key 头)。 |
两套鉴权,分别用在哪
| 鉴权方式 | 用在哪些接口 | 请求头 |
|---|---|---|
| 请求签名 | 生成充值地址、发起提现(所有会改变资金/状态的写操作) | X-Signature: 0x... |
| API Key | 查询充值地址、查询充值/提现记录、查询归集余额 | X-API-Key: ... |
两者都还要额外满足:来源 IP 在白名单内。
2. 准备工作(Checklist)
2.1 生成商户密钥对
密钥是标准的 secp256k1(以太坊同款) 密钥对。
用 SDK 生成(推荐):
go
package main
import (
"fmt"
linkepay "github.com/linkepay/linkepay-sdk-go"
"github.com/linkepay/linkepay-sdk-go/types"
)
func main() {
client := linkepay.NewClient(&types.Config{})
keys, err := client.GenerateKeys()
if err != nil {
panic(err)
}
fmt.Println("private key:", keys.PrivateKey) // 0x + 64 hex,自己妥善保管
fmt.Println("public key:", keys.PublicKey) // 0x04 + 128 hex,提交给平台
fmt.Println("address :", keys.Address)
}或用 openssl / ethers.js 等任意能生成 secp256k1 密钥的工具。
公钥格式:平台接受 未压缩公钥,即 65 字节(
0x04开头 + 128 位十六进制), 也接受去掉0x04前缀的 64 字节(128 位十六进制)形式。
私钥保管:私钥只存在于商户服务端(建议放 KMS / Vault / K8s Secret), 泄露等同于他人可以用你的名义发起提现。
2.2 在控制台完成配置
以下几项需要在 LinkePay 商户控制台(登录后需 TOTP 二次验证)完成,或联系平台运营协助:
| 配置项 | 说明 |
|---|---|
| 登记商户公钥 | 上传 2.1 生成的公钥。未登记时所有签名接口返回 project public key not found。 |
| 生成 API Key | 首次生成与后续轮换是同一个入口。轮换后旧 Key 立即失效。 |
| IP 白名单 | 登记商户服务端的公网出口 IP。需平台审核通过(状态 approved)后才生效。多个出口 IP 需逐个登记。 |
| 回调地址(Callback URL) | 接收充值/提现通知的 HTTPS 地址,并把 callback_enabled 打开。 |
| 开通网络与币种 | 为项目在目标网络(如 Ethereum Mainnet / TRON / BSC)初始化归集地址,并把要支持的币种加入支持列表。 |
| 风控参数 | 单笔免审额度、单日提现次数/金额上限、归集策略等。 |
IP 白名单是硬门槛:来源 IP 未通过审核时,所有
/api/v1/client/...请求直接返回403 IP address not whitelisted or not approved,请求根本不会到达业务层。 白名单变更有约 60 秒缓存,改完请稍等再重试。平台按
CF-Connecting-IP→X-Forwarded-For→X-Real-IP→ TCP 源地址的顺序识别来源 IP。 如果不确定自己的出口 IP,可以在商户服务器上执行curl https://api.ipify.org。
2.3 记录下这几个值
接入代码里需要用到:
BASE_URL = https://linkepay-api.bestxx.com
PROJECT_UID = <平台分配>
API_KEY = <控制台生成>
MERCHANT_PRIVATE_KEY = <自己保管,2.1 生成>
MERCHANT_PUBLIC_KEY = <已登记到平台>
PLATFORM_PUBLIC_KEY = 0xc0b2388188f35c087400575393c124e9c459550f1dfcf848214f47637b599ee08a6b64876c4687e869d070d892b97071fd4c90b0a3491814823b4e97f8e7d50f3. 充值接入流程
3.1 选择地址分配模式
平台提供两种模式,按业务形态二选一(也可混用):
模式 A:按用户 UID 绑定(推荐,一人一址)
调用 POST /user/generate-deposit-address-by-user-uid,自己传 uid,平台返回该 uid 绑定的地址。
uid必须是{project_uid}-{你的用户ID}的格式,例如Ab3xY9Kq7Z-100286。- 同一个
uid只能建一次;重复调用返回uid already used。 - 之后随时可以用
GET /user/{uid}/deposit-address/{network_id}反查地址。
用户首次进入充值页 → 查缓存/DB 是否已有地址
├─ 有 → 直接展示
└─ 无 → 调 generate-deposit-address-by-user-uid → 落库 → 展示模式 B:批量预生成地址池
调用 POST /user/generate-deposit-address,只传 count 和 network_id,一次最多 100 个。 平台为每个地址生成随机 uid,商户自行维护「地址 ↔ 用户」的映射关系。
适合需要提前备货、或者一个用户多个地址的场景。
3.2 展示与入账
- 把地址(以及对应网络、币种)展示给终端用户。
- 用户转账后,平台索引器扫链发现入账,写入充值记录。
- 达到确认数后,平台向商户回调地址推送充值通知。
- 商户验签 → 幂等入账 → 返回 HTTP 201。
入账以回调为准。回调报文里带
tx_hash、amount(最小单位)、float_amount(可读金额)、confirmed、status。详见 03-回调通知.md。
EVM 地址跨链复用:同一个用户 uid 在所有 EVM 网络(Ethereum / BSC)上是同一个地址。 接口只返回你请求的那条网络的记录,但该地址在其它已开通的 EVM 网络上同样会被监控。 TRON 地址与 EVM 地址不同,需要单独申请。
4. 提现接入流程
商户风控/审批通过
│
▼
生成全局唯一 uid ── POST /withdraw (签名) ──▶ LinkePay
│ │
│◀──── 200 {request_uid, status} ──────────│
│ │
│ status = pending → 已进入出金队列
│ status = under_review → 触发平台侧人工审核
│ │
│◀────────── 提现回调(多次,状态推进) ─────│要点:
uid必须全局唯一,建议用 UUID 或商户前缀+业务单号。重复会返回uid already used(错误码1029)。 这同时是提现的幂等键:网络超时后用同一个uid重试是安全的。amount是可读金额字符串,例如"100.5",不是最小单位。平台按币种精度自行换算。- 平台会同时校验链上归集地址余额和数据库归集余额,不足直接返回
1028。 - 提现返回的
status:pending:已受理,进入出金队列。under_review:金额超过项目配置的免审额度,等待平台侧审核。
- 最终结果以提现回调为准,不要用同步返回值判定成功。
5. 回调接入要点
完整规范见 03-回调通知.md,这里是最容易踩坑的三条:
应答码就是控制信号:
201= 处理完成,平台停止推送;200= 尚未完成,平台继续按退避策略推送;4xx= 永久失败,平台立即停止;5xx/超时 = 临时失败,平台重试。
典型用法:充值回调在
confirmed=false时返回 200(不入账),等到status=confirmed && confirmed=true再入账并返回 201。绝不要在未确认时就给用户加余额。必须验签。用平台公钥验证
sig字段,验签失败直接拒绝,防止伪造入账。必须幂等。同一笔充值/提现会被推送多次,用
(type, uid)做去重 (充值的uid就是tx_hash,提现的uid就是你发起提现时传的单号)。
回调地址必须是公网可达的 http/https 地址,且不能指向内网/私有地址段(平台有 SSRF 防护,内网地址会被拒绝)。
6. 联调清单
上线前逐项确认:
- [ ]
curl https://linkepay-api.bestxx.com/api/v1/admin/health/返回server is healthy - [ ] 商户公钥已登记,
generate-deposit-address-by-user-uid返回 200 而不是project public key not found - [ ] 出口 IP 已审核通过,接口不再返回 403
- [ ] API Key 可用,
consolidation/balances返回 200 - [ ] 目标网络已初始化归集地址(否则提现返回
failed to get consolidation address) - [ ] 目标币种已加入项目支持列表
- [ ] 回调地址可从公网访问,返回 201,且能正确验签
- [ ] 小额真实充值走通:地址 → 到账 → 收到回调 → 入账
- [ ] 小额真实提现走通:发起 → 收到回调 → 链上可查
- [ ] 提现
uid重复提交返回1029(幂等验证) - [ ] 商户私钥已放入密钥管理系统,未硬编码在代码/配置仓库中
7. 限流与超时
| 项 | 值 |
|---|---|
| 限流 | 按来源 IP 约 125 请求/秒(突发 125)。超限返回 429 Too many requests |
| 网关请求超时 | 55 秒 |
| SDK 默认超时 | 30 秒(可通过 Config.Timeout 调整,单位秒) |
建议对 5xx 和网络错误做指数退避重试;对写接口重试时务必带上相同的 uid,靠幂等键避免重复。