Z Zise Developers
POST /v1/remit/payees

新建或关联收款人(建档不碰上游

Scope remittances:write 代会员调用 · 必带 x-on-behalf-of x-idempotency-key

收款人是上游无关的实体:这一刻我方一个上游接口都不调,只落库。

在建档这一刻替用户选一个 provider 建过去,等于把一条本该跨上游共用

的记录钉死在今天启用的那一家。上游建档发生在下单分发那一步。

推论有两条,都会影响你的产品设计:

① 建档成功不代表这个收款人一定汇得出去 —— 格式我方尽力校了

(见 GET /v1/remit/payee-form-schema 下发的 pattern),

但上游还有它自己的判据;

② 建档很快、很便宜、可以让用户随时来一遍。

三种结果,看 outcome

  • created 全新的收款人;
  • linked 这个账户我方已经有了,且户名一致 —— 关联,不是重复创建
  • review 这个账户我方已经有了,但户名不一致。仍然会关联成功

201),同时把 name_mismatch 落库。你应当在自己的界面上

让用户复核一次户名。

判据是收款人指纹:由走廊四段 + 账户标识(账号 / IBAN /

路由码 / proxy)算出来,户名走副指纹。所以「同一个账户填两遍」

不会造出两条收款人,而「同一个账户换个户名」会被抓出来。

fields 的三条纪律

契约之外的键一律丢弃(不报错,就是不存)—— 别把你自己的

业务字段塞进来;

② 每个值最长 256 字符,超出截断不报错;

③ 我方先归一再校验alnum_upper 的字段会剥掉横杠空格并转大写

(用户从银行 App 复制的账号一定带分隔符,而上游的 pattern

连横杠都不许)。用户键入的原文我方另存一份,争议留证读那份。

⚠ IBAN 除了 pattern,服务端还会做逐国长度 + mod-97 校验位

错误 reason 分档给出(iban_length / iban_checksum),

那决定用户是去数位数还是去核对原件。这道校验不是多余的洁癖:

一个少一位的 IBAN 本地一路放行,到分发那一刻才被上游拒,

而那时收款人已被钉成终态。

前置条件

  • 走廊可用(同 GET /v1/remit/payee-form-schema 的判据,这里再验一遍)
  • 账号 / IBAN / proxy 三个标识至少有一个非空
字段类型必填说明
x-on-behalf-of string 必填 代哪个会员调用。收款人关联落在这个会员名下。
x-idempotency-key string 必填 UUID v4。24 小时内同键同体回放首次结果(含错误)。

请求体

字段类型必填说明
country_code string 必填 收款银行所在国家,两位大写。别名 country
currency string 必填 到账币种,三位大写。
payment_method string 必填 LOCALSWIFT。别名 method
clearing_system string 必填 清算网络,大小写原样。别名 clearing
entity_type "INDIVIDUAL" | "COMPANY" 必填 别名 entity
nickname string 可选 会员给这个收款人起的名字。只属于这一条关联, 别的会员看不到。超过 64 字符截断。
fields object 必填 字段契约里那些 key 的取值,扁平的一层 (键里带点号,不是嵌套对象)。契约之外的键丢弃。{"bank_details.iban": "GB33BUKB20201555555555", …}

响应

201建档成功。三种 outcome 都是 201 —— linked / review 不是错误,是「我方认出这个账户已经在了」。
{
  "id": "pye_1042",
  "outcome": "created",
  "status": "active"
}
400invalid_fields 逐字段校验失败,fields 数组 (每项 {key, reason}reason 取值 required / too_long / pattern / not_in_enum / iban_length / iban_checksum / account_identifier_required / unknown_clearing_system)。 一句笼统的「信息有误」在一张十几个框的表上等于没说。 corridor_not_supported 走廊四段不全 / 未启用 / 受限辖区 / 没有可确认的路由码类型。
409idempotency_key_reused 同一把键换了请求体(或打到了别的端点)。
调用样例
curl -X POST 'https://api.zise.com/v1/remit/payees' \
  -H 'authorization: Bearer $TOKEN' \
  -H 'x-zise-merchant: $MERCHANT_ID' \
  -H 'x-on-behalf-of: $MEMBER_ID' \
  -H 'x-idempotency-key: $(uuidgen)' \
  -H 'content-type: application/json' \
  -d '{
    "country_code": "GB",
    "currency": "GBP",
    "payment_method": "LOCAL",
    "clearing_system": "FASTER PAYMENTS",
    "entity_type": "INDIVIDUAL",
    "nickname": "房东",
    "fields": {
      "first_name": "MARY",
      "last_name": "SMITH",
      "bank_details.account_holder": "MARY SMITH",
      "bank_details.bank_name": "Barclays",
      "bank_details.bank_address": "1 Churchill Place, London",
      "bank_details.swift_code": "BUKBGB22",
      "bank_details.iban": "GB33BUKB20201555555555",
      "bank_details.routing_code_value1": "202015",
      "bank_details.routing_code_type1": "sort_code",
      "address.country": "GB",
      "address.state": "Greater London",
      "address.city": "London",
      "address.street_address": "221B Baker Street",
      "address.postal_code": "NW1 6XE"
    }
  }'
const res = await fetch(
  "https://api.zise.com/v1/remit/payees",
  {
    method: "POST",
    headers: {
      "authorization": "Bearer $TOKEN",
      "x-zise-merchant": "MERCHANT_ID",
      "x-on-behalf-of": "MEMBER_ID",
      "x-idempotency-key": "crypto.randomUUID()",
      "content-type": "application/json"
    },
    body: JSON.stringify({
      "country_code": "GB",
      "currency": "GBP",
      "payment_method": "LOCAL",
      "clearing_system": "FASTER PAYMENTS",
      "entity_type": "INDIVIDUAL",
      "nickname": "房东",
      "fields": {
        "first_name": "MARY",
        "last_name": "SMITH",
        "bank_details.account_holder": "MARY SMITH",
        "bank_details.bank_name": "Barclays",
        "bank_details.bank_address": "1 Churchill Place, London",
        "bank_details.swift_code": "BUKBGB22",
        "bank_details.iban": "GB33BUKB20201555555555",
        "bank_details.routing_code_value1": "202015",
        "bank_details.routing_code_type1": "sort_code",
        "address.country": "GB",
        "address.state": "Greater London",
        "address.city": "London",
        "address.street_address": "221B Baker Street",
        "address.postal_code": "NW1 6XE"
      }
    }),
  },
);
// 金额一律按字符串读,不要 JSON.parse 成 number
const data = await res.json();
import requests

res = requests.post(
    "https://api.zise.com/v1/remit/payees",
    headers={
        "authorization": "Bearer $TOKEN",
        "x-zise-merchant": "$MERCHANT_ID",
        "x-on-behalf-of": "$MEMBER_ID",
        "x-idempotency-key": "$(uuidgen)",
        "content-type": "application/json"
    },
    json={
        "country_code": "GB",
        "currency": "GBP",
        "payment_method": "LOCAL",
        "clearing_system": "FASTER PAYMENTS",
        "entity_type": "INDIVIDUAL",
        "nickname": "房东",
        "fields": {
            "first_name": "MARY",
            "last_name": "SMITH",
            "bank_details.account_holder": "MARY SMITH",
            "bank_details.bank_name": "Barclays",
            "bank_details.bank_address": "1 Churchill Place, London",
            "bank_details.swift_code": "BUKBGB22",
            "bank_details.iban": "GB33BUKB20201555555555",
            "bank_details.routing_code_value1": "202015",
            "bank_details.routing_code_type1": "sort_code",
            "address.country": "GB",
            "address.state": "Greater London",
            "address.city": "London",
            "address.street_address": "221B Baker Street",
            "address.postal_code": "NW1 6XE"
        }
    },
)
# 金额用 Decimal(str(...)),不要 float
data = res.json()