OOnlobo Gateway OpenAPI 3.1

PRODUCTION API · V1 · 2026-08-24

聚合支付网关
商户接入文档

统一接入支付、退款、订阅、代付与日报。平台只支持标准两位小数币种,交易金额使用分制整数,所有业务结果以订单查询或异步通知为准。

Base URLhttps://onlobo.com/gateway/v1
签名算法HMAC-SHA256
请求格式application/json
重要:HTTP 2xx 只表示请求已被接受,不等于支付成功。读取 data.status,并通过查询或异步通知确认最终结果。
01

SECURITY

签名鉴权

除公开文档和健康检查外,所有 /gateway/v1/** 请求均须携带下列四个鉴权头。API Secret 由商户在商户后台自行创建、查看和切换;切换后旧 Secret 继续有效 10 分钟。

请求头要求
X-Merchant-Id平台商户雪花 ID 的十进制字符串
X-TimestampUTC Unix 秒,允许与服务器相差 5 分钟
X-Nonce16–128 位字母、数字、下划线或短横线;10 分钟内不可重复
X-Signaturev1= + 小写十六进制 HMAC-SHA256

Idempotency-Key 不是全局鉴权头,只在创建支付、退款、代付、订阅和取消订阅等写接口中必传,最长 128 字符。带 JSON 请求体时使用标准 Content-Type: application/json;查询与下载接口不需要幂等头。

开户后取得 Merchant ID 和商户后台账号。登录商户后台后自行创建 API Secret 和 Webhook Secret;Merchant ID 用于定位当前启用的 API Secret,API Secret 用于请求签名,Webhook Secret 只用于验证网关异步通知,二者不可混用。

签名原文

UPPERCASE_HTTP_METHOD + "\n" +
requestTarget + "\n" +
timestamp + "\n" +
nonce + "\n" +
lowercase_hex_sha256(rawBody)

requestTarget 是原始路径与原始查询字符串,例如 /gateway/v1/payments?page=1&pageSize=50。查询参数顺序和编码必须与实际发送的 URL 完全一致。

signature = "v1=" + lowercase_hex(
  HMAC_SHA256(apiSecret, canonicalText)
)

GET 请求的原始请求体为空字节数组,其 SHA-256 固定为 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。JSON 请求必须针对实际发送的 UTF-8 原始字节签名,禁止重新排序字段后再计算。

02

CONTRACT

幂等与统一响应

幂等范围是“商户 + 操作类型 + Idempotency-Key”。相同 Key 和相同请求返回首次结果;请求内容不同返回 1004

{
  "code": 200,
  "message": "Success",
  "data": {},
  "requestId": "req_..."
}
  • code=200 表示接口处理成功,不表示支付成功;支付结果读取 data.status
  • 错误响应的 datanull
  • 请求体最大 1 MB,超出返回 HTTP 413 / 1007
  • 只支持 ISO 默认精度为两位小数的币种;金额按分传整数,例如 12.34 传 1234

第一层响应码

codemessage含义
200Success接口处理成功;交易结果仍读取 data.status
1001–1007Request / resource error请求、校验、资源、幂等、状态、方法或请求体错误;完整取值见“错误码”
1101–1108Authentication / authorization error认证、凭据、时间戳、Nonce、重放、签名或权限错误;完整取值见“错误码”
1202Callback URL error回调地址无效
2001Payment order not found支付订单不存在
2101–2105Risk / permission error金额、日限额、交易权限或风控并发冲突
3001–3002Provider error渠道不可用或结果暂时无法确认
4001Invalid provider webhook signature上游通知签名无效
9001Internal server error平台内部错误
03

PAYMENTS

支付

POST/payments创建支付

使用后台绑定的渠道支付参数创建支付。请求必须携带签名请求头和 Idempotency-Key。金额只接受整数分,商户订单号在当前商户范围内必须唯一。直连卡资料与收银台资料二选一,不允许商户指定渠道。

请求字段

字段类型是否必传规则与说明
merchantOrderNostring必传商户订单号,1–128 位;在当前商户范围内唯一。该值只用于商户与网关对账,不会直接作为上游订单号。
currencystring必传三位 ISO 4217 大写币种编码,例如 USD。只支持平台已启用且默认精度为两位小数的币种。
amountinteger(int64)必传支付金额,必须大于 0,单位为分。例如 1234 表示 12.34 USD,禁止传小数或主币单位字符串。
paymentMethodstring必传后台已绑定并启用的支付方式编码;直连卡资料只允许 CARD,收银台资料须匹配绑定渠道实际支持方式。
customerEmailstring必传客户邮箱,最长 320 位;网关会去除首尾空格并转为小写。渠道需要购物者标识时,网关以该值同时生成渠道 shopper_emailshopper_id,商户无需重复提交。
notifyUrlstring非必传本订单的成功异步通知地址,最长 2048 位,必须为 HTTPS。存在时只投递该地址;缺省时回退商户默认 Webhook;两者都没有则拒绝创建。
returnUrlstring非必传客户浏览器完成 3DS 后的 HTTPS 返回地址,最长 2048 位,网关自动拼接;商户域名报备只记录事实,不参与交易准入。不提交时商户可收到响应后自行拼接。仅用于浏览器回跳,不表示支付成功。
paymentMethodDataobject二选一网关统一直连 CARD 资料,字段见下表。与 checkoutData 必须且只能提交一个非空对象。Elanlink 使用此资料。
checkoutDataobject二选一FuturePay 收银台业务资料:productName(必填,最长255)、productDetail(必填,最长1024)、origin(必填,最长255)、countryCode(必填,两位大写国家编码)。不传卡号、渠道密钥或任意 metadata,不使用占位商品。资料类型与实际绑定不符时,下单前拒绝。

paymentMethodData 字段

字段类型是否必传规则与说明
firstNamestring必传持卡人名字,1–100 位。
lastNamestring必传持卡人姓氏,1–100 位。
cardNumberstring必传卡号,12–23 位数字,可包含空格;网关收到后会移除空格。仅用于本次上游请求,不落库、不写日志。
expirationYearstring必传四位到期年份,例如 2029
expirationMonthstring必传两位到期月份,范围 0112
securityCodestring必传3–4 位卡安全码。仅用于本次上游请求,绝不落库、缓存或记录日志。
shopperIpstring非必传付款客户公网 IP,最长 45 位;建议直连交易传递。
shopperPhonestring非必传付款客户电话,最长 64 位,建议包含国际区号。
billingCountrystring非必传账单国家,两位 ISO 3166-1 alpha-2 编码,例如 US;网关会转为大写。
billingStatestring非必传账单州/省,最长 128 位。
billingCitystring非必传账单城市,最长 128 位。
billingAddressstring非必传账单详细地址,最长 512 位。
billingPostalCodestring非必传账单邮政编码,最长 32 位。
osstring非必传客户操作系统,最长 64 位,用于风控或 3DS。
browserstring非必传浏览器或 User-Agent 信息,最长 512 位。
browserLanguagestring非必传浏览器语言,最长 32 位,例如 en-US
timeZonestring非必传客户端时区信息,最长 16 位。
resolutionstring非必传屏幕分辨率,最长 32 位,例如 1920x1080
challengeWindowSizestring非必传3DS Challenge 窗口规格,最长 8 位。
sessionIdstring非必传商户侧客户会话编号,最长 128 位;不得包含卡号或安全码。

请求示例

{
  "merchantOrderNo": "ORDER-20260820-001",
  "currency": "USD",
  "amount": 1234,
  "paymentMethod": "CARD",
  "customerEmail": "ada\u0040example.com",
  "notifyUrl": "https://merchant.example.com/api/payment/notify",
  "returnUrl": "https://merchant.example.com/payment/return",
  "paymentMethodData": {
    "firstName": "Ada",
    "lastName": "Lovelace",
    "cardNumber": "CARD_NUMBER",
    "expirationYear": "2029",
    "expirationMonth": "08",
    "securityCode": "CVV",
    "billingCountry": "US"
  }
}

当前仅开放 Elanlink 直连 CARD。下游只提交网关统一字段;渠道字段名、渠道商户号、渠道通知地址、签名、token_flag 和其他渠道常量均由网关生成。网关不会向上游传递 payment_method

生产卡数据只能经服务端 HTTPS 请求发送;完整卡号与安全码不得写入 URL、日志、缓存、消息队列或重试存档。商户必须自行满足适用的 PCI DSS 要求。

当前支付方式与渠道支付参数由超级后台一对一绑定。下游不能指定渠道,也不能提交 channelCodechannelSelectionMode

禁止字段:merchantIdchannelCodechannelSelectionModeproviderCodemetadata 及任何上游渠道专属字段。请求出现未定义字段会被拒绝。

创建支付与支付查询响应字段

按平台订单号、商户订单号查询及支付列表中的每个订单使用同一字段结构。订阅订单的 subscriptionCycleNo 对应通知的 data.cycleNo;失败期也可查,订阅期链接口按真实期数正序返回,不因失败中断。

字段类型说明
paymentNostring网关支付订单号,全局唯一;后续查询和退款使用该字段。
merchantOrderNostring商户创建支付时提交的订单号。
subscriptionNostring/null平台订阅唯一编号,订阅创建时预生成,每期查询及通知一致;普通支付为空。存在编号不代表首期已成功。
amountinteger订单原始金额,单位为分。
feeAmountinteger商户手续费,单位为分。
netAmountinteger商户净额,单位为分;与手续费之和严格等于订单金额。
currencystring订单币种。
paymentMethodstring实际支付方式,当前为 CARD
statusinteger平台支付状态码;只有 5 表示支付成功。
refundStateinteger退款汇总状态:20 未退款、21 部分退款、22 全额退款。
refundedAmountinteger已确认成功的累计退款金额,单位为分。
channelCodestring网关实际使用的渠道编码,只读说明字段,不能在请求中指定。
providerCodestring实际执行请求的 Adapter 编码,只读说明字段。
providerTransactionIdstring/null上游交易号;上游尚未返回时为 null
failureCodestring/null明确失败且上游返回原因时的失败码;否则为 null
failureMessagestring/null明确失败且上游返回原因时的安全失败描述;否则为 null
failureSolutionstring/null上游返回的安全处理建议;未返回时为 null
resultSourceinteger平台结果来源编号。
notificationStatusinteger商户通知生命周期:1 表示尚未生成投递任务;完整编号见“业务状态码”。
issueUrlstring / null3DS 浏览器跳转地址,直接 GET 打开;3DS 时与 nextAction.url 完全一致,无 3DS 时为 null。不参与支付状态判断,不是请求中的 returnUrl。
nextActionobject为已接入商户保留 type、url、parameters;不再返回 method 属性。3DS 直接 GET 打开 url,新接入建议读取同级 issueUrl。不判断或驱动任何业务。
aggregateVersioninteger订单聚合版本,用于识别异步事件先后关系。
createdAtstring创建时间,东八区 yyyy-MM-dd HH:mm:ss
paidAtstring/null支付成功时间:渠道有精确时间则使用渠道时间,没有则取首次确认成功时的当前时间并保存;未成功为空。查询和重发不重新取时,历史空值不回填。
subscriptionCycleNointeger/null订阅期数:首期为 1,首次续订为 2,与成功通知 data.cycleNo 相同;普通支付为 null。查询不会猜测或重新编号。
subscriptionPeriodStartstring/null本期已保存的平台账期开始(含);普通支付、首期未成功时为空。
subscriptionPeriodEndstring/null本期已保存的平台账期结束(不含);失败续订仍保留账期。下一期开始等于上一期结束。
completedAtstring/null已保存的结果完成时间:上游精确时间或首次确认终态时的平台时间;未记录时为 null,不是本次查询时间。所有时间固定东八区 yyyy-MM-dd HH:mm:ss。

创建支付响应示例

{
  "code": 200,
  "message": "Success",
  "data": {
    "paymentNo": "P84000000000000001",
    "merchantOrderNo": "ORDER-20260820-001",
    "amount": 1234,
    "feeAmount": 20,
    "netAmount": 1214,
    "currency": "USD",
    "paymentMethod": "CARD",
    "status": 3,
    "refundState": 20,
    "refundedAmount": 0,
    "channelCode": "ELANLINK",
    "providerCode": "ELANLINK",
    "providerTransactionId": null,
    "failureCode": null,
    "failureMessage": null,
    "failureSolution": null,
    "resultSource": 4,
    "notificationStatus": 1,
    "issueUrl": null,
    "nextAction": {
      "type": 1,
      "url": null,
      "parameters": {}
    },
    "aggregateVersion": 1,
    "createdAt": "2026-08-21 15:30:00",
    "paidAt": null
  },
  "requestId": "req_..."
}
GET/payments/{paymentNo}查询支付
GET/payments?merchantOrderNo=...按商户订单号查询

支付列表查询参数

参数是否必传说明
merchantOrderNo非必传商户订单号。传入时执行当前商户范围内的精确查询并返回单个订单,不使用分页。
status非必传支付状态。未传表示不按状态过滤。
page非必传列表页码,从 1 开始,默认 1。按商户订单号精确查询时忽略。
pageSize非必传每页数量,范围 1–200,默认 50。按商户订单号精确查询时忽略。
主要状态1 已创建3 处理中5 成功6 失败7 已取消8 已过期

当前 Elanlink 仅开放直连,不返回 FORM_POST 或 IFRAME 托管页动作。HTTP 成功且同步响应包含非空 issuer_url 时,创建结果为 3(处理中),在 data 内同时返回 issueUrl 和 THREE_DS nextAction,两处地址完全一致。浏览器直接 GET 打开,不构造 POST 表单。nextAction 保留 type、url、parameters,不再输出 method;后续支付结果仍只由渠道异步通知或平台主动查单确认,地址字段不参与状态迁移。

3DS 过渡响应字段示例(data 内,非完整订单)

{
  "issueUrl": "https://issuer.example/3ds?order_no=P...",
  "nextAction": {
    "type": 7,
    "url": "https://issuer.example/3ds?order_no=P...",
    "parameters": {}
  }
}

以上地址仅为格式示例。实际返回地址中的 notify_url、return_url 等参数必须完整保留;没有传 returnUrl 的商户可自行补充 return_url。浏览器返回页不代表支付成功。

04

REFUNDS

退款

POST/payments/{paymentNo}/refunds创建退款
{
  "merchantRefundNo": "REFUND-20260820-001",
  "amount": 500,
  "reason": "Customer request"
}
GET/refunds?page=1&pageSize=50退款列表
GET/refunds/{refundNo}退款详情

退款必须引用当前商户的真实原支付订单,固定使用原支付保存的渠道支付参数 ID 与配置版本;支付参数停用后禁止新退款。退款收费和渠道成本在本次退款创建时固化,预占本金加手续费。累计成功退款与处理中退款本金不得超过可退款金额。

退款响应字段

创建和详情返回 data 对象;列表返回同结构的 data 数组。金额均为整数分,时间为东八区 yyyy-MM-dd HH:mm:ss。

字段说明
refundNo平台退款号
merchantRefundNo商户退款单号
paymentNo原平台支付订单号
amount退款本金(分)
feeRatePpm本次退款商户比例费率(ppm)
fixedFeeAmount本次退款固定费用(分)
merchantFeeAmount本次商户退款手续费(分)
merchantTotalDebitAmount商户扣款总额:本金加手续费(分)
currency交易币种
status退款状态,5 为成功
providerRefundId上游退款号,未取得为空
createdAt创建时间
succeededAt成功时间,未成功为空
05

SUBSCRIPTIONS

订阅

POST/subscriptions创建订阅

创建上游管理的自动续订。请求必须携带签名请求头和 Idempotency-Key。平台不维护商品、订阅包或价格版本;商户在每次创建时实时提交金额和周期条款。

请求字段

字段类型是否必传规则与说明
merchantOrderNostring必传首期正式支付订单的商户订单号,1–128 位,在当前商户范围内唯一。
customerEmailstring必传客户邮箱,最长 320 位;会转为小写保存并支持精确查询。渠道需要购物者标识时,网关以该值生成渠道 shopper_id,商户无需重复提交。
currencystring必传三位 ISO 4217 大写币种编码,平台统一按两位小数处理。
amountinteger必传正整数分金额,例如 999 表示 9.99。标准模式用于每一期;首期优惠模式用于从首期开始的每个优惠期。
recurringAmountinteger必传预售首期或优惠期结束后的常规正整数分金额。无预售的标准模式必须与 amount 相等;有预售时首期可独立定价;首期优惠模式必须大于 amount
pricingModeinteger必传1 标准订阅,2 首期优惠。计价方式与预售相互独立。
discountCyclesinteger必传从首期开始连续享受优惠的期数。标准模式固定为 0;首期优惠模式必须至少为 1,有限订阅时不能超过总期数。
contractStartstring(date)非必传预售条款,格式 yyyy-MM-dd。首期一次性区间在该日结束,常规周期从该日开始;只能有一个预售首期,可与标准计价或首期优惠组合。功能开关关闭时,携带该字段的请求会被明确拒绝。
planCodestring必传周期单位枚举,只允许 DAYWEEKMONTHYEAR;它不是商品或套餐编码。
intervalCountinteger必传正整数,表示每多少个周期单位扣费一次。提交上游前按当前时间预检日期范围,计算结果不得超出 1000–9999 年。
totalCyclesinteger必传包含首期在内的总扣费次数;0 固定表示永久续订。有限期预检最后一期边界,永久订阅只检查单期;无效组合同步拒绝,不创建交易或通知数据。
paymentMethodstring必传支付方式。当前唯一允许值为 CARD
notifyUrlstring非必传订阅成功事件的通知地址,最长 2048 位,必须为 HTTPS。存在时只使用该地址;缺省时回退商户默认 Webhook;两者都没有则拒绝创建。
returnUrlstring非必传首期支付发生 3DS 时的客户浏览器 HTTPS 返回地址,最长 2048 位,网关自动拼接;商户域名报备只记录事实,不参与交易准入。不提交时商户可自行拼接。不能用该页面判断订阅生效。
paymentMethodDataobject必传网关统一的直连卡支付资料,完整字段见下表。订阅支付与单次支付使用同一套卡资料契约。

paymentMethodData 字段

字段类型是否必传规则与说明
firstNamestring必传持卡人名字,1–100 位。
lastNamestring必传持卡人姓氏,1–100 位。
cardNumberstring必传卡号,12–23 位数字,可包含空格;网关收到后会移除空格。仅用于本次上游请求,不落库、不写日志。
expirationYearstring必传四位到期年份,例如 2029
expirationMonthstring必传两位到期月份,范围 0112
securityCodestring必传3–4 位卡安全码。仅用于本次上游请求,绝不落库、缓存或记录日志。
shopperIpstring非必传付款客户公网 IP,最长 45 位;建议直连交易传递。
shopperPhonestring非必传付款客户电话,最长 64 位,建议包含国际区号。
billingCountrystring非必传账单国家,两位 ISO 3166-1 alpha-2 编码,例如 US;网关会转为大写。
billingStatestring非必传账单州/省,最长 128 位。
billingCitystring非必传账单城市,最长 128 位。
billingAddressstring非必传账单详细地址,最长 512 位。
billingPostalCodestring非必传账单邮政编码,最长 32 位。
osstring非必传客户操作系统,最长 64 位,用于风控或 3DS。
browserstring非必传浏览器或 User-Agent 信息,最长 512 位。
browserLanguagestring非必传浏览器语言,最长 32 位,例如 en-US
timeZonestring非必传客户端时区信息,最长 16 位。
resolutionstring非必传屏幕分辨率,最长 32 位,例如 1920x1080
challengeWindowSizestring非必传3DS Challenge 窗口规格,最长 8 位。
sessionIdstring非必传商户侧客户会话编号,最长 128 位;不得包含卡号或安全码。

请求示例

{
  "merchantOrderNo": "ORDER-20260820-001",
  "customerEmail": "customer\u0040example.com",
  "currency": "USD",
  "amount": 999,
  "recurringAmount": 2999,
  "pricingMode": 2,
  "discountCycles": 3,
  "planCode": "MONTH",
  "intervalCount": 1,
  "totalCycles": 0,
  "paymentMethod": "CARD",
  "notifyUrl": "https://merchant.example.com/api/subscription/notify",
  "returnUrl": "https://merchant.example.com/subscription/return",
  "paymentMethodData": {
    "firstName": "Ada",
    "lastName": "Lovelace",
    "cardNumber": "CARD_NUMBER",
    "expirationYear": "2029",
    "expirationMonth": "08",
    "securityCode": "CVV",
    "billingCountry": "US"
  }
}

当前订阅只走直连。Elanlink 接受 DAY、WEEK、MONTH、YEAR;平台映射为上游 interval,并将 totalCycles 映射为 billing_cycle。首期优惠时,上游外层 amount 使用优惠期实扣金额,订阅字符串中的 contract_amount 使用优惠结束后的标准金额,discountCycles 映射为 promotion_cycle。预售时 contractStart 映射为上游 contract_start;它是独立条款,因此可与首期优惠同时提交。Elanlink 要求的 shopper_id 由网关使用规范化后的 customerEmail 生成。首期和每次续期都是独立正式支付订单;优惠期内沿用冻结的优惠金额,超过优惠期后使用冻结的标准金额。

禁止字段:intervalintervalUnitbillingCyclecontractcontractNamecontractAmount、商品或套餐编号、channelCodeproviderCode 及任何上游签名字段。

创建订阅同步响应

subscriptionNo 在请求校验通过、首期支付订单落库时预生成,早于上游调用,不依赖渠道订阅 ID。订单已创建后,无论同步支付状态为处理中或失败,都保留并返回这个编号;同一幂等请求重放返回原编号,不重复生成。首订成功和各期续订通知均使用同一个 subscriptionNo,期数由 cycleNo 区分。校验失败且未创建订单时,不返回订阅号。

同步响应使用标准支付对象,只表示首期正式支付订单的当前状态。平台在创建首期支付订单时生成唯一 subscriptionNo,保存到支付订单并同步返回;该编号只用于结果关联,不表示订阅已经生效。只有上游异步通知或主动查单明确确认首期成功后,平台才创建订阅管理数据,并通过 subscription.activated 异步通知确认生效。上游同步成功响应不能直接激活订阅。

创建订阅响应示例

{
  "code": 200,
  "message": "Success",
  "data": {
    "paymentNo": "P84000000000000003",
    "merchantOrderNo": "ORDER-20260820-001",
    "orderInitiator": 1,
    "subscriptionNo": "8c8de29c90ac4866b2067cb442b6f229",
    "amount": 2999,
    "feeAmount": 0,
    "netAmount": 2999,
    "currency": "USD",
    "paymentMethod": "CARD",
    "status": 3,
    "providerCode": "ELANLINK",
    "providerTransactionId": null,
    "issueUrl": null,
    "nextAction": {
      "type": 1,
      "url": null,
      "parameters": {}
    },
    "resultSource": 4,
    "createdAt": "2026-08-21 15:30:00"
  },
  "requestId": "req_..."
}
GET/subscriptions/{subscriptionNo}订阅详情
GET/subscriptions/{subscriptionNo}/payments完整支付链
GET/subscriptions?customerEmail=...组合查询
POST/subscriptions/{subscriptionNo}/cancel取消订阅(必须传 Idempotency-Key)

订阅查询参数

参数是否必传说明
subscriptionNo非必传按网关订阅号精确查询。
customerEmail非必传按规范化邮箱精确查询,不做模糊匹配。
effectiveStatus非必传按生效状态筛选:9 生效中,8 已到期。
renewalStatus非必传按续存状态筛选:9 续存,7 已取消,11 已自然完成。
page非必传页码,从 1 开始,默认 1。
pageSize非必传每页数量,范围 1–200,默认 50。

订阅关系与扣费结果分开:续存中 renewalStatus=9 的订阅保持 effectiveStatus=9,单期扣费失败不会取消或终止订阅,也不代表失败期已支付。取消或自然完成后,才按实际已支付账期的开始和结束判断生效状态。

当期扣费结果(订阅管理响应)

“当期”是已存在的最大明确期数,不按当前时间预测下一期。没有新一期通知就保持原结果;失败不重试扣款,历史失败订单完整保留。

字段类型说明
currentPaymentNostring / null当期正式支付订单号。
currentCycleNointeger / null已存在最大明确期数。
merchantId / initialMerchantOrderNo / initialPaymentNostring所属商户号、商户首订订单号、平台首订订单号,固定关联真实首期订单。
initialProviderTransactionId / providerSubscriptionIdstring / null直接上游首订订单号和订阅号。
processorCode / initialProcessorTransactionId / processorSubscriptionIdstring / null上上游机构及首订、订阅编号,未知时为空,不代填、不自动切换渠道。
maskedCardNumberstring / null脱敏支付卡号,最多前六后四,中间星号;缺失时为空。档案不保存收费、通知地址或渠道支付参数。
subscriptionStart / subscriptionEndstring / null整个档案的生效区间。开始取首期已固化账期;有限结束按首期锚点和限定期数计算,永久续存的结束为 null。取消只终止续存,结束取已支付期限,不取取消时间。缺少原始锚点时不编造日期。
activePeriodNo / activePeriodStart / activePeriodEndinteger / string / null查询时刻所在的真实期号及区间,左闭右开;没有对应实际期时三个字段都为 null。续存中的失败期也可为当前期,不代表已支付;不与最大已收到期次混用。
currentPaymentStatusinteger / null该期支付状态,复用支付状态码:5 成功、6 失败。无数据为空,不推定失败。
currentPaymentFailureCodestring / null该期失败码,无则为空。
currentPaymentFailureMessagestring / null该期失败原因,无则为空。
currentPaymentPeriodStart / currentPaymentPeriodEndstring / null该期已保存的开始/结束时间,固定东八区 yyyy-MM-dd HH:mm:ss;不表示未来扣款安排。
currentPeriodStart / expiresAtstring最大已存在明确期次的开始/结束时间。失败期也会推进这组真实期链边界,可用于核查下一期通知是否缺失;它不代表该期已支付,也不直接决定生效状态。

支付链接口返回该订阅的每一期正式支付订单,包括扣款失败的期数。subscriptionCycleNo 是上游明确提供的真实期数,缺失时网关不会猜测或补造。续订必须先找到精确上一期;上一期缺失时异步重试,不跳期处理。

平台账期从首期明确支付成功开始计时。每期订单保存 subscriptionPeriodStart(含)与 subscriptionPeriodEnd(不含),下一期开始等于上一期结束;月和年始终以首期日期为锚点,避免月底漂移。失败续订仍有账期,但不延长已支付有效期;通知迟到或重复不会移动账期。首期未成功和普通支付的这两个字段为空。账期由平台管理,不代表渠道返回的扣款排程。

订阅支付订单字段

字段类型说明
paymentNostring该期网关支付订单号,全局唯一。
merchantOrderNostring该期内部订单引用。
orderInitiatorinteger1 表示商户发起首期;2 表示上游续订通知触发。
subscriptionNostring所属网关订阅号,也是订阅管理数据唯一 ID。
subscriptionCycleNointeger上游明确提供或确认的真实期数,从 1 开始;网关不会猜测缺失期数。
subscriptionPeriodStartstring / null本期平台账期开始,东八区 yyyy-MM-dd HH:mm:ss;包含此时刻。首期未成功时为空。
subscriptionPeriodEndstring / null本期平台账期结束,东八区 yyyy-MM-dd HH:mm:ss;不包含此时刻,也是下一期开始。失败续订同样保留此值。
amountinteger该期金额,单位为分。
feeAmountinteger该期商户手续费,单位为分。
netAmountinteger该期商户净额,单位为分。
currencystring该期币种。
paymentMethodstring该期支付方式。
statusinteger支付订单状态。扣款失败仍完整保留为 6
providerCodestring处理该期支付的渠道 Adapter 编码。
providerSubscriptionIdstring/null首订确认的渠道订阅关联值。Elanlink 为 recurring_id
providerTransactionIdstring/null该期上游交易号。
providerEventIdstring/null确认该期当前结果的稳定上游事件号。
providerStatusstring/null渠道返回的综合状态原值。
providerOrderStatusstring/null该期扣款状态原值,不与订阅状态混用。
providerRecurringStatusstring/null上游订阅状态原值。
providerDeductionDatestring/null上游明确返回的该期扣款日期。
providerContractNamestring/null上游返回的原始合同名称,仅作为渠道证据展示。
failureCodestring/null该期扣款失败码。
failureMessagestring/null该期安全失败描述。
failureSolutionstring/null上游返回的安全处理建议。
resultSourceinteger平台结果来源编号。
notificationStatusinteger本期商户通知生命周期;尚未生成投递任务时为 1,完整取值见“业务状态码”。
attemptedAtstring/null实际发起扣款或收到扣款结果的时间。
completedAtstring/null该期已保存的结果完成时间(上游精确时间或首次确认终态时的平台时间),与支付查询一致;未记录时为 null。失败期也返回已有时间,不用查询时间补造。
createdAtstring该期支付订单创建时间。
paidAtstring/null该期成功时间:渠道时间优先,无精确渠道时间时取首次确认成功的当前时间并固定。未成功为空,后续查询不改写。
06

PAYOUTS

代付

代付渠道尚未完成生产验收。接口契约保留,但只有后台启用代付能力后才可调用。
POST/payouts创建代付
GET/payouts?page=1&pageSize=50代付列表
GET/payouts/{payoutNo}查询代付
POST/payouts/{payoutNo}/query主动查询上游

请求字段

请求须携带商户签名和 Idempotency-Key。使用后台绑定的唯一代付参数;商户不能指定渠道。支付方式和收款资料须满足已启用渠道能力。

字段规则
merchantPayoutNo必填,商户内唯一,最长 128 字符。
amount必填,正整数分;按渠道代付单笔范围及商户独立代付日限额校验,不占用收款额度。
currency必填,三位币种代码,必须在绑定参数支持币种内。
paymentMethod必填,最长 64 字符,使用后台启用的支付方式编码。
recipientType必填,从 1 开始的收款方类型;按已启用渠道契约提供。
recipientName必填,收款人名称,最长 128 字符。
recipientCountry必填,两位国家代码。
recipientDetails必填,1–64 项字符串键值;键最长 64 字符,值最长 2048 字符。完整收款资料仅用于本次上游调用;银行账户、IBAN、路由号等持久化前替换为 *,不提供恢复原值的接口。
purpose可选,用途,最长 500 字符。
notifyUrl可选,HTTPS 订单通知地址,最长 2048 字符。未提供时使用唯一启用的默认 Webhook;两者都没有时拒绝创建。

提交前原子预占本金加手续费。币种账户缺失时按零余额进入建账流程;余额不足则回滚,不发起上游代付。成功扣减冻结资金,明确失败、取消或关闭释放;未知结果保持冻结并查单确认。

代付响应字段

创建和详情返回 data 对象;列表返回同结构的 data 数组。金额均为整数分,时间为东八区 yyyy-MM-dd HH:mm:ss。

字段说明
payoutNo平台代付号
merchantPayoutNo商户代付单号
amount代付本金(分)
feeAmount商户代付手续费(分)
totalDebitAmount商户扣款总额:本金加手续费(分)
currency交易币种
paymentMethod支付方式
channelCode渠道编码
providerPayoutId上游代付号,未取得为空
status代付状态,5 为成功
resultSource结果来源整数码
recipientAccountMask平台生成的固定掩码 *,不属于请求字段
createdAt创建时间
paidAt成功时间,未成功为空
07

FUNDS

资金流水

GET/funds/ledger?page=1&pageSize=50查询当前商户资金流水

资金流水由支付、退款、代付或人工调整产生,只读返回。每条包含 entryNobusinessTypebusinessNoentryType、有符号整数分 changeAmountcurrencyoccurredAt。接口只返回当前已认证商户自己的资金流水;渠道支付参数余额及其变化记录属于内部运营数据,不通过商户 API 暴露。不同币种不得直接汇总。

08

REPORTS

每日交易报表

GET/daily-reports?from=2026-08-01&to=2026-08-20&status=3查询日报
GET/daily-reports/{yyyy-MM-dd}/download下载 Excel

每天 01:00(Asia/Shanghai)生成前一日数据;即使没有交易也会生成空报表。下载接口不接受临时维度筛选。

列表可传 fromto(yyyy-MM-dd)、statuspagepageSize,默认第 1 页、每页 20 条,最多 200 条。成功响应 data{items, page, pageSize, total},不是直接返回数组。

items 字段说明
summaryNoreportDate报表编号、报表日期
paymentCountpaymentSuccessCountpaymentFailedCount支付总笔数、成功笔数、失败笔数
refundCountrefundSuccessCount退款总笔数、成功笔数
payoutCountpayoutSuccessCountpayoutFailedCount代付总笔数、成功笔数、失败笔数
fileNamefileSizefileHashrowCount文件名、字节数、文件摘要、明细行数
statusgeneratedAtdownloadUrl报表状态、生成时间、下载地址;下载失败不能当作空报表
currencies按币种分列的金额汇总,全部为整数分;包括支付/退款/代付金额、手续费、人工增减和净变动。完整字段见 OpenAPI 的 DailyCurrencySummary,不得跨币种相加。
09

WEBHOOK

商户异步通知

只有支付或订阅扣款明确成功后才投递。请求提供 notifyUrl 时只使用该地址;未提供时回退商户默认 Webhook;两者都没有则交易创建失败。处理中、需要客户端动作、失败和未知结果都不产生下游支付状态通知。

1结果确认
2业务事件持久化
3异步投递
4响应 SUCCESS

商户回调响应体去除首尾空白后必须精确等于 SUCCESS,否则视为失败并进入延迟重试。不要仅依赖 HTTP 状态码。

首期订阅成功事件类型为 subscription.activated,其 data 携带创建响应中已经返回的平台 subscriptionNo、首期 paymentNocycleNo=1,用于确认该订阅已经生效;续订成功事件为 subscription.renewed。两类成功事件的 data 还包含 subscriptionPeriodStartsubscriptionPeriodEnd,与对应订单查询结果一致。失败期保留在查询链中但不投递失败通知。

订阅支付通知字段(首订与续订相同)

字段路径类型必有说明
data.subscriptionNostring平台订阅唯一 UUID,与创建响应中的订阅号一致;不是期数或渠道订阅号。
data.paymentNostring本期正式支付订单号,每一期不同。
data.cycleNointeger实际期数:首期为 1,第一次续订为 2,依次递增。中间一期失败时不重新编号;第 2 期失败、第 3 期成功,通知仍为 3。字段在 data 内,不在顶层。
data.subscriptionPeriodStartstring本期平台账期开始,包含此时刻,下一期开始等于本期结束。
data.subscriptionPeriodEndstring本期平台账期结束,不包含此时刻。重发不会重算。
data.amountinteger / int64本期实际支付金额,单位为分,100 表示 1.00;不是累计金额。
data.currencystring本期支付币种,例如 USD。
data.statusinteger本期支付状态,成功为 5;不是订阅续存或生效状态。
data.paidAtstring/null本期已保存的成功时间:渠道有精确时间则取渠道时间,没有则取首次确认成功的当前时间。不是投递时间,重试和手动重发保持原值;历史空值不回填。
occurredAtstring商户事件建立时间,在顶层;不是本次投递时间。重试、手动重发保持原值。

上述业务时间统一使用东八区 yyyy-MM-dd HH:mm:ss。以下为第 2 期成功通知的格式示例,并非真实交易记录。既有历史事件保留原始内容;新增字段不会通过重发补写到历史报文。

{
  "eventId": "evt_example_subscription_cycle",
  "merchantId": "83946179674509312",
  "eventType": "subscription.renewed",
  "aggregateType": "PAYMENT",
  "aggregateId": "P12345678901234567",
  "aggregateVersion": 2,
  "data": {
    "subscriptionNo": "0123456789abcdef0123456789abcdef",
    "paymentNo": "P12345678901234567",
    "cycleNo": 2,
    "subscriptionPeriodStart": "2026-08-28 10:00:00",
    "subscriptionPeriodEnd": "2026-08-29 10:00:00",
    "amount": 100,
    "currency": "USD",
    "status": 5,
    "paidAt": "2026-08-28 10:00:03"
  },
  "occurredAt": "2026-08-28 10:00:04"
}

单次支付成功通知示例

{
  "eventId": "evt_...",
  "merchantId": "83946179674509312",
  "eventType": "payment.succeeded",
  "aggregateType": "PAYMENT",
  "aggregateId": "P...",
  "aggregateVersion": 2,
  "data": {
    "paymentNo": "P...",
    "status": 5,
    "amount": 1234,
    "currency": "USD"
  },
  "occurredAt": "2026-08-20 13:00:00"
}
请求头说明
X-Gateway-Event-Id稳定事件编号,用于业务幂等
X-Gateway-Timestamp签名时的 Unix 秒
X-Gateway-Signature64 位小写十六进制 HMAC-SHA256
signedText = X-Gateway-Timestamp + "." + rawRequestBody
expected = lowercase_hex(
  HMAC_SHA256(webhookSecret, signedText)
)

Webhook Secret 是商户级单一凭据,不属于某个 URL,也不发送 Secret 版本。商户后台允许保存多条默认地址,但同一时间只启用一条;订单传入 notifyUrl 时仍只投递该订单地址。新增或切换地址不会改变 Secret;商户生成新的 Webhook Secret 后,旧 Secret 继续用于通知签名 10 分钟,随后自动使用新 Secret。

这 10 分钟内不允许再次轮转 Webhook Secret;后台显示剩余时间并禁用轮转操作,服务端也会拒绝并发或绕过页面的再次轮转。请在过渡期结束前部署新 Secret,并在过渡期同时接受新旧签名。该限制不改变 API Secret 的独立凭据有效期规则。

验签必须使用收到的 UTF-8 原始请求体。首次失败后依次延迟 1、5、15、30、60、360、1440 分钟重试,总计最多投递 8 次。

10

BUSINESS STATUS

业务状态码

平台状态使用同一套全局编号:同一个数字在任何业务中含义完全一致,不需要的编号直接留空。商户 API、Webhook、商户后台和超级后台的内部状态字段统一返回整数编号。英文状态仅作为文档语义名称展示,不作为接口值。0 只可作为查询条件中的“全部/未指定”,永远不是真实业务状态。

平台编号英文值中文描述适用范围
1CREATED已创建支付、退款、代付、通知聚合
2PENDING等待处理通知任务、Inbox、日报、对账批次
3PROCESSING处理中支付、退款、代付、任务、日报、对账批次
4RETRYING等待重试可恢复的异步任务
5SUCCEEDED成功支付、退款、代付、任务、日报、对账批次
6FAILED失败支付、退款、代付、任务、日报、对账批次
7CANCELLED已取消支付、退款、代付、订阅、任务
8EXPIRED已过期支付等有有效期的业务
9ACTIVE有效订阅
11CLOSED已关闭代付人工关闭、有限期订阅自然结束
12ENABLED启用可启停资源和能力
13DISABLED停用可启停资源和能力
14DRAFT草稿配置版本
15PUBLISHED已发布配置版本
16HISTORICAL历史版本配置版本
17OPEN待处理对账差异
18RESOLVED已解决对账差异
19IGNORED已忽略对账差异
20NOT_REFUNDED未退款支付订单退款汇总
21PARTIALLY_REFUNDED部分退款支付订单退款汇总
22FULLY_REFUNDED全额退款支付订单退款汇总
23NORMAL正常商户运行模式
24STOPPED停止使用商户运行模式
25RECEIVE_ONLY只能收款,不允许退款或代付商户运行模式
26PAYOUT_ONLY只能代付,不允许收款或退款商户运行模式
27PORTAL_ONLY仅商户后台商户运行模式
28API_READ_ONLYAPI 只读商户运行模式

各商户 API 字段允许值

字段允许值判定说明
支付订单 status135678只有 5 表示支付成功
退款订单 status13567只有 5 表示退款成功
代付订单 status1356711只有 5 表示代付成功
订阅 effectiveStatus899 生效中;8 已到期
订阅 renewalStatus79119 续存;7 已取消;11 有限期订阅已自然完成
商户通知 notificationStatus12345671 表示尚未生成投递任务;只有 5 表示商户已正确响应 SUCCESS
支付退款汇总 refundState202122分别表示未退款、部分退款和全额退款
日报 status2356直接返回平台整数编号:等待处理、处理中、成功、失败;查询条件 0 表示全部
渠道隔离:providerStatusproviderOrderStatusproviderRecurringStatus 是上游渠道原始字符串,只作为证据展示。它们不属于平台状态码,不能跨渠道比较,也不能用于判断平台业务成功。
11

RESPONSE CODES

第一层响应码

code=200 只表示本次 API 请求处理成功。非 200 表示接口处理失败,datanull;交易结果仍必须读取业务对象的 status

codeHTTPmessage中文描述
200200Success接口处理成功,不代表交易成功
1001400Invalid request请求内容或业务参数无效
1002400Request validation failed请求字段校验失败
1003404Resource not found资源不存在
1004409Idempotency conflict幂等键与首次请求内容冲突
1005409Resource state conflict当前资源状态不允许该操作
1006405Method not allowedHTTP 方法不允许
1007413Request body is too large请求体超过大小限制
1101401Authentication required缺少认证信息
1102401Invalid merchant credential商户凭据无效
1103401Invalid request timestamp请求时间戳格式无效
1104401Request timestamp expired请求时间戳已过期
1105401Invalid request nonceNonce 格式无效
1106401Replay request detected检测到重复请求
1107401Invalid request signature请求签名无效
1108403Access denied当前身份没有接口或页面访问权限
1202400Invalid callback URL回调地址不是有效 HTTPS URL
1203409Credential rotation is still in progressWebhook Secret 尚在过渡期,暂不能再次轮转
2001404Payment order not found支付订单不存在
2101422Transaction amount is outside the allowed range交易金额超出允许范围
2102422Daily transaction count limit exceeded超过每日交易笔数限制
2103422Daily transaction amount limit exceeded超过每日交易金额限制
2104403Transaction is not allowed商户当前状态或能力不允许交易
2105409Risk usage update conflict风控用量并发更新冲突
3001503Payment provider is unavailable支付渠道不可用
3002202Payment provider result is unknown上游结果暂时无法确认
4001401Invalid provider webhook signature上游通知签名无效
9001500Internal server error平台内部错误
9002500Report file is missing or unreadable已发布报表文件缺失或不可读,需恢复原文件,仍记录异常事件。