小程序对接外部会员系统:占位名 + 逐字段锁,而非全局一刀切
把小程序注册流程砍到只留手机号,是常见的漏斗优化动作。用户不想填名字,那就先不填。问题是,背后的外部会员系统(POS / CRM)往往要求 name 字段非空才能建档,而且一旦记录写入,有人就习惯性地加一个「记录已存在 → 全部字段锁定」的逻辑,结果用户连后来想补填真实姓名都做不到。
我在一个对接第三方会员积分系统的微信小程序里踩过这个坑,来完整复盘一遍。
现象
- 注册时仅收集手机号,小程序在后台静默向外部系统注册会员(获取
memberCode)。 - 外部系统 API 返回错误:
name不能为空。 - 第一次修复:注册时用
nickName或"新用户"作为占位符写入name。 - 用户进入「个人资料编辑」页,想补填真实姓名,发现姓名栏是禁用状态——因为「记录已存在」的全局锁把所有字段都锁死了。
- 换一个人:这个人当初直接填了真实姓名,反而生日栏是空的,但同样被全局锁锁住,无法补填。
根因
问题出在锁的粒度错了。全局记录锁(if (record.exists) disableAll())把两类完全不同的字段混为一谈:
- 已填真实值的字段:这些应该锁,防止用户误改。
- 只填了占位符或根本没填的字段:这些应该开放,用户需要补全。
全局锁做不到区分,而且第二个隐患是:如果占位符没有统一前缀标记,后续代码根本无法判断 "新用户" 是真实姓名还是占位垃圾。
坑:全局记录锁 + 无标记占位符双杀
if (record.exists) { nameLocked = true; birthdayLocked = true; } 这个模式看起来「保守安全」,实际上让占位符名字永久污染 CRM,同时剥夺了用户补填真实信息的能力。没有前缀标记的占位符(如 "新用户")一旦写入,代码就再也分不清它是真名还是垃圾。
正解
三段式协作模式,缺任何一段都会破坏闭环。
第一段:注册时写占位名,带可识别的前缀标记
// app.js — 静默注册前构造 name
posOpts.name =
userInfo.realName ||
(userInfo.nickName && "PREFIX_" + userInfo.nickName) ||
"PREFIX_" + phone.slice(-8);前缀(这里用 "PREFIX_" 代指,实际用品牌相关的固定字符串)是整个模式的锚点:
- 永远不改(存量记录依赖它做正则匹配)
- 只在这一处代码路径使用
- CRM 导出时人工也能一眼认出哪些是占位记录
所有注册入口(主注册页、一键授权、分享链接冷启动)必须走同一个 helper,否则一半记录带前缀、一半不带,Piece 2 的正则就废了。
第二段:资料编辑页按字段逐个判断锁状态
// editMyInfo.js — 页面加载后计算各字段是否可编辑
const nameLocked = record.name && !/^PREFIX_/.test(record.name); // 有真实值才锁
const birthdayLocked = Boolean(record.birthday); // 非空才锁
const genderLocked = Boolean(record.gender); // 非空才锁nameLocked用正则区分占位名和真实名,占位名对用户可编辑。birthdayLocked/genderLocked只看非空,任何非空值都视为权威数据,锁定。- 禁止出现
recordLocked全局变量:一个字段填了不能影响另一个空字段的可编辑性。
第三段:提交时只 diff 发送解锁字段的变更
// editMyInfo.js — 构造 POS 更新 payload
const posUpdate = {};
if (!nameLocked && form.name !== origin.name) posUpdate.name = form.name;
if (!birthdayLocked && form.birthday !== origin.birthday) posUpdate.birthYear = yearOf(form.birthday);
if (!genderLocked && form.gender !== origin.gender) posUpdate.gender = form.gender;
if (Object.keys(posUpdate).length) {
posProxyUpdate({ memberCode, ...posUpdate });
}只把「解锁且值有变化」的字段发给外部系统,不发整个 form。好处:不会因为 form 里有一个字段的旧值被意外清空,就把外部系统里的权威数据覆盖掉。
正解:前缀标记 + 逐字段锁 + diff 提交三段协作
- 注册时统一在占位名加固定前缀,确保后续代码可区分。
- 编辑页对每个字段独立计算
locked状态:有真实值才锁,占位/空值保持可编辑。 - 提交时只 diff 解锁字段的变更,绝不全量覆盖。
一句话外卖
跨系统字段锁的粒度应该是字段级别的「是否已有权威值」,而不是记录级别的「是否已存在」——前者可以为空字段保留补填窗口,后者是个无解的死锁。