微信小程序登录与手机号获取:前端到后端全链路实战
2026/9/17 8:58:12 网站建设 项目流程

1. 先搞明白:微信小程序的信息获取链路到底长什么样

做小程序开发,最绕不开的一件事就是"怎么拿到微信用户的身份信息和手机号"。不管你是要做会员登录、电商下单、还是做用户画像,第一步都是先解决"这个用户是谁"的问题。很多新手一上来就去看wx.getUserInfowx.getPhoneNumber这些 API,结果发现要么拿不到数据,要么拿到的是一堆nickName: "微信用户"的默认值,直接卡在第一步。

其实微信的授权体系这些年改得挺狠的。早期版本里,用户一进来弹个授权框,你就能拿到完整的昵称头像,甚至能通过encryptedData解密出手机号。但从 2021 年起,微信把这条路基本堵死了——昵称头像改成了"头像昵称填写能力",手机号改成了"手机号快速验证组件",底层逻辑全部切换成 code 换数据的模式。也就是说,小程序端不再直接给你敏感信息,所有数据都要通过 code 传到你的后端,由后端调用微信服务端接口换取。

这篇文章就用一个前后端分离的完整项目来演示整套流程:前端用原生微信小程序,后端用 Spring Boot,把登录、头像昵称获取、手机号获取三条链路全部打通。核心代码可以直接抄,重点是让你明白每一步为什么这么做,踩到坑了怎么排查。适合正准备开发小程序、或者想把旧授权逻辑升级到新版的朋友参考。

2. 登录态与数据获取方案选型解析

2.1 登录态:openid、session_key、token 三者的关系

先说登录。微信小程序里的登录机制和传统 Web 登录不太一样,它没有密码,也没有短信验证码,靠的是微信自己的一套"静默授权"流程。整个链路里的核心角色有三个:

  • code:临时凭证,由小程序端调用wx.login()获取,有效期大概 5 分钟,只能用一次。它的作用就是"递给"后端,让后端去微信那边换更重要的数据。
  • openid:用户的唯一标识,同一个微信用户在同一小程序下的 openid 是固定的。它是你在自己用户表里建用户、绑定业务数据的主键。
  • session_key:会话密钥,用来解密敏感数据(比如老版手机号解密、用户手机号解密)。注意它不能下发到小程序前端,只能存在后端,否则会有安全风险。

至于登录成功之后给前端返回什么?一般是你自己签发的 token(比如 JWT)。因为前端后续的每次请求,后端都需要知道"这个请求是哪个用户在发",总不能每次都让小程序调一次wx.login。所以标准流程是:小程序wx.login()拿 code → 传给后端 → 后端用 code 调微信接口换openid+session_key→ 后端查库/建用户 → 签发 token → 返回给前端 → 前端存起来,每次请求带上。

2.2 为什么 getUserInfo 被废弃了,现在用什么

2021 年之前,用户进入小程序弹出授权,你就能拿到昵称头像,甚至能通过wx.getUserInfo+encryptedData解密出手机号。这套方案对开发者很爽,但对用户不太友好——很多人看到授权框就反感,而且很多小程序拿了手机号之后乱打电话发短信,搞得微信不得不严管。

现在的方案是:

  • 头像昵称:用户主动触发。使用<button open-type="chooseAvatar">让用户选择微信头像,使用<input type="nickname">让用户填写/选择昵称。微信只负责"提供入口",用户有完全的选择权和控制权。
  • 手机号:使用<button open-type="getPhoneNumber">,用户点击后弹窗确认,确认后前端拿到一个 code,传给后端,后端调用微信接口换取手机号。

这套方案的好处是数据更合规,坏处是开发者不能"静默"拿到手机号了,必须用户主动点一次按钮。但没办法,微信就是要逼你把"收集用户数据"这件事做得明明白白。

2.3 前后端分离为什么是小程序开发的默认姿势

市面上小程序项目基本都是前后端分离的。前端是微信小程序原生代码(或者 Taro / uni-app 这类跨端框架),跑在微信客户端里;后端是独立的 API 服务,可以放服务器上,Spring Boot、Node.js、Go 都行。两者通过 HTTPS 接口通信。

