仅使用微信的测试公众号,Java开发内容,遇错与参考
- Java接入测试微信公众号调试流程
- 前提
- 创建并配置测试号
- 登陆注册微信测试公众号【沙箱】
- 微信验签
- 免登授权获取用户信息
- 微信接口调试工具的使用
- 创建服务号菜单
- 常见错误
- invalid signature
Java接入测试微信公众号调试流程
前提
- 微信号
- 一个开发工具,我用的idea
- 最好准备一个穿透工具,我用的花生壳
- 去微信官方下载好所需的jar包引入到你的项目,微信脚手架
创建并配置测试号
登陆注册微信测试公众号【沙箱】
页面参数从上到下依次解析:
- 测试号信息 ,请记住并保存下它们。它可以给你换取到调用凭证accesstoken
- 接口配置信息,这里主要是对你的项目进行可行性验证,你需要在你的项目中写上一个可以访问的接口,这边的Token你可以自己定义,点击【提交】按钮的时候,微信服务器会发送请求到你的URL,你需要根据Token去验证签名并返回给微信服务器正确的内容
至于微信的验签怎么做?请参考目录
返回微信验签成功后:
3. 测试号二维码
左边的二维码,就是提供给你沙箱测试的二维码,右边就是扫描了你的二维码关注的用户名称和当前公众号的openId。正式环境的后台也是可以看到每个用户的openId的。
把用户移除再关注,openId不会改变。
-
消息模版接口
新增一个消息模版,模版具体内容以你的业务所需要而定。测试号发送消息稍微会随意一点,正式的公众号后台可以选定行业模版。最终做推送需要记录的模版Id。 -
体验接口权限表
下面展示的都是测试号允许调用的接口权限,点击进去是文档具体描述,应该不需要我再解释了吧。
微信验签
/**
* Created with IntelliJ IDEA.
*
* @Author Nipppppp
* @Date: 2023/03/02/15:10
* @Description: 验签小工具
*
*/
public class WxTokenCheckUtil{
// 与接口配置信息中的Token要一致
private static String token = "";
/**
* 验证签名
* @param signature 微信计算出的前面
* @param timestamp 时间戳
* @param nonce 唯一标识
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// 将token、timestamp、nonce三个参数进行字典序排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(content.toString().getBytes());
//这是你计算出来的签名
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//对比一下你计算出来的签名和微信的是否一致
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
/**
* 一个普通的提供验签开放接口
*/
@RequestMapping("/niptest/valid")
@ResponseBody
public void wxValidTest(HttpServletRequest request, HttpServletResponse response) {
//你可以打个日志看看
log.debug("微信进来了。。。。");
// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
PrintWriter out = null;
try {
out = response.getWriter();
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
}
}
免登授权获取用户信息
如果你需要oauth2免登授权获取用户code换取openId话,请注意权限表里需要开启【网页授权获取用户基本信息】
这里已经踩过坑了,本身我的需求是需要公众号主页菜单点击的时候要拿到个人信息,在我没开启这个权限的时候,是拿不到用户免登code。
主页菜单免登跳转链接如下:
(注意替换appId、redirectUrl,并且redirectUrl需要你对参数进行一下encode编码)
https://open.weixin.qq.com/connect/oauth2/authorize?appid={appId}&redirect_uri={redirectUrl}&response_type=code&scope=snsapi_base&connect_redirect=1#wechat_redirect
code换取用户openId链接如下:
https://api.weixin.qq.com/sns/oauth2/access_token?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code"
如何在H5中拿到用户code,我这边不说明了
流程:
- 获取用户code (注意code含有时效性,只能换一次
- http请求微信服务端,code换取用户openId
- 如果你的数据库中有对实体类和openId的绑定关系的话,现在就可以确认用户了
微信接口调试工具的使用
微信官方提供的调试工具
可以看到官方有提供部分权限功能的调试,最主要的就是先换取接口凭证access_token,再带着接口凭证去访问你需要调用的微信接口。和你在代码里所需要实现的逻辑应该是一致的。
appId、secret也就是你刚创建测试号时候我需要你去记录的必要参数
拿到调用凭证后,我们尝试着调用一下接口。
创建服务号菜单
拿到上一步获取的未过期的access_token ,按照微信提供的api文档,填写你需要的body,检查通过后会生成菜单。
body参数怎么构造、菜单玩法请参考微信api文档。
如果多次修改菜单,微信客户端会有缓存。重新关注公众号,获取最新的菜单。
常见错误
invalid signature
常见于微信验签错误,遇到该提示时请确认:
-
appId、secret 公众号于你本地签名所用的是否一致
-
域名是否一致
这里踩坑两次: ① 问号拼接带参url ,像这种https://....的内容 需要enconde编码一下,转成https%3A%2F%2F....。你实际以为你是https://,但是计算的时候可不一定是一样的字符串。 ② 个人有遇到,明明是https的域名,计算签名的时候,断点进去是http(HttpServletRequest中的获取域名拿到的就是http。。。nginx加了证书后终于可以拿到https了)
如果都确认完毕还是报错,请打上断点。
微信js签名校验工具
看看小工具返回的签名和你的是否完全一致
文章出处登录后可见!