// utils/request.js (需要先创建这个文件) function request(options) { return new Promise((resolve, reject) { wx.request({ url: options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, ...options.header }, success: (res) { if (res.statusCode 200 res.statusCode 300) { resolve(res.data); } else { reject(res); } }, fail: (err) { reject(err); } }); }); } // 将 request 导出 module.exports { request: request }; // pages/login/login.js (主页面逻辑) const api require(../../utils/request); // 引入请求工具 Page({ data: {}, // 获取手机号按钮回调 getPhoneNumber(e) { if (e.detail.errMsg getPhoneNumber:ok) { // 1. 获取微信登录凭证 code wx.login({ success: (loginRes) { const code loginRes.code; if (!code) { wx.showToast({ title: 登录失败请稍后重试, icon: none }); return; } // 2. 将 code 和手机号加密数据一起发给后端 this.doLogin(code, e.detail); }, fail: (err) { console.error(wx.login fail, err); wx.showToast({ title: 获取登录凭证失败, icon: none }); } }); } else { // 用户拒绝授权 console.log(用户拒绝了手机号授权, e.detail.errMsg); wx.showToast({ title: 您取消了授权, icon: none }); } }, // 发送登录请求到后端 doLogin(code, phoneDetail) { wx.showLoading({ title: 登录中... }); api.request({ url: 你的后端接口地址/api/login, // 替换为你的真实接口 method: POST, data: { code: code, // 微信登录 code encryptedData: phoneDetail.encryptedData, // 手机号加密数据 iv: phoneDetail.iv // 加密向量 }, header: { Content-Type: application/json } }).then(res { wx.hideLoading(); if (res res.code 200) { // 假设后端返回格式为 { code: 200, token: xxx } // 登录成功保存 token wx.setStorageSync(token, res.token); wx.showToast({ title: 登录成功, icon: success }); // 示例跳转到首页 wx.switchTab({ url: /pages/index/index // 假设首页是 tabbar 页面 }); } else { wx.showToast({ title: res.message || 登录失败, icon: none }); } }).catch(err { wx.hideLoading(); console.error(登录请求失败, err); wx.showToast({ title: 网络错误请稍后重试, icon: none }); }); } }); 方案二后端实现逻辑 (关键)注意从 2023 年起微信调整了策略前端无法直接解密出手机号必须由后端使用session_key进行解密。后端以 Node.js/Java/Python 为例的处理流程如下换取 SessionKey使用前端传来的codeAppIDAppSecret调用微信接口GET https://api.weixin.qq.com/sns/jscode2session?appidAPPIDsecretSECRETjs_codeCODEgrant_typeauthorization_code返回结果包含openid和session_key。解密手机号使用上一步拿到的session_key配合前端传来的encryptedData和iv通过AES-128-CBC算法解密。解密后的 JSON 数据中即包含phoneNumber手机号和purePhoneNumber。业务处理查询数据库该openid或phoneNumber是否存在不存在自动注册新用户。存在生成自定义登录态Token。返回 Token 给前端。总结实现“一键登录”的核心在于前后端配合前端负责“要票”code和“拿加密包”encryptedData。后端负责“换钥匙”session_key和“开箱取号”解密手机号。// utils/request.js (需要先创建这个文件) function request(options) { return new Promise((resolve, reject) { wx.request({ url: options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, ...options.header }, success: (res) { if (res.statusCode 200 res.statusCode 300) { resolve(res.data); } else { reject(res); } }, fail: (err) { reject(err); } }); }); } // 将 request 导出 module.exports { request: request }; // pages/login/login.js (主页面逻辑) const api require(../../utils/request); // 引入请求工具 Page({ data: {}, // 获取手机号按钮回调 getPhoneNumber(e) { if (e.detail.errMsg getPhoneNumber:ok) { // 1. 获取微信登录凭证 code wx.login({ success: (loginRes) { const code loginRes.code; if (!code) { wx.showToast({ title: 登录失败请稍后重试, icon: none }); return; } // 2. 将 code 和手机号加密数据一起发给后端 this.doLogin(code, e.detail); }, fail: (err) { console.error(wx.login fail, err); wx.showToast({ title: 获取登录凭证失败, icon: none }); } }); } else { // 用户拒绝授权 console.log(用户拒绝了手机号授权, e.detail.errMsg); wx.showToast({ title: 您取消了授权, icon: none }); } }, // 发送登录请求到后端 doLogin(code, phoneDetail) { wx.showLoading({ title: 登录中... }); api.request({ url: 你的后端接口地址/api/login, // 替换为你的真实接口 method: POST, data: { code: code, // 微信登录 code encryptedData: phoneDetail.encryptedData, // 手机号加密数据 iv: phoneDetail.iv // 加密向量 }, header: { Content-Type: application/json } }).then(res { wx.hideLoading(); if (res res.code 200) { // 假设后端返回格式为 { code: 200, token: xxx } // 登录成功保存 token wx.setStorageSync(token, res.token); wx.showToast({ title: 登录成功, icon: success }); // 示例跳转到首页 wx.switchTab({ url: /pages/index/index // 假设首页是 tabbar 页面 }); } else { wx.showToast({ title: res.message || 登录失败, icon: none }); } }).catch(err { wx.hideLoading(); console.error(登录请求失败, err); wx.showToast({ title: 网络错误请稍后重试, icon: none }); }); } }); view classlogin-container button classlogin-btn typeprimary open-typegetPhoneNumber getphonenumbergetPhoneNumber 手机号一键登录 /button /view .login-container { display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f5f5f5; } .login-btn { width: 80%; margin-top: 20rpx; }
uniapp与微信小程序如何一键微信登录和手机号登录
// utils/request.js (需要先创建这个文件) function request(options) { return new Promise((resolve, reject) { wx.request({ url: options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, ...options.header }, success: (res) { if (res.statusCode 200 res.statusCode 300) { resolve(res.data); } else { reject(res); } }, fail: (err) { reject(err); } }); }); } // 将 request 导出 module.exports { request: request }; // pages/login/login.js (主页面逻辑) const api require(../../utils/request); // 引入请求工具 Page({ data: {}, // 获取手机号按钮回调 getPhoneNumber(e) { if (e.detail.errMsg getPhoneNumber:ok) { // 1. 获取微信登录凭证 code wx.login({ success: (loginRes) { const code loginRes.code; if (!code) { wx.showToast({ title: 登录失败请稍后重试, icon: none }); return; } // 2. 将 code 和手机号加密数据一起发给后端 this.doLogin(code, e.detail); }, fail: (err) { console.error(wx.login fail, err); wx.showToast({ title: 获取登录凭证失败, icon: none }); } }); } else { // 用户拒绝授权 console.log(用户拒绝了手机号授权, e.detail.errMsg); wx.showToast({ title: 您取消了授权, icon: none }); } }, // 发送登录请求到后端 doLogin(code, phoneDetail) { wx.showLoading({ title: 登录中... }); api.request({ url: 你的后端接口地址/api/login, // 替换为你的真实接口 method: POST, data: { code: code, // 微信登录 code encryptedData: phoneDetail.encryptedData, // 手机号加密数据 iv: phoneDetail.iv // 加密向量 }, header: { Content-Type: application/json } }).then(res { wx.hideLoading(); if (res res.code 200) { // 假设后端返回格式为 { code: 200, token: xxx } // 登录成功保存 token wx.setStorageSync(token, res.token); wx.showToast({ title: 登录成功, icon: success }); // 示例跳转到首页 wx.switchTab({ url: /pages/index/index // 假设首页是 tabbar 页面 }); } else { wx.showToast({ title: res.message || 登录失败, icon: none }); } }).catch(err { wx.hideLoading(); console.error(登录请求失败, err); wx.showToast({ title: 网络错误请稍后重试, icon: none }); }); } }); 方案二后端实现逻辑 (关键)注意从 2023 年起微信调整了策略前端无法直接解密出手机号必须由后端使用session_key进行解密。后端以 Node.js/Java/Python 为例的处理流程如下换取 SessionKey使用前端传来的codeAppIDAppSecret调用微信接口GET https://api.weixin.qq.com/sns/jscode2session?appidAPPIDsecretSECRETjs_codeCODEgrant_typeauthorization_code返回结果包含openid和session_key。解密手机号使用上一步拿到的session_key配合前端传来的encryptedData和iv通过AES-128-CBC算法解密。解密后的 JSON 数据中即包含phoneNumber手机号和purePhoneNumber。业务处理查询数据库该openid或phoneNumber是否存在不存在自动注册新用户。存在生成自定义登录态Token。返回 Token 给前端。总结实现“一键登录”的核心在于前后端配合前端负责“要票”code和“拿加密包”encryptedData。后端负责“换钥匙”session_key和“开箱取号”解密手机号。// utils/request.js (需要先创建这个文件) function request(options) { return new Promise((resolve, reject) { wx.request({ url: options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, ...options.header }, success: (res) { if (res.statusCode 200 res.statusCode 300) { resolve(res.data); } else { reject(res); } }, fail: (err) { reject(err); } }); }); } // 将 request 导出 module.exports { request: request }; // pages/login/login.js (主页面逻辑) const api require(../../utils/request); // 引入请求工具 Page({ data: {}, // 获取手机号按钮回调 getPhoneNumber(e) { if (e.detail.errMsg getPhoneNumber:ok) { // 1. 获取微信登录凭证 code wx.login({ success: (loginRes) { const code loginRes.code; if (!code) { wx.showToast({ title: 登录失败请稍后重试, icon: none }); return; } // 2. 将 code 和手机号加密数据一起发给后端 this.doLogin(code, e.detail); }, fail: (err) { console.error(wx.login fail, err); wx.showToast({ title: 获取登录凭证失败, icon: none }); } }); } else { // 用户拒绝授权 console.log(用户拒绝了手机号授权, e.detail.errMsg); wx.showToast({ title: 您取消了授权, icon: none }); } }, // 发送登录请求到后端 doLogin(code, phoneDetail) { wx.showLoading({ title: 登录中... }); api.request({ url: 你的后端接口地址/api/login, // 替换为你的真实接口 method: POST, data: { code: code, // 微信登录 code encryptedData: phoneDetail.encryptedData, // 手机号加密数据 iv: phoneDetail.iv // 加密向量 }, header: { Content-Type: application/json } }).then(res { wx.hideLoading(); if (res res.code 200) { // 假设后端返回格式为 { code: 200, token: xxx } // 登录成功保存 token wx.setStorageSync(token, res.token); wx.showToast({ title: 登录成功, icon: success }); // 示例跳转到首页 wx.switchTab({ url: /pages/index/index // 假设首页是 tabbar 页面 }); } else { wx.showToast({ title: res.message || 登录失败, icon: none }); } }).catch(err { wx.hideLoading(); console.error(登录请求失败, err); wx.showToast({ title: 网络错误请稍后重试, icon: none }); }); } }); view classlogin-container button classlogin-btn typeprimary open-typegetPhoneNumber getphonenumbergetPhoneNumber 手机号一键登录 /button /view .login-container { display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f5f5f5; } .login-btn { width: 80%; margin-top: 20rpx; }