所需文档
- 微信公众平台(公众号和小程序管理平台):
- 公众号: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)
},
})
}
})
}
}
})
},
})