快速上手
NeoLinks 商户 BFF 覆盖收单、收款、付款、法币换汇与账户。当前对外契约是 /api/merchant/v1,鉴权为登录会话 Bearer。Partner HMAC 尚未开放。
Merchant BFF
Bearer 会话鉴权,RESTful JSON,路径以 api/merchant.openapi.yaml 为准。
虚拟账户 VA
法币收单 / 收款走 stub VA,响应只回掩码账号与附言,不回完整账号。
稳定币链上
Vault 收单、Scanner 入账 crypto_inbounds,清算不得记成充值。
能力总览
type + status=active)。客户链上支付写入 crypto_inbounds,匹配后完结订单;Vault→清算不得记为商户充值。金额:稳定币 amount_minor 为 1e6,法币为分。
环境与 Base URL
对外商户 API 挂在官网同源路径下。下文接口路径均相对此 Base URL;本地联调见「本地联调」。
| 环境 | Base URL | 说明 |
|---|---|---|
| Production | https://neolinks.io/api/merchant/v1 |
官网 neolinks.io 同源;门户与集成均用此地址 |
认证
先 POST /auth/login 拿会话 token,之后请求带 Authorization: Bearer <token>。写接口另需对应 mch:* 权限。
请求头
| Header | 类型 | 说明 |
|---|---|---|
| Authorization必填 | string | Bearer 后接登录返回的 token |
| Idempotency-Key可选 | string | 收单建票可选;同一 key + 不同 body 返回 CONFLICT |
| X-2FA-Challenge-Token可选 | string | 付款 / 兑换下单在开启 2FA 时必填 |
curl -X POST "https://neolinks.io/api/merchant/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"password1"}'
curl -X POST "https://neolinks.io/api/merchant/v1/acquiring/invoices" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: inv-001" \
-d '{"amount_due_minor":100000000,"currency":"USDC","payment_rail":"CRYPTO","chain_id":31337}'
/api/partner/v1 使用 Partner HMAC(X-Api-Key + HMAC)。
通用响应格式
成功时 HTTP 2xx 且 code = 0(整数)。错误时 HTTP 4xx/5xx,code 为字符串错误码。
{
"code": 0,
"message": "ok",
"data": { /* 业务对象 */ },
"trace_id": "tr_abc123",
"request_id": "req_xyz789"
}
{
"code": "GATE_DENIED",
"message": "no active ACQUIRING_CRYPTO behavior",
"trace_id": "tr_abc123",
"request_id": "req_xyz789"
}
幂等与金额单位
幂等
| 字段 | 范围 | 说明 |
|---|---|---|
| Idempotency-Key | 收单建票 | 可选;冲突且 body 不同 → 409 CONFLICT |
金额单位
| 资产 | amount_*_minor | 说明 |
|---|---|---|
| USDC / USDT | 1e6 | 必须带已登记 chain_id;100 USDC = 100000000 |
| USD / EUR / HKD | 分(×100) | 不得带 chain_id;50.00 USD = 5000 |
收单 Acquiring
资源名为发票 /acquiring/invoices(/acquiring/orders 为同处理器别名)。建单前须有对应 active Behavior(CRYPTO 或 FIAT)。
订单状态
| 状态 | 说明 |
|---|---|
| AWAITING_PAYMENT | 已分配 Vault / 掩码 VA,等待付款 |
| PAYMENT_DETECTED | 已匹配入账、尚未完结 |
| COMPLETED | 足额匹配且结算完结 |
| CANCELLED / EXPIRED | 关单或过期 |
创建收单发票。成功 201。CRYPTO 返回 pay_address / pay_contract / order_ref;FIAT 返回掩码 VA 与 fiat_payment_ref。
Request Body
| 参数 | 类型 | 说明 |
|---|---|---|
| amount_due_minor必填 | integer | 应付最小单位。也可用展示字段 amount |
| currency必填 | string | USDC / USDT 或 USD / EUR / HKD |
| payment_rail可选 | enum | 省略或 CRYPTO;法币必须显式 FIAT |
| chain_idCRYPTO 必填 | integer | 已登记链。本地 31337。FIAT 禁止携带 |
{
"amount_due_minor": 100000000,
"currency": "USDC",
"payment_rail": "CRYPTO",
"chain_id": 31337
}
{
"code": 0,
"message": "ok",
"data": {
"id": "ao_...",
"status": "AWAITING_PAYMENT",
"amount": "100.000000",
"amount_due_minor": 100000000,
"currency": "USDC",
"payment_rail": "CRYPTO",
"pay_address": "0x...",
"pay_contract": "0x...",
"order_ref": "0x...",
"chain_id": 31337,
"company_id": "co_...",
"behavior_id": "beh_..."
}
}
查询本公司发票。跨公司 id 返回 404。列表:GET /acquiring/invoices。
关闭未完结发票。已 COMPLETED 不可关。
虚拟账户 Virtual Account
法币收单 / 收款使用 VA。创建时必须 payment_rail: "FIAT",且该币种 Capability 已开通。响应永不返回完整账号。
FIAT 发票字段
| 字段 | 类型 | 说明 |
|---|---|---|
| fiat_account_masked | string | 掩码账号(与 fiat_va_masked 同值) |
| fiat_payment_ref | string | 付款附言,银行转账须原样填写 |
| payment_rail | string | FIAT |
{
"amount_due_minor": 500000,
"currency": "USD",
"payment_rail": "FIAT"
}
own_account_id 或完整 account_number → 400。开发阶段银行入账为 stub,不是真实通道。
收款 Collection
独立收款单,不是收单发票。CRYPTO 分配地址;FIAT 返回掩码 VA。客户支付匹配入 crypto_inbounds / fiat_inbounds,不是充值。
创建收款单。成功 201。
Request Body
| 参数 | 类型 | 说明 |
|---|---|---|
| amount_due_minor必填 | integer | 期望金额(最小单位) |
| currency必填 | string | CRYPTO:USDC/USDT;FIAT:USD/EUR/HKD |
| payment_rail可选 | enum | CRYPTO | FIAT(法币必须显式 FIAT) |
| chain_idCRYPTO 必填 | integer | 已登记链。本地 31337。FIAT 禁止携带 |
| reference_no可选 | string | 商户参考号 |
详情含 pay_address(CRYPTO)或 fiat_va_masked(FIAT)。关单:POST …/cancel。
CRYPTO:绑定付款方链上交易哈希(payment_tx_hash 或 tx_hash),触发匹配。成功 200;状态不允许或哈希冲突 → 409。
列出贸易材料。需先 POST /uploads 拿到 file_id。
挂载材料。成功 201。待审状态可在详情页补传(含 COMPLETED)。
Request Body
| 参数 | 类型 | 说明 |
|---|---|---|
| file_name必填 | string | 文件名 |
| file_id必填 | string | 上传接口返回的 file_id |
| document_type可选 | string | 默认 COLLECTION_SUPPORTING |
仅 PENDING_OPS 可删;已审材料 → 409。
付款 Payout
对手必须是本公司已核验 payees(purpose=PAYOUT)。禁止手填地址/账号。CRYPTO 扣 TREASURY 并进入材料审核;BANK 无 chain_id。
Request Body
| 参数 | 类型 | 说明 |
|---|---|---|
| payee_account_id必填 | string | 已 VERIFIED 的付款对手 id |
| amount_minor必填 | integer | 付款金额(最小单位) |
| currency必填 | string | CRYPTO:USDC/USDT;FIAT:USD/EUR/HKD |
| rail可选 | enum | 省略/CRYPTO 或显式 BANK |
| chain_idCRYPTO 必填 | integer | CRYPTO 必填;BANK 禁止 |
{
"payee_account_id": "pae_...",
"amount_minor": 100000000,
"currency": "USDC",
"rail": "CRYPTO",
"chain_id": 31337
}
不存在可写的 …/execute、…/finalize、…/batch。
兑换 Exchange
已开通的 FIAT_FX / CRYPTO_SWAP / ONRAMP / OFFRAMP 走 stub 询价再下单。扣款户只能是 TREASURY。未开通或已停用的类型返回 403 GATE_DENIED。source_amount_minor / target_amount_minor 按各币种最小单位;跨法币↔稳定币时目标金额会按汇率并换算 scale(法币×100,稳定币×1e6)。
锁定汇率,成功 201。需要 mch:exchange:quote。
Request Body
| 参数 | 类型 | 说明 |
|---|---|---|
| exchange_type必填 | string | FIAT_FX / CRYPTO_SWAP / ONRAMP / OFFRAMP |
| source_currency必填 | string | 卖出币种 |
| target_currency必填 | string | 买入币种 |
| source_amount_minor必填 | integer | 卖出金额(源币种最小单位:法币×100,稳定币×1e6) |
用 quote_id 成交,成功 201 COMPLETED。需要 mch:exchange:create。没有 …/execute。
充值 Deposits
GET /deposits 只表示真实充值。客户付到 Vault、Vault→清算都不是充值,不会出现在此列表。
分页。收单流水请看 /acquiring/transactions 或发票详情。
余额 Balances
按业务账户查询可用余额。query business_account:ACQUIRING / COLLECTION / TREASURY / EXCHANGE。
例:?business_account=TREASURY
稳定币收单
开通 ACQUIRING_CRYPTO 后建 CRYPTO 发票。付款方对 Vault 调用 pay(orderRef, amount)。Scanner 写入 crypto_inbounds 并匹配订单。
- 匹配成功 → inbound
MATCHED,订单离开纯待付 - Vault→清算完结订单,禁止记两条假充值
- 本地 Anvil
chain_id=31337
法币收单
先开通 ACQUIRING_FIAT(按币种 scope)。建单必须显式 payment_rail=FIAT,且 currency 为 USD/EUR/HKD。
- 响应只有掩码账号与
fiat_payment_ref - 入账通道默认 stub,不阻塞功能验收
- 本环境 Webhook 不含法币超额 / 充值入账事件
开通 Capability
无对应 active 细 Behavior 时建单 403 GATE_DENIED。KYB 须 APPROVED。
| POST | 说明 |
|---|---|
| /capabilities/acquiring-crypto/activate | ACQUIRING_CRYPTO |
| /capabilities/partner-api/activate | PARTNER_API |
| /capabilities/acquiring-fiat/activate | ACQUIRING_FIAT,按币种 |
| /capabilities/collection-crypto/activate | COLLECTION_CRYPTO |
| /capabilities/collection-fiat/activate | COLLECTION_FIAT |
| /capabilities/payout-crypto/activate | PAYOUT_CRYPTO |
| /capabilities/payout-bank/activate | PAYOUT_BANK |
| /capabilities/exchange/activate | body: exchange_type=FIAT_FX |
Webhook 事件
在门户「设置 → Webhook」或 PATCH /integration/webhook 配置 URL。本环境只投递下列三条收单事件。
本环境已推送
| 事件 | 触发时机 |
|---|---|
| acquiring.order.awaiting_payment | 建票成功且已有付款地址 |
| acquiring.order.payment_detected | 订单进入 PAYMENT_DETECTED |
| acquiring.order.completed | 订单 COMPLETED |
不投递:收款 / 付款 / 兑换、deposit_credited、法币超额、KYT 失败。
{
"event": "acquiring.order.completed",
"id": "ao_...",
"status": "COMPLETED",
"amount_due_minor": 100000000,
"currency": "USDC",
"order_ref": "0x..."
}
签名验证
首次保存配置会返回一次明文 secret。签名:
| Header | 说明 |
|---|---|
| X-Webhook-Signature | sha256= + hex(HMAC-SHA256(secret, timestamp + "\n" + rawBody)) |
| X-Webhook-Timestamp | RFC3339 UTC |
接收方返回 HTTP 2xx 视为成功。轮换密钥:POST /integration/webhook/rotate。
错误码
| code | HTTP | 说明 |
|---|---|---|
| 0 | 2xx | 成功(整数) |
| INVALID_REQUEST | 400 | 参数错误 |
| UNAUTHORIZED | 401 | 未登录或 token 无效 |
| FORBIDDEN | 403 | 缺少 mch:* 权限 |
| GATE_DENIED | 403 | 无 active Behavior 或 KYB 未批 |
| TENANT_MISMATCH | 403 | body/query 的 company_id 不属于本会话 |
| TWO_FA_REQUIRED | 403 | 需要 X-2FA-Challenge-Token |
| EXCHANGE_TYPE_UNSUPPORTED | 403 | 未知兑换类型 |
| EXCHANGE_DEBIT_FORBIDDEN | 400 | 兑换扣款户不是 TREASURY |
| INSUFFICIENT | 400 | 可用余额不足 |
| NOT_FOUND | 404 | 资源不存在或不属于本公司 |
| CONFLICT | 409 | 幂等冲突、重复或状态不允许 |
| INTERNAL_ERROR | 500 | 内部错误 |
本地联调
在 neolinks-core 仓库启动 Docker API 与商户门户即可对照本文档调接口。
- make up && make up-app-skip-build && make web-restart
- POST /auth/login 获取 Bearer token
- 确认 KYB APPROVED 且已开通对应 Capability
- 创建 CRYPTO 发票,用 Anvil 钱包向 Vault 支付
- PATCH /integration/webhook 后观察三条收单事件
# neolinks-core 仓库
make up # Postgres + Redis
make up-anvil # 本地链 RPC :8545
make up-app-skip-build # Docker API :8080
make web-restart # 商户 :3000 / 运营 :3001
更新日志
| 版本 | 日期 | 变更 |
|---|---|---|
| Merchant BFF 0.2 | 2026-09 | 收款材料 documents;兑换跨法币/稳定币 minor scale;账户多 BA 同链余额聚合 |
| Merchant BFF 0.1 | 2026-08 | 对齐 /api/merchant/v1:Bearer、amount_minor、payment_rail、三条 Webhook;废止 Partner HMAC 文档 |
