所需文档
- 微信公众平台(公众号和小程序管理平台):
- 公众号:mp.weixin.qq.com/cgi-bin/hom…
- API文档:
developers.weixin.qq.com/doc/offiacc…
developers.weixin.qq.com/doc/offiacc…
一:前期准备
公众号基本配置
- 配置开发者密码
- 配置服务器地址
- 如果是本地开发测试用,需要做内网穿透(暂时用的花生壳做的内网穿透),因为本地没有公网IP
- 还有可以做端口转发
- 配置加密密钥
- 自动生成即可
- 编码
- 用来校验
二:服务器端校验token(微信服务器验证接口)
接口名称:/api/passport/wechat-checkSignature GET请求 (参数:String signature, String timestamp, String nonce, String echostr)
注: 校验通过,才可以和微信服务器打通,进行接下来的接口调试
三:获取微信公众号临时二维码(前端接入)
接口名称:/api/passport/wechat-login-QRCode GET请求 无参 返回数据:二维码链接url(3分钟有效)
- 先获取access_token,
- 然后用access_token去换取ticket
- 然后用ticket和地址拼接组成公众号二维码地址。
前端接入:
- 扫码弹窗每次弹起,刷新获取最新的二维码信息, 等待扫码
- 轮训接口获取,关注后的回调地址,拿到微信信息
- 轮训三分钟过期, 停止轮训, 清理定时器
- 错误处理, 网路问题或者二维码图片展示出错时,显示错误的兜底,点击可以重新刷新
四:处理事件接口(微信服务器回调接口)
接口名称:/api/passport/wechat-checkSignature POST请求 (参数:String xml)
处理事件大概步骤:
通过eventType判断事件类型,根据事件类型去进行相应的处理。
获取access_token,通过access_token等获取用户的unionid.
官方文档地址:developers.weixin.qq.com/doc/offiacc…
注意事项:此处想要获取access_token需要在公众号配置页面配置IP白名单,否则获取不到access_token
然后处理事件消息,例如:订阅事件
A. 将此人的微信信息存入redis中,以eventkey(就是生成公众号二维码时的scene_str)为主键,
B. 然后前端以这个为请求参数轮询后端接口,如果轮循到,则说明该微信用户已经关注公众号,则对这个用户进行注册或登录操作。
C. 然后发送模板消息到其公众号。(两种方式:一种通过模板来发送,第二种就是可以通过客服消息发送模板消息)
模板消息官方文档地址:developers.weixin.qq.com/doc/offiacc…
客服消息官方文档地址:developers.weixin.qq.com/doc/offiacc…
五:轮询接口(前端接入,通过sceneid)
接口名称: /api/passport/poll-redis GET请求 (参数:String sceneId)
通过此轮询来判断用户是否关注了公众号,如果关注了则根据返回的数据去执行登录流程(或是注册流程)。
前端接入:
接口判断登陆注册分别走不同对应逻辑
六:登陆注册前置准备接口(前端接入)
接口名称:/api/passport/wechat-start POST请求 (参数: unionid; sceneStr; openid;requestType; nickname; headimgurl; phoneNo;deviceNo;deviceType; deviceVersion;)
然后进行具体的逻辑判断。下一步是注册还是登录。
七:微信扫码登录接口
接口名称:/api/passport/wechat-login POST请求 (参数:String token)
八:注册流程
接口名称:/api/passport/wechat-phone-singup POST请求 (参数:String openid;String unionid;String nickname;String sex; String headimgurl; String phoneNo;)
这里的参数就是在处理事件时(第四步)中存入redis中的信息,前端存储一下,再转发给后端。后端拿着这个微信用户的信息去注册。然后直接登录。
九:个人信息界面的解绑
接口名称:/api/personal/info/set/unBindWeChat GET请求 (参数:String phoneNo)
通过手机号进行解绑。
前端接入:
弹窗之间的处理逻辑为, 隐藏个人设置弹窗, 弹出扫码弹窗, 扫码后,刷新接口, 切换弹窗
注意: 弹窗之间如果不进行切换操作, 会导致弹窗不刷新, 不符合要求
十:个人信息界面的绑定
和扫描公众号二维码同一个接口。只不过是后端业务逻辑进行了区分和处理。
六:获取小程序二维码
前端通过小程序也可以获取到用户手机号,通过接口调用, 达到新用户,可以不输入手机号,则进入系统的作用,方便用户的操作, 减少操作步骤
小程序获取手机号的流程
- 通过调用wx.login 拿到code, 调用后端接口换取 sessionId 服务端是通过 code和密钥,appid拿到的用户信息
- 存储sessionId ,这个为每次调用接口,或者登录过期的凭证, 如果过期,需要重新调用wx.login 重新获取sessionId
- 通过button open-type="getPhoneNumber" 和 getUserInfo 拿到用户的信息和手机号信息(此处为加密信息), 调用后端接口, 进行信息解密
- 完整代码如下
app.js
// app.js App({ onLaunch() { // 展示本地存储能力 const logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) // 登录 this.my_login() }, my_login: function () { let that = this wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId wx.request({ url: `${that.globalData.apiUrl}/passport/wechatMini-sessionkey/${res.code}`, method: "GET", success(e) { let data = e.data || {} wx.setStorageSync('sessionId', data.data) } }) } }) }, globalData: { userInfo: null, // 本地环境 apiUrl: 'http://192.168.2.32:8080/api', // 测试环境 // apiUrl: 'http://47.99.216.198:8080/api' }, })
login.js
// pages/login/login.js // var WXBizDataCrypt = require('../../utils/WXBizDataCrypt.js') const APPID = 'wx66aa25a5ebdad4b0' const SECRET = '6360ac0a9e43214c2c7ad99d356df689' const app = getApp() Page({ /** * 页面的初始数据 */ data: {}, /** * 生命周期函数--监听页面加载 */ // onLoad: function (options) {} // onLaunch: function () {}, /** * * @param {}} e * 将数据发送后端 */ sendwechatUserinfo: function (e, res) { wx.request({ // 发送iv,encryptedData url: app.globalData.apiUrl + '/passport/wechatMini-userinfo', data: { iv: res.iv, encryptedData: res.encryptedData, sessionId: wx.getStorageSync("sessionId"), iphoneIv: e.detail.iv, iphoneEncryptedData: e.detail.encryptedData }, method: "POST", success: (e) => { console.log('后台返回的数据', e) } }) }, /** * 获取手机号回调 */ getPhoneNumber: function (e) { //点击获取手机号码按钮 let that = this; wx.getSetting({ success(res) { if (res.authSetting['scope.userInfo']) { wx.getUserInfo({ success: (res) => { console.log("res", res) //这个res就是用户的信息 console.log(e, 'e....') that.sendwechatUserinfo(e, res) }, }) // 判断是否过期 wx.checkSession({ success() { //session_key 未过期,并且在本生命周期一直有效 }, fail() { // session_key 已经失效,需要重新执行登录流程 app.my_login() // 重新登录,更新session_key wx.getUserInfo({ success: (res) => { console.log("res啦啦啦", res) //这个res就是用户的信息 // 将数据发送后端 that.sendwechatUserinfo(e, res) }, }) } }) } } }) }, })