| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 开发测试 -> 对接企业微信4:接收消息与事件 -> 正文阅读 |
|
[开发测试]对接企业微信4:接收消息与事件 |
关于接收消息为了能够让自建应用和企业微信进行双向通信,企业可以在应用的管理后台开启接收消息模式。
|
参数 | 必须 | 说明 |
---|---|---|
msg_signature | 是 | 企业微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体 |
timestamp | 是 | 时间戳 |
nonce | 是 | 随机数 |
echostr | 是 | 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、CorpID四个字段,其中msg即为消息内容明文 |
企业后台收到请求后,需要做如下操作:
以上2~3步骤可以直接使用验证URL函数一步到位。
之后接入验证生效,接收消息开启成功。
开启接收消息模式后,企业微信会将消息发送给企业填写的URL,企业后台需要做正确的响应。
假设企业的接收消息的URL设置为http://api.3dept.com。
请求方式:POST
请求地址 :http://api.3dept.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS×tamp=13500001234&nonce=123412323
接收数据格式 :
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<AgentID><![CDATA[toAgentID]]></AgentID>
<Encrypt><![CDATA[msg_encrypt]]></Encrypt>
</xml>
参数说明
参数 | 说明 |
---|---|
ToUserName | 企业微信的CorpID,当为第三方套件回调事件时,CorpID的内容为suiteid |
AgentID | 接收的应用id,可在应用的设置页面获取 |
Encrypt | 消息结构体加密后的字符串 |
企业收到消息后,需要作如下处理:
以上1~2步骤可以直接使用解密函数一步到位。
3步骤其实包含加密被动回复消息、生成新签名、构造被动响应包三个步骤,可以直接使用加密函数一步到位。
被动响应包的数据格式:
<xml>
<Encrypt><![CDATA[msg_encrypt]]></Encrypt>
<MsgSignature><![CDATA[msg_signature]]></MsgSignature>
<TimeStamp>timestamp</TimeStamp>
<Nonce><![CDATA[nonce]]></Nonce>
</xml>
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
Encrypt | 是 | 经过加密的消息结构体 |
MsgSignature | 是 | 消息签名 |
TimeStamp | 是 | 时间戳 |
Nonce | 是 | 随机数,由企业自行生成 |
?java解密:
注意事项:
6.针对json解析,需要编译导入架包json.jar,我们有提供,官方源码下载地址 :?GitHub - stleary/JSON-java: A reference implementation of a JSON package in Java.
7.异常java.security.InvalidKeyException:illegal Key Size的解决方案:
在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7 Download
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件,如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件
此处参考博客:java.security.InvalidKeyException: Illegal key size错误_伫望向北的博客-CSDN博客
记得重启项目哦
更多参考官方文档:接收消息与事件 - 企业微信API
以下我自己用Servlet写的对接代码
package com.thinkgem.jeesite.util;
import com.google.common.collect.Maps;
import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizJsonMsgCrypt;
import com.thinkgem.jeesite.common.mapper.JsonMapper;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.web.Servlets;
import com.thinkgem.jeesite.modules.sys.entity.Ctiserver;
import com.thinkgem.jeesite.modules.sys.entity.InterfaceLog;
import com.thinkgem.jeesite.modules.sys.entity.Queue;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.CtiserverService;
import com.thinkgem.jeesite.modules.sys.service.InterfaceLogService;
import com.thinkgem.jeesite.modules.sys.service.QueueService;
import com.thinkgem.jeesite.modules.sys.service.SystemService;
import com.thinkgem.jeesite.modules.sys.utils.SysUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class weiXinCheckUrl extends HttpServlet{
@Autowired
private InterfaceLogService interfaceLogService;
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public weiXinCheckUrl() {
super();
}
/**
* msg_signature 是 企业微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体
* timestamp 是 时间戳
* nonce 是 随机数
* echostr 是 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、CorpID四个字段,其中msg即为消息内容明文
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String msg_signature = request.getParameter("msg_signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr");
System.out.println("消息推送前验证=============================================");
System.out.println("msg_signature:"+msg_signature);
System.out.println("timestamp:"+timestamp);
System.out.println("nonce:"+nonce);
System.out.println("echostr:"+echostr);
String sToken= SysUtils.getSysConfigValue("check_url_token", "");
String sEncodingAESKey = SysUtils.getSysConfigValue("check_url_key", "");
String sCorpID = SysUtils.getSysConfigValue("enterprise_wechat_id", "");
WXBizJsonMsgCrypt wxcpt = null;
try {
wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);
} catch (AesException e) {
e.printStackTrace();
}
String sEchoStr = ""; //需要返回的明文
try {
sEchoStr = wxcpt.VerifyURL(msg_signature, timestamp,
nonce, echostr);
System.out.println("返回的消息是===verifyurl echostr: " + sEchoStr);
// 验证URL成功,将sEchoStr返回
// HttpUtils.SetResponse(sEchoStr);
} catch (Exception e) {
//验证URL失败,错误原因请查看异常
e.printStackTrace();
}
UtilHelp.PrintWriter(sEchoStr, "json", request, response);
}
/**
* msgSignature 签名串,对应URL参数的msg_signature
* timeStamp 时间戳,对应URL参数的timestamp
* nonce 随机串,对应URL参数的nonce
* postData 密文,对应POST请求的数据
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Date beginCreateDate=new Date();
String isSuccess="0";
String returnValueNormal="0";
String results="";
String requestVal="";
String sReqMsgSig = request.getParameter("msg_signature");
String sReqTimeStamp = request.getParameter("timestamp");
String sReqNonce = request.getParameter("nonce");
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
requestVal="msg_signature:"+sReqMsgSig+"; timestamp:"+sReqTimeStamp+";nonce "+sReqNonce;
String lines;
StringBuffer bodyXml = new StringBuffer("");
while ((lines = reader.readLine()) != null) {
lines = new String(lines.getBytes(), "utf-8");
bodyXml.append(lines);
}
System.out.println(bodyXml);
Document Doc = null;
String strXml="";
if(StringUtils.isNotBlank(bodyXml)){
strXml=bodyXml.toString().replaceAll("<!\\[CDATA\\[","").replaceAll("]]>","");
try {
Doc = DocumentHelper.parseText(UtilHelp.formatXml(strXml)); // 将字符串转为XML
} catch (DocumentException e) {
returnValueNormal="1";
results="解析转为xml";
e.printStackTrace();
}
}
String toUserName = "";
String AgentID = "";
String Encrypt = "";
Element root = Doc.getRootElement(); // 获取根节点
List<Element> contents = root.content();
for(int i=0;i<contents.size();i++){
Element element = contents.get(i);
String text = element.getText();
if("ToUserName".equals(element.getName())){
toUserName=element.getText();
System.out.println("用户"+toUserName+" ;");
}else if("AgentID".equals(element.getName())){
AgentID=element.getText();
System.out.println("在应用id为:"+AgentID+"的因应用 ;");
}else if("Encrypt".equals(element.getName())){
Encrypt=element.getText();
System.out.println("发送了消息为:"+Encrypt+" ;");
}
System.out.println(element.getText());
}
System.out.println("消息推送前验证=============================================");
System.out.println("sReqMsgSig:"+sReqMsgSig);
System.out.println("sReqTimeStamp:"+sReqTimeStamp);
System.out.println("sReqNonce:"+sReqNonce);
System.out.println("body数据是哪个?:");
System.out.println("strXml:"+strXml);
String sToken= SysUtils.getSysConfigValue("check_url_token", "");
String sEncodingAESKey = SysUtils.getSysConfigValue("check_url_key", "");
String sCorpID = SysUtils.getSysConfigValue("enterprise_wechat_id", "");
WXBizJsonMsgCrypt wxcpt = null;
try {
wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);
} catch (AesException e) {
e.printStackTrace();
}
String sMsg= ""; //需要返回的明文
try {
sMsg = wxcpt.DecryptMsg(sReqMsgSig, sReqTimeStamp, sReqNonce, Encrypt);
System.out.println("解密后得到的消息是===sMsg: " + sMsg);
} catch (Exception e) {
e.printStackTrace();
returnValueNormal+="解密消息失败";
}
String CreateTime=new Date().getTime()+"";
//返回消息格式
/**
* Encrypt 是 经过加密的消息结构体
MsgSignature 是 消息签名
TimeStamp 是 时间戳
Nonce 是 随机数,由企业自行生成
**/
String sEncryptMsg="";
/* String sRespData = "{\"ToUserName\":\"wx5823bf96d3bd56c7\"," +
"\"FromUserName\":\"mycreate\"," +
"\"CreateTime\": 1409659813," +
"\"MsgType\":\"text\"," +
"\"Content\":\"hello\"," +
"\"MsgId\":4561255354251345929," +
"\"AgentID\": 218}";*/
String Content="我回复了你的消息,抱歉,暂时我只会回复这一句话!";
Map<String,String> resultMap=new HashMap<>();
resultMap.put("ToUserName",toUserName);
resultMap.put("CreateTime",CreateTime);
resultMap.put("MsgType","text");
resultMap.put("Content",Content);
resultMap.put("MsgId",sReqMsgSig);
resultMap.put("AgentID",sCorpID);
String jsonString = JsonMapper.toJsonString(resultMap);
try{
sEncryptMsg = wxcpt.EncryptMsg(jsonString, sReqTimeStamp, sReqNonce);
System.out.println("after encrypt sEncrytMsg: " + sEncryptMsg);
// 加密成功
// TODO:
// HttpUtils.SetResponse(sEncryptMsg);
}
catch(Exception e) {
e.printStackTrace();
// 加密失败
}
String returnXml="<xml>\n" +
" <Encrypt><![CDATA["+sEncryptMsg+"]]></Encrypt>\n" +
" <MsgSignature><![CDATA["+sReqMsgSig+"]]></MsgSignature>\n" +
" <TimeStamp>"+CreateTime+"</TimeStamp>\n" +
" <Nonce><![CDATA["+sReqNonce+"]]></Nonce>\n" +
"</xml>";
requestVal="msg_signature:"+sReqMsgSig+"; timestamp:"+sReqTimeStamp+";nonce "+sReqNonce+"; 加密的xml"+strXml+"解密的消息:"+sMsg;
InterfaceLog interfaceLog = new InterfaceLog("5",requestVal,returnValueNormal,results,isSuccess,beginCreateDate,new Date());
interfaceLogService.save(interfaceLog);
UtilHelp.PrintWriter(returnXml, "Xml", request, response);
}
@Test
public void test(){
String strXml="<xml><ToUserName><![CDATA[ww427c0be81be8555f]]></ToUserName><Encrypt><![CDATA[gICWNYyM3DUknCuhhNy9HVjvheQ+qcJsBl+k0Qzym8xruXYxWom7Dg4GnFAOdiTejmseEwMlXX5M9Nh/Cg3MhzC7T/KCN7hhT65igaHhxJQgmavkaC7RbrzBIH04EN2dYd+IbB5VoM7IRTeYbkO1nmpYIMIVQehCfSbqsxqikjHybvO8hhUfyLxLCWq5VtON2XMHNDn5fndizdKPCzBIEvEhjsiD8yRVIufldgc6vYz8CkfUQdeo9bSwm2VYa7hk6EO8/OEgVvHOA1w+7WrKQhnw32fAwQKhQTjQzNhS+gXhbCgmIbZMt2f5rck3Zl/8POwvdDMiZR3hnCO0IO3uOvbKpZOkeTSHVvB+uxOsSZuCQkkyYKGLetGKECEdp6J8MtAdALZQVZjyyeI0sjH1PdjEbv7AaMOrtaeJMykOsA8=]]></Encrypt><AgentID><![CDATA[]]></AgentID></xml>";
System.out.println(strXml);
Document Doc = null;
if(StringUtils.isNotBlank(strXml)){
strXml=strXml.replaceAll("<!\\[CDATA\\[","").replaceAll("]]>","");
try {
Doc = DocumentHelper.parseText(UtilHelp.formatXml(strXml)); // 将字符串转为XML
} catch (DocumentException e) {
e.printStackTrace();
}
}
Element root = Doc.getRootElement(); // 获取根节点
List<Element> contents = root.content();
for(int i=0;i<contents.size();i++){
Element element = contents.get(i);
String text = element.getText();
System.out.println(element.getName()+":");
System.out.println(text);
}
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("~~~微信消息推送及验证~~~");
}
public static byte[] readAsBytes(HttpServletRequest request) {
int len = request.getContentLength();
byte[] buffer = new byte[len];
ServletInputStream in = null;
try
{
in = request.getInputStream();
in.read(buffer, 0, len);
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (null != in)
{
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return buffer;
}
}
|
开发测试 最新文章 |
pytest系列——allure之生成测试报告(Wind |
某大厂软件测试岗一面笔试题+二面问答题面试 |
iperf 学习笔记 |
关于Python中使用selenium八大定位方法 |
【软件测试】为什么提升不了?8年测试总结再 |
软件测试复习 |
PHP笔记-Smarty模板引擎的使用 |
C++Test使用入门 |
【Java】单元测试 |
Net core 3.x 获取客户端地址 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/18 5:51:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |