流程图:
只是这里的消息回调,仅作为提示,群内有消息了。不是具体的消息,而是类似这样的结构,:
如果需要获取消息,还需要拉取企微群内消息方法,这个后续再更新。
好了,我们开始吧。
开启消息回调和接收消息回调,地址是一样的,只是
开启消息回调,get请求,
接受消息回调,post请求。
代码如下:
开启消息回调
Controller层:
@ApiOperation(value = "企业微信url验证")
@GetMapping("/weworkUrl")
public void weworkUrl(@RequestParam(name = "msg_signature")String msgSignature,
@RequestParam(name = "timestamp")String timestamp,
@RequestParam(name = "nonce")String nonce,
@RequestParam(name = "echostr")String echostr, HttpServletResponse response) {
try {
echostr = echostr.replace(" ", "+");//有时+号会被删除
queryMarketingRecordService.weworkUrl(msgSignature,timestamp,nonce,echostr,response);
} catch (Exception e) {
e.printStackTrace();
LogUtils.info("Exception 企业微信url验证出错:"+(e.getMessage().length() > 2000 ? e.getMessage().substring(0, 2000) : e.getMessage()));
}
}
具体方法层:
public void weworkUrl(String sVerifyMsgSig, String sVerifyTimeStamp, String sVerifyNonce, String sVerifyEchoStr, HttpServletResponse response) throws AesException {
String sToken = weworkToken;//填你自己的
String sCorpID = weworkCorpId;//填你自己的
String sEncodingAESKey = weworkEncodingAESKey;//填你自己的
RequestLog requestLog = new RequestLog();
requestLog.setType("we_work_verify");
requestLog.setRequestTime(LocalDateTime.now());
Map<String,String> map = new HashMap<>();
map.put("sToken",sToken);
map.put("sCorpID",sCorpID);
map.put("sEncodingAESKey",sEncodingAESKey);
requestLog.setRequestContent(JsonUtils.toJson(map));
String sEchoStr = ""; //需要返回的明文
try {
WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);//工具类去官方下载,文章中我提供了链接,去下载json格式的
sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
sVerifyNonce, sVerifyEchoStr);
requestLog.setResponseContent(sEchoStr);
response.getWriter().print(sEchoStr);//这行代码不写,后面配置的时候可能会有问题
} catch (Exception e) {
//验证URL失败,错误原因请查看异常
e.printStackTrace();
}finally {
requestLogRepository.save(requestLog);
}
}
接受消息回调
Controller层:
@ApiOperation(value = "企业微信接收信息")
@PostMapping("/weworkUrl")
public String weworkUrl(@RequestParam(name = "msg_signature")String msgSignature,@RequestParam(name = "timestamp",required = false)String timestamp, @RequestParam(name = "nonce",required = false)String nonce, @RequestBody String xmlPayload // 接收整个 XML 字符串) {
try {
return queryMarketingRecordService.weworkUrl(msgSignature,timestamp,nonce,xmlPayload);
} catch (Exception e) {
e.printStackTrace();
LogUtils.info("Exception 企业微信url接收信息出错:"+(e.getMessage().length() > 2000 ? e.getMessage().substring(0, 2000) : e.getMessage()));
}
return null;
}
具体方法层:
//接收企微推送来的信息
public String weworkUrl(String msgSignature, String timestamp, String nonce,String xmlPayload) throws AesException, JAXBException {
NotifyLog notifyLog = new NotifyLog();
notifyLog.setResponseTime(LocalDateTime.now());
notifyLog.setApiKey("we_work_callback");
String sToken = weworkToken;
String sCorpID = weworkCorpId;
String sEncodingAESKey = weworkEncodingAESKey;
String sReqMsgSig = msgSignature;
String sReqTimeStamp = timestamp;
String sReqNonce = nonce;
// post请求的密文数据
JAXBContext jaxbContext = JAXBContext.newInstance(WeworkXml.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(xmlPayload);
WeworkXml weworkXml = (WeworkXml) unmarshaller.unmarshal(reader);
String toUserName = weworkXml.getToUserName();
String agentID = weworkXml.getAgentID();
String encrypt = weworkXml.getEncrypt();
Map<String,String> paramMap = new HashMap<>();
paramMap.put("tousername",toUserName);
paramMap.put("agentid",agentID);
paramMap.put("encrypt",encrypt);
String sReqData = JsonUtils.toJson(paramMap);
WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);
try {
String sMsg = wxcpt.DecryptMsg(sReqMsgSig, sReqTimeStamp, sReqNonce, sReqData);
notifyLog.setRequestContent(sMsg);
LogUtils.info("收到企微推送消息回调 after decrypt msg: " + sMsg);
//处理其他业务
} catch (Exception e) {
e.printStackTrace();
}finally {
notifyLogService.save(notifyLog);
}
return "";
}
基本就可以测试了。
测试开通回调:
这里的url 是需要能公开访问到的链接。
测试回调成功:
测试回调失败:
失败可能原因:
1、没有把EchoStr返回,或返回的EchoStr带了“”
正式上线前, 需要先去配置一下:
配置失败:
可能原因:返回值的时候,返回的数据带了引号,如果没带引号,也还是提示“回调地址请求不通过”。那应该就是方法不对。
关于这点,我相信很多朋友和我一样,被卡了很久,我去搜了大量的帖子,官方的社群和回复都问了。官方回复是:
但我试了一下,还是不行。
还有人说,
可能是 相应时间 超过1秒。
可能是 接收格式不对可能是 secret 没配置
可能是返回值 xml 格式
可能是 int(sEchoStr) 没有转成整形
可能是 response.getWriter().print()
我挑了最后试下, response.getWriter().print() ,可以了。具体可看上方我提供的代码。
官方加解密工具类在这里: