第三方 POS 接口只传两个字段,开卡门店永远不更新
接入某 POS 系统的会员同步接口时,业务需求是把会员的「归属门店」和「开卡门店」同时迁移到新门店。调用 updateNew 接口后,归属门店(belongCounterCode)确实变了,但数据库里的开卡门店字段(open_card_counter_code)始终是旧值。
翻遍了三处源码注释,都写着同一句话:「updateNew 接口不支持修改开卡门店,只能改归属门店」。这条注释被当成 API 限制记录在案,后续维护者照单全收,没人去验证原始接口文档。
现象
updateNew调用返回code: 10000、returnCode: "0",HTTP 200,一切正常- 本地数据库
open_card_counter_code字段不更新 - 三处历史注释均断言「此接口不修改开卡门店」
根因
注释描述的是当时的业务设计(「我们的 updateNew 调用不修改开卡门店」),而不是 API 能力边界。真实情况是:
updateNew 接口支持同时修改归属门店和开卡门店,但开卡门店需要完整传入四个字段,缺一不可:
| 字段 | 来源 | 注意 |
|------|------|------|
| openCardCounterId | 等同于 organizationId(POS 组织 ID) | 是 POS 内部 org ID,不是本地系统主键 |
| openCardCounterCode | 门店的 POS 柜台编码 | |
| openCardCounterName | 门店名称 | 用 name 字段,不是 counter_name(虚拟渠道店名不同) |
| organizationId | POS 组织 ID | 同时控制归属门店 |
历史代码只传了 memberCode + organizationId 两个字段,开卡相关的三个 openCard* 字段从未出现在请求体里。POS 端收到请求后只更新有值的部分,开卡门店当然纹丝不动。
注释把「我们没传字段」误写成「接口不支持」,之后每一位接手的开发者都相信了这个错误断言,并沿用只传两个字段的写法,进一步「验证」了注释的正确性——形成了一个自我强化的错误循环。
POS 接口不会因为缺字段报错,只会静默忽略。返回 code: 10000 只代表请求被接受,不代表所有字段都被更新。必须传完整的四元组,开卡门店才会变更。
另外,openCardCounterName 必须取门店的 name,不能取 counter_name——部分虚拟渠道门店的这两个字段值不同,用错会导致 POS 端存入错误门店名。
正解
构造完整六字段请求体,缺一不可:
$body = [
'memberCode' => $memberCode, // 会员 POS 卡号
'organizationId' => $store->offline_org_id, // POS 组织 ID(非本地主键)
'openCardCounterId' => $store->offline_org_id, // 与 organizationId 相同
'openCardCounterCode' => $store->counter_code, // POS 柜台编码
'openCardCounterName' => $store->name, // 门店名,注意不是 counter_name
'brandCode' => 'ACME',
'callerSource' => 'MyApp',
];成功判断需要双重校验:
if ($res['code'] === 10000 && $res['data']['returnCode'] === '0') {
// 真正成功,归属门店 + 开卡门店均已更新
}updateNew 原生支持同时更新归属门店和开卡门店,无需两次调用。传入完整的 6 个字段,并同时校验 body.code == 10000 和 body.data.returnCode == "0",才算真正落地。
排查要点
接口返回成功但字段没变,优先排查以下三点:
- 请求体是否包含全部必要字段——用抓包或日志打印实际发出的 JSON
- 字段名大小写——例如
openCardCounterID(大写 D)会被静默忽略,必须是openCardCounterId - ID 来源——
organizationId必须是 POS 系统的组织 ID(对应本地数据库的offline_org_id),传本地主键会导致 POS 端找不到组织
一句话外卖
第三方接口注释写着「不支持 X」时,先验证注释是描述 API 限制还是描述当时代码的取舍——历史业务决策很容易被后人误读成能力边界。