Preface
使用微信提供的微信平台体系(微信开放平台/微信公众号平台/微信小程序/微信支付等)可以使我们的业务接入庞大的微信体系, 定义自己的个性化业务.
这里主要记录一下微信公众号开发相关的要点…
前置
- 是已认证的服务号
- 后端采用 Java 开发
后端微信开发工具包采用官方推荐的 Java 工具包: WxJava, 假定你已经阅读过官方 Wiki
下面集成用例均在本地完成, 微信对于开发者服务器只能是80端口或者443, 因此本地开发调试时, 需要借助内网穿透工具, 该类工具有很多, 比如 Ngrok, 如何使用请自行搜索.
Maven 引用开发包
1 | <dependency> |
- 微信小程序:
weixin-java-miniapp
- 微信支付:
weixin-java-pay
- 微信开放平台:
weixin-java-open
- 公众号(包括订阅号和服务号):
weixin-java-mp
- 企业号/企业微信:
weixin-java-cp
开发者服务器配置
作用
- 接收微信各种事件推送(eg: 关注公众号事件/关键字回复/公众号菜单点击事件/扫码事件等)
- 扩展微信公众号功能(eg: 自动回复/自定义菜单等)
流程说明
服务器地址只能配置一个 URL, 此后所有检测(微信会定时发送 GET 请求到此 URL 确认服务器还正常运行)以及所有的事件回调(关注事件/文本接收等)都会发送到此 URL:
- 对于服务器检测, 发送的是 GET 请求
- 其他事件推送, 发送的是 POST 请求
服务器开发
在配置服务器前, 需要实现开发(只需要能够收到并处理检测的 GET 请求即可)并启动服务器
因为在提交配置的时候微信会检测服务器可用情况.
核心代码示例(WxJava配置请查看官网):
1 | 4j |
此时我们处理微信请求的路径为 /wx/portal
, 假定:
serverContextPath
为portal-user
- 内网穿透地址为
http://wx.ngrok.yangbingdong.com
那么我们最终的服务器 URL 为 http://wx.ngrok.yangbingdong.com/portal-user/wx/portal
.
配置服务器
进入微信公众号平台, 在左边最下面找到开发 -> 基本配置:
点击修改配置, 并填入 URL:
点击提交, 此时微信会发送 GET 请求到服务器:
至此, 自己的服务器已接入微信公众号平台.
启用服务器
接收微信的推送事件需要将服务器配置启用, 否则会无法收到事件推送.
配置白名单
获取微信公众号 access_token 前, 还需要配置 IP 白名单, 否则会报 40164 错误(invalid ip x.x.x.x, not in whitelist hint...
)
接收并处理微信推送的消息
微信推送都是以 POST 请求发送的.
注意: 公众号调用各接口时都需使用access_token, 文档请看这里, 在 WxJava 中通过
WxMpConfigStorage
管理 access_token, 我们只需要 Redis版 的WxMpConfigStorage
即可(请看 WxJava 官方 Demo).
先看两段段明文的消息报文示例:
1 | <xml> |
1 | <xml> |
微信推送的消息基本都会带有 MsgType
字段, 比较常用的就是:
text
: 普通文本消息event
: 事件, 如果 MsgType 为event
, 那么还会附带Event
字段, 代表事件类型:subscribe
: 关注事件CLICK
: 菜单点击事件VIEW
: 菜单连接查看事件
更多的消息类型以及事件类型查看 me.chanjar.weixin.common.api.WxConsts.XmlMsgType
与 me.chanjar.weixin.common.api.WxConsts.EventType
.
处理这类消息也很简单, 只需要配置 WxMpMessageRouter
即可:
1 |
|
然后在 POST 请求中处理:
1 | "application/xml; charset=UTF-8") (produces = |
授权获取用户信息
在调用授权接口之前, 需要配置网页授权域名, 在 公众号设置 -> 功能设置 -> 网页授权域名
切记, 只需要配置域名, 不要加协议, 也不要加路径, 否则 10003 错误, 也就是 redirect_uri
域名与后台配置不一致错误. redirect_uri
上面配置的网页授权域名, redirect_uri
可以添加参数, 比如标记落地页等. 用户同意授权后微信会在 redirect_uri
后面加上 code
参数, 并重定向到该 URL.
流程走的是标准的 OAUTH2, 什么是 OAUTH2 自行搜索…
主要流程就是:
构建授权 URL(微信跳转到该
redirectUri
时会在参数后面拼接上code
):1
String url = this.wxService.oauth2buildAuthorizationUrl(redirectUri, WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);
用户点击 URL, 微信重定向到
redirectUri
, 并附带上code
参数利用
code
获取access_token
:1
WxMpOAuth2AccessToken accessToken = wxService.oauth2getAccessToken(code);
利用
access_token
获取用户信息:1
WxMpUser user = wxService.oauth2getUserInfo(accessToken, null);
获取 JS-SDK 加密信息
需要提前配置JS接口安全域名, 公众号设置 -> 功能设置 -> JS接口安全域名
1 | WxJsapiSignature jsapiSignature = wxService.createJsapiSignature("当前页面 URL"); |
创建自定义公众号菜单
1 | "/create") ( |
微信支付
支付步骤:
- 调用微信统一下单接口, 拿到 prepay_id
- 根据不同端封装返回参数(小程序支付/JS-SDK支付/H5支付等)
- 前端拉起微信支付
- 用户支付
- 支付成功回调
相关文档:
注意事项
timestamp
驼峰命名问题:
微信公众号中的微信支付采用 JS-SDK, 文档中的 timestamp
中的 s
是小写, 而签名中需要时 timeStamp
(S
大写), 这一点文档中有说明, 需要注意:
1 | wx.chooseWXPay({ |
关注公众号后网站自动登录功能实现
网页端的微信登录多数基于微信开放平台登录功能, 这种方式需要申请开放平台, 比较麻烦.
另外一种扫码登录方式只需要一个微信服务号就行, 大概流程是:
- 点击微信登录, 网站自己弹出一个二维码
- 扫描二维码后弹出公众号的关注界面
- 只要一关注公众号网站自动登录, 第二次扫描登录的时候网站直接登录
- 体验一下 「随便找的一个网站」, 这种扫码登录的方式有利于公众号推广
主要的核心原理就是利用了 带参数二维码 以及 接收事件推送.
所以实现方案大概如下:
- 生成自定义场景值参数, 比如UUID字符串, 设置进 Redis 中, key 生成的字符串, value 为空字符串
- 使用上面生成的随机字符串生成临时带参数二维码(
action_name=QR_STR_SCENE&scene_str={UUID}
) - 将二维码与 UUID 一同返回前端, 前端通过 UUID 轮询登录状态
- 用户扫描二维码, 会有以下两种情况:
- 如果用户还未关注公众号, 则用户可以关注公众号, 关注后微信会将带场景值关注事件推送给开发者.
- 如果用户已经关注公众号, 在用户扫描后会自动进入会话, 微信也会将带场景值扫描事件推送给开发者.
- 根据扫码结果(微信回调拿到自定义字符串与 OpenId), 创建用户(已创建则跳过这步), 修改 Redis 中对应的值改为用户Id或者登录 Token
- 前端轮训拿到了用户 Id 或者 Token, 完成登录.
注意事项
- 配置的服务器 URL 不要拦截(登录拦截等), 只支持 80 或 443 端口.
- 微信消息可能会重复发送, 需要开发者自己确保幂等, 虽然 WxJava 已经带有消息去重逻辑, 但模式实现是单机版的, 所以如果是集群的服务器, 需要自己实现
WxMessageDuplicateChecker
, 并配置到WxMpMessageRouter
中.