为什么必须分?因为微信的敏感数据交换必须由后端完成。code 换 openid 需要用到appSecret,这东西如果放在小程序前端代码里,就等于把钥匙交出去了——任何人都能通过反编译工具看你的源码,把你的 appSecret 扒出来,然后伪装成你的小程序调微信接口。所以前端永远只做一件事:把 code 传给后端,剩下的活交给后端干。这种架构天然要求前后端分离。

还有一点,小程序的请求域名必须在微信公众平台配置白名单,且必须是 HTTPS。这也是为什么本地开发时经常遇到"request 域名不在合法域名列表"的报错——解决办法要么配域名,要么在开发者工具里关掉域名校验,但真机预览必须配好域名。

3. 基础准备与开发环境搭建

3.1 注册小程序账号,拿到 AppID 和 AppSecret

做微信小程序开发,第一步是去微信公众平台注册小程序账号。注册完成后,在"开发管理 - 开发设置"里能看到两个关键字段:

  • AppID:小程序的唯一标识,前端代码里配置,公开没关系。
  • AppSecret:调微信服务端接口的密钥,必须严格保密,只放在后端。

需要注意,手机号快速验证组件有一个硬性条件:小程序主体必须是企业、个体工商户或政府等认证主体。个人主体的小程序无法申请该能力,调用接口时微信会直接报"无权限"。如果你的项目还在规划阶段,这一点务必提前确认,不然辛苦开发完发现手机号功能根本没法用,返工成本很高。

3.2 配置服务器域名

小程序前端调后端的接口,域名必须在"开发管理 - 开发设置 - 服务器域名"里面配置好。具体配置项:

配置项作用要求
request 合法域名前端 wx.request 的请求地址必须 HTTPS,不能带路径,支持端口
downloadFile 合法域名前端 wx.downloadFile 下载文件地址必须 HTTPS
uploadFile 合法域名前端 wx.uploadFile 上传文件地址必须 HTTPS

开发阶段可以在微信开发者工具里勾选"不校验合法域名",方便本地调试。但真机预览和上线发布时,域名必须真实配置且备案,否则直接请求失败。

3.3 后端工程基础骨架

后端我这边用 Spring Boot,主要是生态成熟、社区资料多,你搜任何问题基本都能找到答案。项目结构大概长这样:

src/main/java/com/example/demo ├── controller │ └── AuthController.java // 登录、手机号获取接口 ├── service │ ├── WxApiClient.java // 封装微信服务端接口调用 │ └── UserService.java // 用户注册/查询逻辑 ├── entity │ └── User.java // 用户实体 ├── mapper │ └── UserMapper.java // 数据库操作(或用MyBatis-Plus) └── config └── WebMvcConfig.java // 拦截器、跨域配置

数据库表设计也不复杂,最小的用户表就这几个字段:

id BIGINT 主键 openid VARCHAR(64) 微信用户唯一标识,唯一索引 nickname VARCHAR(64) 用户昵称 avatar_url VARCHAR(512) 用户头像地址 phone VARCHAR(20) 手机号(可为空) create_time DATETIME 注册时间 update_time DATETIME 更新时间

这里有个经验:手机号字段不要一味追求一开始就补齐,很多用户点进来就是想浏览一下,并不想马上把手机号给你。所以我的做法是"先登录、后补手机号"——用户进入小程序先静默登录(拿 openid 建立用户身份),等他要下单、要领取权益的时候,再弹手机号授权。这样既合规,又不会把用户挡在第一道门外。

4. 前端实现:登录、头像昵称、手机号三件套

4.1 静默登录:wx.login 出 code

wx.login是小程序里最基础的登录接口,它不需要用户授权,静默就能执行。代码如下:

// utils/auth.js function wxLogin() { return new Promise((resolve, reject) => { wx.login({ success: (res) => { if (res.code) { // 拿到临时凭证code resolve(res.code); } else { reject(new Error('wx.login 失败:' + res.errMsg)); } }, fail: (err) => reject(err) }); }); } function silentLogin() { return wxLogin().then((code) => { // 调后端登录接口,换token return new Promise((resolve, reject) => { wx.request({ url: 'https://your-api.com/api/auth/login', method: 'POST', data: { code }, success: (res) => { if (res.statusCode === 200 && res.data.success) { const { token, userInfo } = res.data.data; wx.setStorageSync('token', token); wx.setStorageSync('userInfo', userInfo); resolve(userInfo); } else { reject(new Error(res.data.message || '登录失败')); } }, fail: (err) => reject(err) }); }); }); }

