一.微信公众号基本设置中配置好服务器配置,服务器地址(例如http://域名/base/wx_message/redirect)为回调地址
二.springboot接口代码
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<!-- <version>${aws.version}</version>-->
<version>1.12.99</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
/**
* 消息重定向路径
* @param req
* @return
*/
@RequestMapping("redirect")
@Inner(value = false)
public String redirect(String signature,
String timestamp,
String nonce,
String echostr,
HttpServletRequest req){
return iWxMessageService.redirect(signature, timestamp, nonce, echostr, req);
}
@Override
public String redirect(String signature,
String timestamp,
String nonce,
String echostr,
HttpServletRequest req) {
String requestMethod = req.getMethod();
if (requestMethod.equals("POST")) { // 处理 POST 请求
Map<String, String> msgMap = this.parseXmlData2Map(req);
//处理订阅事件
String subscribeMsgPopupEvent = msgMap.get("SubscribeMsgPopupEvent");
List<Map> list = JSONArray.parseArray(subscribeMsgPopupEvent, Map.class);
System.out.println("666666" + msgMap.toString());
return "success";
} else if (requestMethod.equals("GET")) { // 处理 GET 请求
log.info("接收到微信服务器的验证消息,[{},{},{}, {}]", signature, timestamp, nonce, echostr);
if(StringUtils.isEmpty(signature) || StringUtils.isEmpty(timestamp) || StringUtils.isEmpty(nonce) || StringUtils.isEmpty(echostr)){
throw new IllegalArgumentException("请求参数非法,请核实!");
}
Boolean aBoolean = this.checkSignature(signature, timestamp, nonce);
if(!aBoolean){
return "签名不合法!";
}
return echostr;
} else {
return "不是 GET 和 POST";
}
}
public Boolean checkSignature(String signature, String timestamp, String nonce) {
String token = "xxxxx";
String[] arr = {token, timestamp, nonce};
Arrays.sort(arr);
StringBuilder sb = new StringBuilder();
for (String a : arr){
sb.append(a);
}
String str = sb.toString();
// SHA1签名生成
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
md.update(str.getBytes());
byte[] digest = md.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
log.info("接收的签名:{}", signature);
log.info("生成的签名:{}", hexstr.toString());
return hexstr.toString().equals(signature);
}
public Map<String, String> parseXmlData2Map(HttpServletRequest req) {
HashMap<String, String> msgMap = new HashMap<>();
try {
ServletInputStream inputStream = req.getInputStream();
// dom4j 用于读取 XML 文件输入流的类
SAXReader saxReader = new SAXReader();
// 读取 XML 文件输入流, XML 文档对象
Document document = saxReader.read(inputStream);
// XML 文件的根节点
Element root = document.getRootElement();
// 所有的子节点
List<Element> childrenElement = root.elements();
for (Element element : childrenElement) {
msgMap.put(element.getName(), element.getStringValue());
}
} catch (Exception e) {
e.printStackTrace();
}
return msgMap;
}
三.在公众号后台启用配置时会调用GET方法,关注和取消关注公众号时会调用POST方法,订阅事件需要在小程序中调用弹框,用户同意或者拒绝订阅微信后台都会调用这个回调地址,推送接口文档:微信官方文档