Skip to content

商户 Webhook

商户 Webhook 用于接收 FuturePay UCard 主动发送的业务事件通知。

接入流程

  1. 登录 FuturePay 商户管理后台,在 UCard 的“租户回调配置”中填写自己的 Webhook URL 并启用。每个商户同时只允许启用一个回调地址。
  2. 在该 URL 上提供可公开访问的 HTTP 接口,接收 FuturePay 发送的 POST application/json 请求。
  3. 使用请求 Header 和未经修改的原始请求体完成平台签名校验。
  4. 读取 Payload 中的 eventType,根据事件类型执行不同的业务处理。
  5. 使用 eventNo 做幂等处理,成功接收后返回 HTTP 2xx。

所有支持的 UCard 事件都会发送到同一个已启用的 Webhook URL。商户不需要为不同事件配置多个地址,应在自己的接收服务中按 eventType 分发。

历史事件兼容说明

新建事件统一使用 schemaVersion: 2,且 eventType 只表示业务场景。为保持原始请求体、签名和重放幂等不变,历史 PENDING/DEAD 事件重放时仍可能携带状态型 eventType,卡提现旧事件也可能没有 eventType。商户应继续以 eventNo 幂等,并对历史格式保留兼容解析。

回调请求

FuturePay 使用以下请求方式:

说明
HTTP 方法POST
Content-Typeapplication/json
请求地址商户管理后台中已启用的 Webhook URL
请求超时10 秒
成功响应任意 HTTP 2xx

HTTP 3xx、4xx、5xx、连接异常或超时均视为投递失败。建议使用 HTTPS,并在 10 秒内完成验签和可靠落库;耗时业务可在落库后异步处理。

签名 Header

每次 Webhook 请求都会携带以下 Header:

Header说明
X-FP-TimestampFuturePay 生成签名时的毫秒级时间戳。
X-FP-Api-KeyFuturePay 平台 Ed25519 公钥 hex。
X-FP-SignatureFuturePay 平台签名 hex。
X-FP-Body-Hash原始请求体的 SHA-256 hex。

签名原文为:

text
X-FP-Timestamp|RAW_CALLBACK_BODY

验签时必须使用收到的原始请求体,不能先解析 JSON 再重新序列化。完整算法和密钥说明见 加签说明

公共字段

字段类型说明
schemaVersionintegerPayload 结构版本。新建事件固定为 2
eventNostringWebhook 事件唯一编号,也是商户幂等键。自动重试和人工重放不会改变该值。
eventTypestring业务场景,用于分发到对应业务处理器,不包含成功或失败状态。
statusstring当前场景的业务状态。具体含义以对应事件为准。
failCodestring失败码;没有失败信息时为空。
failMessagestring失败原因;没有失败信息时为空。
occurredTimestring事件发生时间,格式为 yyyy-MM-dd HH:mm:ss

不同事件会携带各自的业务字段。商户应先识别事件类型,再按对应结构解析,不要假设所有事件 Payload 完全相同。

事件类型

eventType说明
CARD_OPENING开卡场景;通过 status 判断成功或失败。
CARD_RECHARGE卡充值场景;通过 status 判断成功或失败。
CARD_WITHDRAWAL卡提现场景;通过 status 判断成功或失败。
CARD_CONSUMPTION卡消费场景;通过 statusfeeCharged 和失败字段判断交易及手续费结果。
CARD_MONTHLY卡月费场景;通过 status 判断扣取成功或失败。

事件业务字段

除公共字段外,不同事件包含以下业务字段:

eventTypestatus 说明业务字段
CARD_OPENINGSUCCESSFAILEDcardOrderNorequestNofeeAmountassetCodecardIdcardAccountIdlast4expiryMonthexpiryYear
CARD_RECHARGESUCCESSFAILEDorderNorequestNocardIdamountcurrencyfeeAmountfeeCurrency
CARD_WITHDRAWALSUCCESSFAILEDorderNorequestNocardIdamountfeeAmountplatformFeeAmounttenantFeeAmounttotalAmountcurrency
CARD_CONSUMPTION卡交易终态,例如 SUCCESSCOMPLETEDSETTLEDFAILEDREJECTEDCANCELLEDCANCELEDproviderTransactionIdcardIdcardAccountIdamountassetCodecountryCodefeeChargedtransactionFeeauthorizationFeetotalFee
CARD_MONTHLYSUCCESSFAILEDcardIdbillingMonthamountassetCode

CARD_CONSUMPTIONstatus 表示卡交易状态;手续费是否处理成功应结合 feeChargedtotalFeefailCodefailMessage 判断。

当前 CARD_WITHDRAWALamounttotalAmount 均表示本次提现总扣款金额,即提现本金与手续费之和。

卡消费通知示例

本次卡消费通知使用 countryCode 表示消费国家或地区代码:

json
{
  "schemaVersion": 2,
  "eventNo": "UCCB202608040001",
  "eventType": "CARD_CONSUMPTION",
  "providerTransactionId": "TXN202608040001",
  "cardId": "CARD001",
  "cardAccountId": "ACCOUNT001",
  "amount": "100.00",
  "assetCode": "USD",
  "countryCode": "US",
  "feeCharged": true,
  "transactionFee": "1.00",
  "authorizationFee": "0.00",
  "totalFee": "1.00",
  "status": "SUCCESS",
  "failCode": null,
  "failMessage": null,
  "occurredTime": "2026-08-04 12:00:00"
}

幂等处理

FuturePay 采用至少一次投递语义,同一个事件可能被多次发送。商户必须以 eventNo 为唯一键处理幂等,不能只使用 eventType、订单号或交易号去重。

推荐处理顺序:

  1. 校验平台签名。
  2. 在数据库中插入 eventNo,并建立唯一约束。
  3. 如果 eventNo 已存在,直接返回 HTTP 2xx。
  4. 根据 eventType 执行业务处理。
  5. 提交本地事务后返回 HTTP 2xx。

如果先返回 2xx、后异步落库,进程异常可能造成通知丢失。若业务处理耗时较长,建议先可靠保存原始事件,再异步消费。

重试规则

  • 首次投递失败后,FuturePay 会继续扫描待投递事件并重试。
  • 每个事件最多自动尝试 3 次。
  • HTTP 非 2xx、连接异常和 10 秒超时都会占用一次尝试。
  • 自动重试以及平台人工重放均保持原始 eventNo 和请求体不变。
  • 三次自动尝试均失败后,平台停止自动投递,但运营人员仍可能人工重放,因此商户不能在任何时间窗口后关闭幂等保护。
  • 商户不应依赖固定重试间隔,也不应假设不同事件严格按发生顺序到达。

接入检查

  • 已在商户管理后台配置并启用正确的 Webhook URL。
  • 接口可接收 POST application/json,并在 10 秒内返回。
  • 使用原始请求体完成 X-FP-* 签名校验。
  • 根据场景型 eventType 分发业务处理,并兼容历史状态型事件格式。
  • 数据库对 eventNo 建立唯一约束。
  • 重复事件返回 HTTP 2xx,不重复执行资金或订单状态变更。