页面onLoad时直接调silentLogin(),用户无感完成身份建立,这就是整套系统的地基。

需要提醒一个新手常见坑:wx.login获取的 code 是一次性的,如果后端处理失败,前端不能拿同一个 code 重试,必须重新调一次wx.login拿新 code。

4.2 头像昵称填写能力实战

WXML 部分:

<view class="profile-card"> <button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar"> <image src="{{avatarUrl || '/assets/default-avatar.png'}}" mode="aspectFill" /> </button> <input type="nickname" class="nickname-input" value="{{nickName}}" bind:input="onNicknameInput" placeholder="请输入昵称" /> </view>

JS 部分:

Page({ data: { avatarUrl: '', nickName: '' }, onChooseAvatar(e) { // 用户授权微信头像后返回临时路径 const tempPath = e.detail.avatarUrl; this.setData({ avatarUrl: tempPath }); // 注意:这个tempPath是本地临时文件,需要上传到自己的服务器 this.uploadAvatar(tempPath); }, onNicknameInput(e) { this.setData({ nickName: e.detail.value }); }, uploadAvatar(tempPath) { wx.uploadFile({ url: 'https://your-api.com/api/upload', filePath: tempPath, name: 'file', success: (res) => { const result = JSON.parse(res.data); if (result.success) { this.setData({ avatarUrl: result.data.url }); wx.setStorageSync('avatarUrl', result.data.url); } } }); } });

这里有个细节:e.detail.avatarUrl返回的是本地临时文件路径(比如wxfile://tmp_xxx),这个路径只在当前会话有效,不能直接当成线上头像使用。你需要把图片上传到自己的服务器或云存储,再拿固定 URL 存数据库。上传后记得处理一下防盗链,微信对图片外链的校验还是挺严的。

昵称输入框用type="nickname",微信会在键盘上方给出昵称快捷填入选项,用户点一下就能自动填入微信昵称,体验很顺。

4.3 手机号快速验证组件落地

手机号获取是整套流程里最核心、也最容易踩坑的部分。WXML 如下:

<button class="phone-btn" open-type="getPhoneNumber" bind:getphonenumber="onGetPhoneNumber" loading="{{phoneLoading}}" > 获取手机号 </button>

JS 部分:

Page({ data: { phoneLoading: false }, async onGetPhoneNumber(e) { if (!e.detail.code) { // 用户点了拒绝,或者授权失败 wx.showToast({ title: '需要授权才能获取手机号', icon: 'none' }); return; } this.setData({ phoneLoading: true }); try { const res = await new Promise((resolve, reject) => { wx.request({ url: 'https://your-api.com/api/auth/phone', method: 'POST', header: { 'Authorization': 'Bearer ' + wx.getStorageSync('token') }, data: { code: e.detail.code }, success: (res) => { if (res.data.success) resolve(res.data.data); else reject(new Error(res.data.message)); }, fail: reject }); }); wx.showToast({ title: '手机号获取成功', icon: 'success' }); this.setData({ phone: res.phoneNumber }); wx.setStorageSync('phone', res.phoneNumber); } catch (err) { wx.showToast({ title: err.message || '获取失败', icon: 'none' }); } finally { this.setData({ phoneLoading: false }); } } });

很多人会问:为什么前端拿不到手机号,只拿到一个 code?这是微信故意设计的。手机号属于敏感个人信息,如果直接把手机号返回给前端,前端代码被反编译后,就能批量偷取用户数据。所以微信只给一个一次性 code,后端拿到 code 之后自己调微信服务端接口取手机号,这个 code 有效期也很短,并且只能换一次。

4.4 三块串成完整登录流程

一个典型的用户首次进入小程序流程应该是这样:

  1. onLoad触发静默登录,拿 openid 建立用户身份,存 token。
  2. 用户点击"编辑资料",弹出头像昵称编辑面板,用户主动选择微信头像、填写昵称,前端上传头像图片、提交昵称到后端。
  3. 用户点击"绑定手机号"按钮,弹出微信手机号授权弹窗,确认后前端把 code 发给后端,后端换到手机号,返回并提示绑定成功。
  4. 后续用户再次进入,token 有效期内直接拉起用户信息,不再重复登录。

前端这里有个建议:不要在一进页面就把头像昵称和手机号三个授权一起弹出来,那样很容易引起用户反感。最优做法是区分"必要授权"和"非必要授权",头像昵称可以在用户准备下单、准备发布内容时再要求填写,手机号则在支付前、领取优惠券前这种强场景再要。这个顺序直接影响用户的转化率,别嫌啰嗦,真的重要。

5. 后端实现:code2session、token 签发与手机号换取

5.1 登录接口:用 code 换 openid 和 session_key

后端先封装一个微信 API 客户端,专门处理与微信服务端的通信:

// WxApiClient.java @Service public class WxApiClient { @Value("${wx.appid}") private String appid; @Value("${wx.secret}") private String secret; private final RestTemplate restTemplate = new RestTemplate(); /** * 用 login code 换 openid 和 session_key */ public WxSession code2Session(String code) { String url = "https://api.weixin.qq.com/sns/jscode2session" + "?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code"; String response = restTemplate.getForObject(url, String.class); JSONObject json = JSON.parseObject(response); // 微信返回 errcode 表示失败 if (json.containsKey("errcode") && json.getIntValue("errcode") != 0) { throw new BizException("微信登录失败:" + json.getString("errmsg")); } WxSession session = new WxSession(); session.setOpenid(json.getString("openid")); session.setSessionKey(json.getString("session_key")); session.setUnionid(json.getString("unionid")); return session; } }

然后在 AuthController 里写登录接口:

@RestController @RequestMapping("/api/auth") public class AuthController { @Autowired private WxApiClient wxApiClient; @Autowired private UserService userService; @Autowired private JwtUtil jwtUtil; @PostMapping("/login") public Result login(@RequestBody LoginDTO dto) { // 1. 用 code 换微信会话 WxSession wxSession = wxApiClient.code2Session(dto.getCode()); // 2. 查用户,不存在则注册 User user = userService.findOrCreate(wxSession.getOpenid()); // 3. 签发 JWT token String token = jwtUtil.generateToken(user.getId(), user.getOpenid()); // 4. 返回给前端 LoginVO vo = new LoginVO(); vo.setToken(token); vo.setUserInfo(user); return Result.success(vo); } }

这里的重点是:后端用自己的 appSecret 去调微信接口,appSecret 全程不出服务器,这是安全的底线。登录接口返回的 token,我这边用 JWT,原因很简单:无状态、不需要存 Redis、跨服务认证方便。你如果系统里有 Spring Security,直接用它的 JWT 支持也行。

5.2 手机号获取接口:用 code 换手机号

登录之后,用户点击手机号授权,前端把e.detail.code传过来。后端收到后,需要先拿到access_token,再调用微信的手机号获取接口。

先看 access_token 的获取和缓存:

// 在 WxApiClient 中新增 private String accessTokenCache; private long accessTokenExpireTime = 0; public synchronized String getAccessToken() { long now = System.currentTimeMillis(); // 提前5分钟过期,防止临界区请求失败 if (accessTokenExpireTime - now > 5 * 60 * 1000) { return accessTokenCache; } String url = "https://api.weixin.qq.com/cgi-bin/token" + "?grant_type=client_credential" + "&appid=" + appid + "&secret=" + secret; String response = restTemplate.getForObject(url, String.class); JSONObject json = JSON.parseObject(response); if (json.containsKey("errcode") && json.getIntValue("errcode") != 0) { throw new BizException("获取access_token失败:" + json.getString("errmsg")); } accessTokenCache = json.getString("access_token"); accessTokenExpireTime = now + json.getLongValue("expires_in") * 1000; return accessTokenCache; }

注意 access_token 的官方有效期是 7200 秒(2 小时)。如果每次请求都重新拿,一是微信接口有频率限制,二是性能也差。所以必须做缓存,最好用 Redis 存,多实例部署时也不会互相踢掉 token。我这里的实现是单机缓存,生产环境建议换成 Redis。

然后写获取手机号的接口:

/** * 手机号快速验证组件:用 code 换手机号 */ public PhoneInfo getPhoneInfo(String phoneCode) { String accessToken = getAccessToken(); String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); JSONObject requestBody = new JSONObject(); requestBody.put("code", phoneCode); HttpEntity<String> entity = new HttpEntity<>(requestBody.toJSONString(), headers); String response = restTemplate.postForObject(url, entity, String.class); JSONObject json = JSON.parseObject(response); if (json.getIntValue("errcode") != 0) { throw new BizException("获取手机号失败:" + json.getString("errmsg")); } JSONObject phoneInfoJson = json.getJSONObject("phone_info"); PhoneInfo phoneInfo = new PhoneInfo(); phoneInfo.setPhoneNumber(phoneInfoJson.getString("phoneNumber")); phoneInfo.setPurePhoneNumber(phoneInfoJson.getString("purePhoneNumber")); phoneInfo.setCountryCode(phoneInfoJson.getString("countryCode")); return phoneInfo; }

Controller 层:

@PostMapping("/phone") public Result bindPhone(@RequestBody PhoneDTO dto, @RequestHeader("Authorization") String token) { // 1. 解析token,拿用户id Long userId = jwtUtil.parseToken(token.replace("Bearer ", "")); // 2. 用 code 换手机号 PhoneInfo phoneInfo = wxApiClient.getPhoneInfo(dto.getCode()); // 3. 绑定到用户 userService.bindPhone(userId, phoneInfo.getPurePhoneNumber()); return Result.success(phoneInfo.getPurePhoneNumber()); }

这个接口返回的数据里,phoneNumber带 +86 前缀,purePhoneNumber是纯手机号。实际业务里建议存purePhoneNumber,方便后续发短信、做手机号匹配,但展示给用户时可以用phoneNumber或自己格式化。

5.3 老版解密方案简述(兼容兜底)

目前新版open-type="getPhoneNumber"返回的是 code 换取方案,但如果你接的是老系统,或者遇到某些兼容场景,可能还会碰到encryptedData+iv的老方案。处理逻辑是后端先用session_key做 AES-128-CBC 解密,代码如下:

public String decryptData(String sessionKey, String encryptedData, String iv) { try { byte[] keyBytes = Base64.decodeBase64(sessionKey); byte[] ivBytes = Base64.decodeBase64(iv); byte[] encryptedBytes = Base64.decodeBase64(encryptedData); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes); cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); byte[] original = cipher.doFinal(encryptedBytes); return new String(original, StandardCharsets.UTF_8); } catch (Exception e) { throw new BizException("解密失败:" + e.getMessage()); } }

解密出来的 JSON 里有purePhoneNumbercountryCode这些字段。

需要注意的是:session_key不会长期有效,微信在用户调用某些接口时可能会滚动更新它。老方案如果出现session_key失效,解密就失败。所以我现在做项目基本都是直接把老方案丢弃,统一用新方案,逻辑简单,也不容易出岔子。

6. 前后端完整联调与常见问题排查实录

6.1 联调走通:从小程序到服务器的全链路

把前端和后端都部署好之后,全链路怎么自测?我一般按这个顺序:

  1. 微信开发者工具里打开项目,确保 AppID 已配置。
  2. 关掉"不校验合法域名"选项,用真实 HTTPS 域名调接口,确认 request 合法域名已配置好。
  3. 打开调试模式,进入页面触发wx.login,Network 面板里确认登录接口返回了 token。
  4. 点击"选择头像"按钮,确认上传接口正常,返回的 URL 能直接访问。
  5. 点击"手机号快捷登录",确认弹窗正常弹出,授权后手机号接口返回成功。
  6. 数据库里确认用户表的 openid、nickname、avatar_url、phone 字段都已正确落库。

联调过程中我习惯把所有微信接口的请求和响应都打日志,特别是 code、errcode、errmsg 这三个字段。微信的错误码信息本身已经写得足够清晰,遇到问题看日志基本就能定位了。

6.2 常见问题速查表

问题现象可能原因解决方案
登录接口报 errcode 40029code 无效或已过期;重复使用了同一个 code重新调 wx.login 拿新 code,一次代码只换一次数据
errcode 40001access_token 无效或过期重新获取 access_token,并做缓存
errcode 40013AppID 不合法核对后端的 appid 和 secret 是否写反
errcode 40125AppSecret 填写错误去公众平台重新查看 secret,注意别复制到空格
errcode 63002手机号 code 无效/会话失效重新触发 getPhoneNumber 授权,再拿新 code
前端拿不到 e.detail.code用户取消授权;或基础库版本过低引导用户重新授权;升级基础库,最低要求 2.21.2
个人主体小程序调手机号接口报无权限手机号快速验证组件仅对认证后非个人主体开放升级主体或改用其他合规方案
开发者工具能跑,真机请求失败服务器域名白名单未配置/未备案在公众平台配置 request 合法域名,必须 HTTPS 且已备案
头像上传后返回的临时路径失效wxfile:// 临时路径只在本会话有效必须把图片上传到自己的服务器或云存储
登录后 openid 在库里总是生成新用户前端登录接口没复用,每次都重新调 login登录成功后的 token 要缓存,后续请求带上 token,不要重复调 login

6.3 避坑经验与实操心得

这套流程我自己做了至少五六个项目,有些坑是真的踩过之后才长记性的。

第一个坑:手机号授权按钮的样式问题。open-type="getPhoneNumber"必须用在<button>组件上,不能用在viewtext上。而且这个按钮的授权行为只在用户真实点击时触发,任何通过 JS 模拟的点击都不会弹授权窗,也没办法在onShow里自动调。如果你希望通过"点击整块区域弹出授权",直接把这个按钮的样式撑满容器就行,但不要试图绕过用户点击。

第二个坑:code 只能换一次。这是微信的硬性约束。我遇到过生产环境的问题:前端把手机号 code 传给后端,后端起先没做异常处理,网络超时导致前端重试,结果同一个 code 被用了两次,第二次就报 40029。解决办法是前端对这类请求做 loading 状态锁定,防止重复提交;后端也要对 code 做幂等处理,至少做到"换过了就不再换"。

第三个坑:access_token 多实例缓存。如果你的后端部署了多台机器,每台机器各本地缓存一份 access_token 没问题,但获取的时候要注意并发——两个实例同时刷新 token,前一个 token 会被后一个挤下线。表情包虽然是苏州码子,但这种问题在生产是真的遇到过的。最简单的方案:用 Redis 做分布式锁 + 缓存,或者干脆用一个专门的 token 管理服务。

第四个坑:隐私协议声明。新版微信要求小程序在「小程序管理后台 - 设置 - 服务内容声明 - 用户隐私保护指引」中声明会收集用户的昵称、头像、手机号等信息,否则调用相关接口时会报隐私协议未声明或者弹窗提示。具体操作是在后台添加对应的收集项:选「用户信息 - 昵称、头像」,以及「手机号」。如果这块不配置,真机预览时会发现授权弹窗不出来,开发者工具里却能正常跑,很容易让人以为代码有问题。

第五个坑:头像上传的临时路径。chooseAvatar获得的临时文件路径在不同平台的表现不太一样。iOS 有时会返回wxfile://tmp_xxx,Android 有时返回http://tmp/xxx,这些都要通过wx.uploadFile上传后才能得到稳定 URL。另外上传之后如果返回的 URL 是 http 协议,在 Android 真机上可能会被拦,所以生产环境必须是 HTTPS。

6.4 上线前必做的检查清单

写到这里,我把每次上线前必过的检查项列一下:

  • 小程序后台已配置服务器域名白名单,且全部为 HTTPS。
  • 后端环境变量里 appid、secret 已正确配置,secret 不进代码仓库。
  • 用户隐私保护指引已声明收集昵称、头像、手机号。
  • 手机号接口已做频率限制,防止恶意刷接口。
  • 用户表 openid 已建唯一索引,避免并发注册产生脏数据。
  • 敏感数据(token、session_key、手机号)在日志中脱敏,不打印明文。
  • 已在小程序后台配置「客服」等必要的服务能力(如果用到)。

这套流程做完,前后端就完全打通了。最后再分享一个我实际体验中的小技巧:做手机号授权时,按钮文案不要写"获取手机号",写"一键登录"或者"微信手机号快捷登录",用户点击意愿会高很多。别小看这点文案的差异,我实测过转化率能差 10% 以上。另外,授权成功后把手机号脱敏展示给用户看,让用户确认这个号是不是自己的,能避免后续一堆客诉。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询