Z Zise Developers

提前把收款人送去上游建档(不动一分钱

POST /v1/remit/payees/{id}/verify scope: remittances:write
代会员调用 · 必带 x-on-behalf-of

它解决的是什么

我方的收款人是上游无关的实体:建档那一刻一个上游接口都不调

(提前替用户选一家供应商建过去,会把这条记录钉死在今天这一家)。

上游建档默认发生在下单分发那一刻。

代价是失败点在冻结之后:上游对收款人的拒绝是终态

而订单此时已经把会员的钱从可用余额冻进锁定桶,只能等我方人工处置。

上游拒绝的理由不止格式(重复添加、制裁名单命中、它自己的银行目录里

查不到这家行)—— 格式那一类我方本地能挡,其余的**第一次发生时一定

要花掉一次冻结**。

这个端点就是那个问句:把上游建档提前到没有钱牵涉其中的时候。

建议在 POST /v1/remit/payees 成功之后立刻调一次,

并在 upstream_statusactive 之前不要放行下单。

它做什么、不做什么

  • 不动钱:不建单、不冻结、不扣你的预付;
  • 不接受你指定供应商或上游账户。那两维由我方按 line 推导 ——

一个拼错的值会在上游建出第二条指向同一个银行账户的记录,

而此后没有任何一条业务路径会用到它(上游没有删除接口);

  • 不重试 failed。那是终态,原样再发一次一定还是拒。

幂等

这个端点不要 x-idempotency-key,可以放心轮询。

原因是幂等层会在 24 小时内回放首次响应 —— 你拿同一把键轮询会永远

读到那一次的 pending,而收款人可能早就 active 了。

真正的幂等保证更强且在我方这一侧:送上游那把键**落在我方库里、

重试沿用**,所以同一条收款人无论调多少次都只会在上游产生一条记录。

返回什么

upstream_statusGET /v1/remit/payees/{id} 同一套取值

(这里只会出现 pending / active / failed)。

failedreason 是我方自己的词表:

  • upstream_rejected 上游拒了这条数据。具体理由要人看 ——

上游没有错误码表,只有一句英文自由文本,逐字转发只会让你按一句

会变的话写分支。处置:让用户改收款人重建一条,或联系我方;

  • upstream_gone 上游那一侧的记录不见了(曾建成、后被删);
  • payee_not_found / no_beneficiary_id 我方这一侧的异常,请报工单。

沙盒同样打真实上游(这条线没有上游沙盒)。也就是说你在沙盒里

verify 出来的 beneficiary 是真的,而上游没有删除接口。

联调时请用真实、可用的收款账户,别灌测试数据。

路径参数

字段类型必填说明
id string 必填 收款人号。pye_ 前缀可带可不带;剥掉后必须是纯数字。

查询参数

字段类型必填说明
line "express" | "pobo" 可选 按哪条线建档。同一条收款人在两条线下是两条独立的上游记录 (个人线走该会员自己的子账户上下文)—— 两条线都要用就调两次。
字段类型必填说明
x-on-behalf-of string 必填 代哪个会员调用。必须是这条收款人关联到的那个会员。

响应

200OK
{
  "id": "pye_1042",
  "upstream_status": "pending",
  "reason": ""
}
400product_not_available 这条线现在没有可用供应商,或(个人线) 这个会员还没有可用的上游子账户 —— 这不是收款人的问题 · service_unavailable 我方尚未配置上游。
404not_found 这条收款人不在这个会员名下(或 id 不是数字)。
429rate_limited 独立的一道闸(每商户 30 次/分钟)。 每一次未命中都是一次真实的上游写调用,而它在上游产生的是 不可撤销的实体
502upstream_error 上游明确拒了这次调用(凭据 / 参数 / 限流)。
504upstream_timeout 结果不明。 ⚠ 这一档重投是安全的:送上游那把幂等键是我方生成并落库的, 同键重投拿回的是首次那一条,不会在上游建出第二个收款人。
请求
curl -X POST 'https://api.zise.com/v1/remit/payees/{id}/verify' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-on-behalf-of: $MEMBER_ID'
const res = await fetch("https://api.zise.com/v1/remit/payees/{id}/verify", {
  method: "POST",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-on-behalf-of": "$MEMBER_ID",
  },
});
// 金额按字符串读,别让它变成 number
const data = await res.json();
import requests

res = requests.post(
    "https://api.zise.com/v1/remit/payees/{id}/verify",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-on-behalf-of": "$MEMBER_ID",
    },
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()
req, _ := http.NewRequest("POST", "https://api.zise.com/v1/remit/payees/{id}/verify",
    nil)
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-on-behalf-of", "$MEMBER_ID")
res, err := http.DefaultClient.Do(req)
// 金额字段用 string 接,不要 float64
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.zise.com/v1/remit/payees/{id}/verify"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-on-behalf-of", "$MEMBER_ID")
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
// 金额字段用 String / BigDecimal,不要 double
$ch = curl_init('https://api.zise.com/v1/remit/payees/{id}/verify');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-on-behalf-of: $MEMBER_ID',
  ],
]);
$res = curl_exec($ch);
// 金额用 bcmath / 字符串,不要 floatval
200
{
  "id": "pye_1042",
  "upstream_status": "pending",
  "reason": ""
}