前提:这里只针对企业微信(下称企微)内部联系人和外部联系人的回调举例和编码,暂时未贴出回复被动消息等回调,示例语言为java。
地址:企微java的实现
下载下来解压之后有下面几个类:
这里为不影响篇幅我就不贴出代码,自己去下载。
需要发的就一个类MessageUtil(是我自己实现的,解密xml的工具类)
注:前提是maven仓库中有dom4j的依赖,版本自己去定义,我这里用的springboot自带的1.6.x
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MessageUtil {
/**
* 解析微信发来的请求(XML).
*
* @param msg 消息
* @return map
*/
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(final String msg) {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 从request中取得输入流
try (InputStream inputStream = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8.name()))) {
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList) {
map.put(e.getName(), e.getText());
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
细心的同学已经发现了,这货的参数跟微信的差不了多少。
其一是回调的接口地址,其二是需要验签用的token,其三是随机的key,然后我们看一下回调接口的回调参数
请求方式:GET
demo地址:
http://api.3dept.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS%2525C3%252597tamp=13500001234&nonce=123412323&echostr=ENCRYPT_STR
然后看到回调参数有
msg_signature=ASDFQWEXZCVAQFASDFASDFSS
timestamp=13500001234
nonce=123412323
echostr=ENCRYPT_STR
根据企微提供的加密类我们可以直接对该参数进行解密
post请求为企微验证通过之后发送的数据(接口地址与get请求一样)
首先是get请求
/**
* get 请求 验签.
*
* @param msgSignature 加密
* @param timestamp 时间戳
* @param nonce 随机
* @param echostr .
* @param response .
* @throws Exception .
*/
@GetMapping(value = "/callback")
public void reveiceMsg(@RequestParam(name = "msg_signature") final String msgSignature,
@RequestParam(name = "timestamp") final String timestamp,
@RequestParam(name = "nonce") final String nonce,
@RequestParam(name = "echostr") final String echostr,
final HttpServletResponse response) throws Exception {
//企业回调的url-----该url不做任何的业务逻辑,仅仅微信查看是否可以调通.
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey);
// 随机字符串
String sEchoStr = wxcpt.verifyURL(msgSignature, timestamp, nonce, echostr);
PrintWriter out = response.getWriter();
try {
//必须要返回解密之后的明文
if (StringUtils.isBlank(sEchoStr)) {
System.out.println("URL验证失败");
} else {
System.out.println("验证成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
out.write(sEchoStr);
out.flush();
}
get请求有可能解密失败
关于加解密会报错,可以查看文档:文档
Post方式请求:
/**
* 企业微信客户联系回调.
*
* @param request request
* @param sMsgSignature 签名
* @param sTimestamp 时间戳
* @param sNonce 随机值
* @return success
*/
@ResponseBody
@PostMapping(value = "/callback")
public String callback(final HttpServletRequest request,
@RequestParam(name = "msg_signature") final String sMsgSignature,
@RequestParam(name = "timestamp") final String sTimestamp,
@RequestParam(name = "nonce") final String sNonce) {
try {
InputStream inputStream = request.getInputStream();
String sPostData = IOUtils.toString(inputStream, "UTF-8");
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey);
//解密
String sMsg = msgCrypt.decryptMsg(msgSignature, timeStamp, String nonce, postData);
//将post数据转换为map
Map<String, String> dataMap = MessageUtil.parseXml(sMsg);
//然后去操作你的业务逻辑
} catch (Exception e) {
e.printStackTrace();
}
return "success";
}