微信获取手机号必须用户主动点击button触发,e.detail.code需5分钟内传给后端换取明文手机号,access_token须由后端缓存管理,旧版解密方式已弃用。

button 的 open-type="getPhoneNumber" 必须配合用户主动点击触发
微信强制要求:获取手机号的授权弹窗只能由用户真实点击按钮触发,不能自动调用、不能在 onLoad 里模拟点击、也不能通过 uni.showToast 后延时调用——否则直接静默失败,控制台无报错,@getphonenumber 根本不执行。
常见错误现象:
– 页面一进来就调用 uni.login() + 拿到 code 后立刻发请求,结果后端返回 40013 invalid appid 或空响应;
– 把 getPhoneNumber 按钮藏在 v-if 里、或初始 opacity: 0,微信会判定为“非可交互元素”,拒绝唤起授权。
实操建议:
– 按钮必须是可见、可点击、有明确文案(如“授权并绑定手机号”)的 ;
– 不要用 + @click 伪装按钮;
– Vue 3(<script setup></script>)中事件写法必须是 @getphonenumber="onGetPhoneNumber",注意大小写(不是 getPhoneNumber 或 getphonenumber);
– 确保该 button 没被 disabled 或 pointer-events: none 干扰。
e.detail.code 是动态令牌,5 分钟内仅能使用一次
这个 code 不是 uni.login() 返回的登录 code,也不是 session_key 相关凭证,而是微信专为手机号接口生成的一次性动态令牌。它只在用户点击“允许”后才存在(拒绝时 e.detail.code 为 undefined),且必须在 5 分钟内传给后端换取手机号,超时或重复使用都会返回 40001 errcode。
实操建议:
– 前端拿到 e.detail.code 后应立即调用你自己的登录 API,不要缓存、不要节流、不要等其他异步操作完成;
– 不要把它和 uni.login() 的 code 混用,二者用途、有效期、校验方式完全不同;
– 如果用户点了按钮又取消授权,e.detail.code 为空,此时应提示“请授权以继续”,而不是重试或跳过。
access_token 必须由后端获取,且需缓存避免频繁调用
前端绝不能硬编码 appid 和 secret 去请求 https://api.weixin.qq.com/cgi-bin/token,否则源码暴露即等于泄露小程序密钥。这个步骤必须交由后端完成,且因 access_token 有效期仅 2 小时,每次换新 token 都要消耗调用配额(日限 2000 次),高频请求极易触发限流。
实操建议:
– 后端首次请求后,将 access_token 和过期时间(expires_in)存入内存缓存(如 Node.js 的 Map 或 Redis);
– 下次请求前先检查缓存是否有效,无效再刷新;
– 若用 uniCloud,可在云函数中封装 token 获取逻辑,并加锁防止并发刷新;
– 注意:微信对 access_token 的校验非常严格,拼错一个字符、多一个空格、时间戳偏差过大,都会导致 getuserphonenumber 接口返回 40001。
后端调用微信 getuserphonenumber 接口时,只传 code,别传 encryptedData 和 iv
这是 2025 年底起微信强制推行的新流程:旧版解密手机号方式(依赖 encryptedData + iv + session_key)已逐步弃用;新版只需把 code 发给 https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=xxx,微信服务端直接返回明文手机号(字段为 purePhoneNumber)。
常见错误现象:
– 后端仍按老方式尝试解密,结果抛出 invalid iv 或 buffer length error;
– 前端把 e.detail.encryptedData 和 e.detail.iv 也一起传给后端,后端误当成新接口参数,导致 400 错误;
– 接口返回 {"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest"},其实是 token 没更新,但误以为是参数问题。
实操建议:
– 前端只提取并上传 e.detail.code;
– 后端 POST 请求体仅含 {"code": "xxx"},Content-Type 为 application/json;
– 成功响应结构为:{"phone_info":{"phoneNumber":"+86138****1234","purePhoneNumber":"138****1234","countryCode":"86"}};
– 若返回 errcode: 87014,说明用户未勾选“同步手机号”,不是技术问题,需引导用户重试。
微信手机号授权真正卡点不在前端怎么写,而在于你有没有企业资质、域名有没有备案、access_token 到底缓存对没对、以及那个 code 有没有在 5 分钟内干净利落地送到后端——中间任何一环断掉,用户看到的都只是“点不动”或“没反应”。










