Skip to content

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-IPX-Forwarded-ForX-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  = 0xc0b2388188f35c087400575393c124e9c459550f1dfcf848214f47637b599ee08a6b64876c4687e869d070d892b97071fd4c90b0a3491814823b4e97f8e7d50f

3. 充值接入流程

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,只传 countnetwork_id,一次最多 100 个。 平台为每个地址生成随机 uid,商户自行维护「地址 ↔ 用户」的映射关系。

适合需要提前备货、或者一个用户多个地址的场景。

3.2 展示与入账

  1. 把地址(以及对应网络、币种)展示给终端用户。
  2. 用户转账后,平台索引器扫链发现入账,写入充值记录。
  3. 达到确认数后,平台向商户回调地址推送充值通知
  4. 商户验签 → 幂等入账 → 返回 HTTP 201

入账以回调为准。回调报文里带 tx_hashamount(最小单位)、float_amount(可读金额)、 confirmedstatus。详见 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,这里是最容易踩坑的三条:

  1. 应答码就是控制信号

    • 201 = 处理完成,平台停止推送;
    • 200 = 尚未完成,平台继续按退避策略推送;
    • 4xx = 永久失败,平台立即停止;
    • 5xx/超时 = 临时失败,平台重试。

    典型用法:充值回调在 confirmed=false 时返回 200(不入账),等到 status=confirmed && confirmed=true 再入账并返回 201。绝不要在未确认时就给用户加余额。

  2. 必须验签。用平台公钥验证 sig 字段,验签失败直接拒绝,防止伪造入账。

  3. 必须幂等。同一笔充值/提现会被推送多次,用 (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,靠幂等键避免重复。

本文档描述 LinkePay 生产环境(主网)接口。接口如有变更以本文档为准。