不能直接拿到明文手机号,必须走微信官方open-type="getPhoneNumber"按钮+后端解密流程;个人主体不支持,仅企业/政府/媒体认证账号可用;需同时满足三个硬性条件:主体类型合规、manifest.json中AppID真实有效、微信公众平台接口权限已勾选并审核通过。

不能直接拿到明文手机号,必须走微信官方的 open-type="getPhoneNumber" 按钮 + 后端解密流程。个人主体小程序不支持,企业认证账号才可用。
button open-type="getPhoneNumber" 点不动或没反应
这不是代码写错了,而是权限卡在微信侧。三个硬性条件缺一不可:
- 小程序账号主体必须是企业 / 政府 / 媒体(个人号直接无权限)
-
manifest.json里配置的mp-weixin.appid必须是该企业账号下真实、已认证的小程序 AppID - 微信公众平台「开发管理 → 接口权限」中,必须手动勾选「获取手机号」并提交审核通过(不是自动开通)
常见错误现象是控制台完全不输出 detail,只报 getPhoneNumber:fail no permission——此时改前端毫无意义,先去后台检查权限状态。
@getphonenumber 回调里拿不到 encryptedData 或 iv
用户点击授权后,e.detail 为空、encryptedData 为 undefined 或 iv 缺失,大概率是用户点了“拒绝”而非“允许”。必须严格判断 e.detail.errMsg:
-
getPhoneNumber:ok→ 可安全取e.detail.encryptedData和e.detail.iv -
getPhoneNumber:fail user deny→ 用户拒绝,不要继续发请求 -
getPhoneNumber:fail not clickable→ 按钮被禁用、v-if 隐藏后又显示、或套在 disabled 容器里,微信强制要求“真实可点击”
注意:uni.getPhoneNumber() 已于基础库 2.21.2 起彻底废弃,调用即报 getPhoneNumber is not a function,别再查旧教程。
后端解密失败:乱码、空字符串、报错
前端传了 encryptedData 和 iv,但后端解出来不是手机号,问题几乎全出在 session_key 上:
- 解密必须用
jscode2session接口返回的session_key,不是access_token -
code必须来自uni.login({ provider: 'weixin' })的 success 回调,且每个 code 只能用一次、5 分钟过期 - 不能分两次请求:前端不能先传 login code 换 openid,再传 getPhoneNumber code —— 后端处理 getPhoneNumber code 时,login code 可能已被消耗或过期
- AES 解密必须用
AES-128-CBC,填充方式为PKCS#7(不是 PKCS#5),session_keybase64 解码后必须是 16 字节
最易忽略的一点:新版手机号快速验证接口(phonenumber.getPhoneNumber)虽不依赖 session_key,但需 access_token + 新的 code,且每次调用收费 0.03 元;老方案(用 session_key 解密)免费但依赖登录态完整闭环——选哪条路,得看你的成本敏感度和架构一致性。











