一、微信公众号
(一)基础信息
微信授权类型
自己的网站、APP等第三方,要实现接入微信授权登录,有多种方式:微信公众号(网页)、微信小程序、微信开放平台(APP)等等。
【项目代码】
GitHub - liyinchigithub/springboot-learn: springboot 学习项目
微信公众号(网页)
- 公众号配置JS安全域名、code回调域名
- 微信授权登录,获取access_token、openid等用户信息
- jssdk认证(签名)
- 调用jssdk相关方法调用
- 花生壳域名内网穿透
- 微信开放平台地址汇总
1.申请公众号
(1)第一步 认证微信公众帐号
首先,得拥有一个通过认证了的微信公众号或者开发者帐号认证费一年300块钱;
(2)第二步 添加安全域名
在公众帐号平台后台添加 app 运行的域名地址,为某个域名添加白名单功能,让微信知道这个ip是你的机子。
例如:微信公众号是”瓜瓜“,添加了 guagua.com 为安全域名,那么我在 guagua.com 上的网页可以使用瓜瓜下公众帐号的数字签名了;
(3)第三步 生成数字签名
在微信公众平台后台上面能找到一个 appid 及 secret字符串
通过这两个参数,请求微信提供的两个公开API地址,生成对应的access_token后再生成ticket再通过规则加密成数字签名,数字签名必须在服务端生成,这里我以Springboot来实现
2.微信公众号平台配置
微信公众平台微信公众平台,给个人、企业和组织提供业务服务与用户管理能力的全新服务平台。https://mp.weixin.qq.com/
(1)添加开发者的微信号到公众号人员设置中
绑定运营者微信号
(2)添加开发者微信账号到web
菜单路径:首页》开发》开发者工具》Web开发工具 》绑定开发者微信号
绑定开发者微信号
(3)查看微信公众号appID和appScrent
菜单路径:首页》开发》基本配置 》公众号开发信息
(4)将AppID和AppSecret配置到项目中
3.微信公众平台接口调试工具(检测准备工作情况)
如果微信公众号认证还没通过,可以先使用官方提供的测试号来进行调试。
方便调试,在线工具:微信公众平台接口调试工具
注意:这边使用的appid和secret是测试号的环境(沙盒)。
微信公众平台
遇到问题:如果接口报错返回提示无效ip
解决办法:需要将本地电脑ip地址,添加到公众号ip白名单中。
菜单路径:设置与开发 > 基本配置 > IP白名单 > 查看/添加
重新请求,成功获取accessToken
【使用微信JSSDK示例】
(1)获取关注者列表接口
① 基础支持-获取access_token接口
备注:旧版本是formdata格式(2020年),新版本是json格式(2024年6月16日)
{ "grant_type": "client_credential", "appid": "xxxxx", "secret": "xxxxxx" }
② 获取关注列表接口
传入上一步access_token参数值,作为鉴权参数。
所有关注此公众号的微信号openid都在数组里
(2)获取用户基本信息接口 /user/info
①填入上一步获取到的access_token
②填入上上步获取到的openid(可通过获取关注者列表接口获取到)
最新版没有用户昵称(2024年6月16日)
遇到问题:token过期
{ "errcode": 42001, "errmsg": "access_token expired rid: 666fa0b9-04633663-35fb85fa" }“
解决办法:重新调用,基础支持获取access_token获取新的token
网页授权 | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
前端通过用户触发请求公众号授权接口
- 第一种形式:location.href
<a href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"></a>
注意:这种方式会暴露appid在前端页面
- 第二种形式:按钮事件(推荐)
<button @click="toWechatLogin">toWechatLogin() {/*** @description 前端请求微信开放平台(微信登录授权接口,回调code)* @param appid 微信公众号appid* @param redirect_url 微信授权流程,获取code回调地址* */// TODO 用户触发发起授权链接var appid = 'xxxxx';// 微信公众号APPIDvar redirect_uri = encodeURIComponent('http://xxxxx.zicp.vip/code');// 网页授权code回调地址window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`}
微信开发者工具,访问本地开发环境地址(模拟微信客户端内置浏览器打开业务域名,一般是登录页面)
返回数据
注意:请求`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`,不能使用客户端自带http请求库(如:axios、request)来发起请求这个地址,而是只能使用location.href方式
4.方向代理配置
第一种:本地配置Nginx代理转发(推荐)
Nginx文件
// 修改nginx.conf文件
server {listen 80;#监听的端口号server_name wxh5.xxx.fssh.com;#本地访问的域名(注意: host文件也要配置)location / {# 前端项目接口, 反向代理路径proxy_pass http: //127.0.0.1:9020/;#代理的域名加本地项目启用的端口号 - > nginx服务会代理本地起的服务从而可以在wx开发者工具上调试, 因为你的目的就是为了在工具调试本地的微信授权登录的流程}location / sns {# 微信公众号平台接口, 反向代理路径#return 666;proxy_pass https: //api.weixin.qq.com; }location / code {# code回调接口地址proxy_pass http: //127.0.0.1:4343; }location / api {# 后端项目接口, 反向代理路径proxy_pass http: //127.0.0.1:4343; }
}
host文件
127.0.0.1 wxh5.xxx.fssh.com
教程:window安装配置nginx(window Nginx安装配置)
原本我使用花生壳做内网穿透,但百度到一篇文件,不使用花生壳,可以直接修改hosts文件+nginx配置,就可以用本地自定义的域名来通过微信开发者工具访问到前端项目、前端项目访问后端接口,具体如下。
cd /usr/local/etc/nginx open /usr/local/etc/nginx
我的本地前端项目地址、端口
127.0.0.1:9020
我的本地后端项目地址、端口
127.0.0.1:4343
重启nginx
sudo nginx -s reload
微信公众号js接口安全域名配置(域名与nginx配置自定义本地域名一致)
微信公众号测试号,回调域名配置(域名与nginx配置自定义本地域名一致)
微信开发者工具,访问本地前端项目,url输入自定义本地域名
开发者工具url输入,自定义本地域名+/api/
示例:后端 接口/code
对应nginx中的/code如下:
nginx.conf文件
总结,本地nginx文件配置流程:
- (1)自定义本地访问的域名
- (2)前端项目本地IP和端口
- (3)后端项目本地IP和端口
- (4)微信公众号平台接口域名
- (5)JSSDK域名
备注:如果使用nodejs anywhere库启动打包后静态文件dist文件夹,那么IP也是127.0.0.1+anywhere端口号修改配置到nginx
5.微信JSSDK引入与配置
前端什么时候需要引入微信JS-SDK?
(1)如果你的目的是让用户点击按钮后通过重定向到微信授权页面进行登录,那么不需要引入微信JS-SDK。
这种情况下,用户的登录流程是完全由后端处理的,前端只负责触发重定向。
<!-- src/main/resources/static/wechatLogin.html --> <!DOCTYPE html>
<html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wechat Login</title>
</head><body>
<h1>Wechat Login Test</h1>
<button onclick="location.href='/login/wechat'">Login with Wechat</button>
<!-- <button onclick=window.location.href=`https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxx&redirect_uri=https://xxxx.vicp.fun/login/wechat/callback&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`>Login with Wechat
</button>-->
</body>
</html>
<!-- wechatLogin.html 页面本身不需要包含请求参数 code 和 state。 这个页面只是提供一个按钮,用户点击后会被重定向到微信的授权页面。 在这个过程中,code 和 state 参数是由微信在用户授权后自动附加到回调URL上的。 -->
(2)当你需要用到用户地理位置、微信支付、分享等。
如果你需要在你的H5页面中使用这些功能,或者需要通过微信网页直接获取用户信息而不是重定向,那么你应该引入和配置JS-SDK。
引入和配置步骤
(1)引入JS-SDK:
在你的HTML页面中,添加以下脚本标签来引入微信JS-SDK。
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
(2)配置JS-SDK:
你需要后端提供JS-SDK的配置信息,包括appId, timestamp, nonceStr, signature等。这些信息需要通过调用微信的接口获得。
配置示例如下:
wx.config({ debug: true, // 开启调试模式appId: '你的AppID', // 必填,公众号的唯一标识 timestamp: '生成签名的时间戳', // 必填,生成签名的时间戳nonceStr: '生成签名的随机串', // 必填,生成签名的随机串 signature: '签名', // 必填,签名 jsApiList: ['checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表 });
(3)发起微信登录请求:
如果你决定使用JS-SDK来处理登录,可以使用wx.login方法来发起微信登录请求。
wx.login({
success: function(res) { if (res.code) { // 使用返回的code去后端换取access_token等信息 } else { console.log('登录失败!' + res.errMsg); } } });
在wechatLogin.html实现引入JSSDK并获取用户地理位置、分享。
(1)你需要从后端获取必要的配置参数(appId, timestamp, nonceStr, signature),这通常涉及到服务器端的一些处理,以确保安全性。这里假设你已经有了一个API可以调用来获取这些数据。
在HTML中添加以下脚本来配置SDK
(2)使用JS-SDK获取地理位置
在配置成功后,你可以调用wx.getLocation方法来获取用户的地理位置:
<script>
wx.ready(function() {// 获取地理位置wx.getLocation({type: 'wgs84',success: function (res) {var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。var speed = res.speed; // 速度,以米/每秒计var accuracy = res.accuracy; // 位置精度alert('Latitude: ' + latitude + '\nLongitude: ' + longitude);}});// 配置分享给朋友的信息wx.updateAppMessageShareData({ title: '分享标题', // 分享标题desc: '分享描述', // 分享描述link: 'https://yourwebsite.com', // 分享链接imgUrl: 'https://yourwebsite.com/image.jpg', // 分享图标success: function () {// 设置成功alert('已分享');}});// 配置分享到朋友圈的信息wx.updateTimelineShareData({ title: '分享标题', // 分享标题link: 'https://yourwebsite.com', // 分享链接imgUrl: 'https://yourwebsite.com/image.jpg', // 分享图标success: function () {// 设置成功alert('已分享到朋友圈');}});
});
</script>
(3)处理错误
添加错误处理来响应配置失败的情况:
<script>
wx.error(function(res){// config信息验证失败会执行error函数,如签名过期导致验证失败alert("Error: " + res.errMsg);
});
</script>
总结
如果你的页面只是需要一个简单的微信登录按钮,并通过后端处理登录流程,那么不需要引入微信JS-SDK。
6.UnionID 微信开放平台
(1)如果需要在多公众号、移动应用之间做用户共通,则需前往微信开放平台,将这些公众号和应用绑定到一个开放平台账号下,绑定后,一个用户虽然对多个公众号和应用有多个不同的OpenID,但他对所有这些同一开放平台账号下的公众号和应用,只有一个UnionID,可以在用户管理-获取用户基本信息(UnionID机制)文档了解详情。
7.公众号消息会话
(1)群发消息:
公众号可以以一定频次(订阅号为每天1次,服务号为每月4次),向用户群发消息,包括文字消息、图文消息、图片、视频、语音等。
(2)被动回复消息:
在用户给公众号发消息后,微信服务器会将消息发到开发者预先在开发者中心设置的服务器地址(开发者需要进行消息真实性验证),公众号可以在5秒内做出回复,可以回复一个消息,也可以回复命令告诉微信服务器这条消息暂不回复。被动回复消息可以设置加密(在公众平台官网的开发者中心处设置,设置后,按照消息加解密文档来进行处理。其他3种消息的调用因为是API调用而不是对请求的返回,所以不需要加解密)。
(3)客服消息:
用户在公众号内发消息/触发特定行为后,公众号可以给用户发消息。
具体发送规则见公众号客服消息文档:客服账号管理 | 微信开放文档
(4)模板消息:
在需要对用户发送服务通知(如刷卡提醒、服务预约成功通知等)时,公众号可以用特定内容模板,主动向用户发送消息。
8.返回码
微信开放文档
遇到问题:微信开发者工具访问测试页面,点击授权微信登录按钮后,跳转提示”Scope 参数错误或没有 Scope 权限“
解决办法(排查方案):
- 使用的是订阅号,订阅号没有权限使用网页授权,详细可参考接口权限:微信开放文档
- 需要已认证的服务号
- 网页授权回调域名填写错误
- Scope参数顺序不对
- 服务号不支持扫码登录,要网站应用才支持:关于微信快速登录功能的说明 | 微信开放文档
- snsapi_userinfo的接口权限被封
https://mp.weixin.qq.com/advanced/advanced?action=table&token=1037385634&lang=zh_CN
接口权限 》网页服务》 网页权限》
设置网页授权域名
参考:网页授权 | 微信开放文档
参考:Scope 参数错误或没有 Scope 权限,错误码:10005 | 微信开放社区
第三步:依据接口文档实现业务逻辑
验证URL有效性成功后即接入生效,成为开发者。
你可以在公众平台网站中申请微信认证,认证成功后,将获得更多接口权限,满足更多业务需求。
成为开发者后,用户每次向公众号发送消息、或者产生自定义菜单、或产生微信支付订单等情况时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,开发者可以依据自身业务逻辑进行响应,如回复消息。
公众号调用各接口时,一般会获得正确的结果,具体结果可见对应接口的说明。返回错误时,可根据返回码来查询错误原因。全局返回码说明
用户向公众号发送消息时,公众号方收到的消息发送者是一个OpenID,是使用用户微信号加密后的结果,每个用户对每个公众号有一个唯一的OpenID。
此外,由于开发者经常有需在多个平台(移动应用、网站、公众账号)之间共通用户账号,统一账号体系的需求,微信开放平台(open.weixin.qq.com)提供了UnionID机制。开发者可通过OpenID来获取用户基本信息,而如果开发者拥有多个应用(移动应用、网站应用和公众账号,公众账号只有在被绑定到微信开放平台账号下后,才会获取UnionID),可通过获取用户基本信息中的UnionID来区分用户的唯一性,因为只要是同一个微信开放平台账号下的移动应用、网站应用和公众账号,用户的UnionID是唯一的。换句话说,同一用户,对同一个微信开放平台账号下的不同应用,UnionID是相同的。详情请在微信开放平台的资源中心-移动应用开发-微信登录-授权关系接口调用指引-获取用户个人信息(UnionID机制)中查看。
另请注意,微信公众号接口必须以http://或https://开头,分别支持80端口和443端口。
9.AccessToken过期刷新
因为accessToken获取次数有限,我想在有效期7200秒内,使用同一个accessToken去请求获取用户信息,如果token过期了用刷新token去换一个新的accessToken,如果刷新token也过期了,那么再去重新请求新的accessToken,避免把当日accessToken获取次数用完。
如何实现?
为了有效管理微信 accessToken 的使用和刷新,你可以实现一个服务来处理 accessToken 的获取、存储、刷新以及过期逻辑。
这个服务将负责确保在请求微信 API 时使用有效的 accessToken,并在必要时自动刷新。
实现步骤:
(1)存储 accessToken 和 refreshToken:
你可以使用数据库或内存缓存(如 Redis)来存储 accessToken、refreshToken 及其过期时间。
(2)获取 accessToken 的服务方法:
- 检查当前存储的 accessToken 是否有效。
- 如果有效,直接返回它。
- 如果无效,检查 refreshToken 是否还有效。
- 如果 refreshToken 有效,使用它来获取新的 accessToken。
- 如果 refreshToken 也失效,重新进行认证以获取新的 accessToken 和 refreshToken。
10.开发者注意事项
(1)微信公众平台开发
是指为微信公众号进行业务开发,为移动应用、PC端网站、公众号第三方平台(为各行各业公众号运营者提供服务)的开发,请前往微信开放平台接入。
(2)在申请到认证公众号之前,你可以先通过测试号申请系统,快速申请一个接口测试号,立即开始接口测试开发。
(3)在开发过程中,可以使用接口调试工具来在线调试某些接口。
(4)每个接口都有每日接口调用频次限制,可以在公众平台官网-开发者中心处查看具体频次。
(5)在开发出现问题时,可以通过接口调用的返回码,以及报警排查指引(在公众平台官网-开发者中心处可以设置接口报警),来发现和解决问题。
(6)公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,access_token在2小时内有效,过期需要重新获取,但1天内获取次数有限,开发者需自行存储,详见获取接口调用凭据(access_token)文档。10.