“button open-type='getPhoneNumber'点不了”根本原因是未满足三个硬性条件:小程序主体须为企业/政府/媒体类(个人主体无权限);manifest.json中AppID必须为该企业真实且已认证的AppID;微信公众平台“开发管理→接口权限”中已勾选“获取手机号”并审核通过。
button open-type="getPhoneNumber" 点不了?先查这三个硬性条件
按钮没反应、点下去连 console 都不输出,大概率不是代码问题,而是微信侧权限没通。必须同时满足:
- 小程序主体是企业/政府/媒体类——个人号直接无权限,
getPhoneNumber:fail no permission就是这个原因 -
manifest.json里填的是该企业账号下真实、已认证的AppID,不能用测试号或他人 AppID - 微信公众平台「开发管理 → 接口权限」中已手动勾选「获取手机号」,并完成审核(不是勾了就生效,要等审核通过)
特别注意:开发版/体验版还需在「成员管理 → 测试人员」里绑定白名单手机号,否则即使权限开了也弹不出授权框。
@getphonenumber 回调不触发?检查用户交互是否“真实”
回调函数完全不执行,常见于以下几种情况:
- 按钮被
v-if控制显隐——微信判定为“非初始可交互元素”,拒绝唤起授权 - 按钮套在
disabled的父容器里,或 CSS 设置了pointer-events: none - 在
onLoad或onShow里自动调用uni.login()后再模拟点击——微信强制要求“用户真实点击”,静默拦截且不报错 - Vue 3 +
<script setup></script>中事件名写成@getPhoneNumber或@getphonenumber(大小写错误),正确写法是@getphonenumber
实操建议:按钮必须是可见、有文案、无遮挡的原生 <button></button>,文案如“授权并登录”,不要用 <view></view> + @click 伪装。
e.detail.code 拿到了但后端解密失败?90% 是 session_key 用错了
前端拿到 e.detail.encryptedData 和 e.detail.iv 只是第一步。真正解密依赖服务端持有的 session_key,而它必须来自:
- 调用微信接口
https://api.weixin.qq.com/sns/jscode2session,传入e.detail.code,不是用access_token -
e.detail.code和uni.login()返回的code完全无关——前者专用于手机号,5 分钟内单次有效;后者用于登录,换openid和session_key - 前端必须把
e.detail.code、e.detail.encryptedData、e.detail.iv三者打包一次发给后端,不能分两次请求;否则后端拿code换session_key时,code已被消耗或过期 - 后端解密必须用
AES-128-CBC+PKCS#7填充,任何语言库若默认用PKCS#5或忽略iv,都会返回乱码或空字符串
一个容易被忽略的点:session_key 有效期约 2 小时,但微信不保证长期有效。如果前端多次调 uni.login(),旧 session_key 可能被覆盖,导致后端缓存的 key 和加密时用的不一致——解密必败。
为什么不能用 uni.getPhoneNumber?它真没了
自微信基础库 2.21.2 起,uni.getPhoneNumber API 已被彻底移除。现在调用会直接报错:
getPhoneNumber is not a function
当前唯一合规路径只有这一条:
- 用
<button open-type="getPhoneNumber"></button>触发授权 - 监听
@getphonenumber事件获取encryptedData+iv - 服务端用
e.detail.code换session_key,再用该 key 解密
用户拒绝授权时,e.detail.errMsg 固定为 getPhoneNumber:fail user deny,不是其他变体,判断逻辑必须写准,否则分支走错。











