1. 内网映射
由于微信企业号回调模式的URL尽支持域名方式访问,估需要注册花生壳,做一个内网穿透(需要花16块钱,购买一个免费版,购买之后,第二天才能添加上域名)
2. 微信企业号
注册微信企业号:https://qy.weixin.qq.com/ (选择团队,团队不需要认证)
通讯录:新建组织 - > 关注成员
企业号 -> 应用中心 -> 新建应用 -> 消息型应用 -> 模式选择(回调模式) -> 开启微信消息转发,
回调模式说明:http://qydev.weixin.qq.com/wiki/index.php?title=%E5%9B%9E%E8%B0%83%E6%A8%A1%E5%BC%8F
回调模式加密解密代码:http://qydev.weixin.qq.com/wiki/index.php?title=%E5%8A%A0%E8%A7%A3%E5%AF%86%E5%BA%93%E4%B8%8B%E8%BD%BD%E4%B8%8E%E8%BF%94%E5%9B%9E%E7%A0%81
如图1:
自定义菜单: 开发应用的请求路径如图2:
设置 -> 功能设置 -> 权限管理 -> 新建管理组 -> 应用权限( Secret )
3. 利用Jersey开发web Service服务
3.1 在类中定义token, 随机密码43位,公司corpId, secret
3.2 验证方法
/*
* ------------使用示例一:验证回调URL---------------企业开启回调模式时,企业号会向验证url发送一个get请求
* 假设点击验证时,企业收到类似请求: GET
* /cgi-bin/wxpush?msg_signature=5c45ff5e21c57e6ad56bac8758b79b1d9ac89fd3
* ×tamp
* =1409659589&nonce=263014780&echostr=P9nAzCzyDtyTWESHep1vC5X9xho%
* 2FqYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp%2B4RPcs8TgAE7OaBO%2BFZXvnaqQ%3D%3D
* HTTP/1.1 Host: qy.weixin.qq.com
*
* 接收到该请求时,企业应
* 1.解析出Get请求的参数,包括消息体签名(msg_signature),时间戳(timestamp),随机数字串(nonce
* )以及公众平台推送过来的随机加密字符串(echostr), 这一步注意作URL解码。 2.验证消息体签名的正确性 3.
* 解密出echostr原文,将原文当作Get请求的response,返回给公众平台 第2,3步可以用公众平台提供的库函数VerifyURL来实现。
*/
/**
* 回调URL,微信调用此方法进行验证
*
* @return
*/
@GET
@Path("station")
public String verify() {
String msgSignature = request.getParameter("msg_signature");
String timeStamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
System.out.println(timeStamp + " " + nonce);
String echostr = request.getParameter("echostr");
String sEchoStr = null;
try {
sEchoStr = wxcpt.VerifyURL(msgSignature, timeStamp, nonce, echostr);
} catch (Exception e) {
e.printStackTrace();// 验证URL失败,错误原因请查看异常
}
return sEchoStr;
}
3.3 接收用户信息,并解密
/*
* ------------对用户回复的消息解密---------------
* 用户回复消息或者点击事件响应时,企业会收到回调消息,此消息是经过公众平台加密之后的密文以post形式发送给企业,密文格式请参考官方文档
* 假设企业收到公众平台的回调消息如下: POST /cgi-bin/wxpush?
* msg_signature=477715d11cdb4164915debcba66cb864d751f3e6
* ×tamp=1409659813&nonce=1372623149 HTTP/1.1 Host: qy.weixin.qq.com
* Content-Length: 613 <xml>
* <ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName
* ><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo
* +rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/
* sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT
* +6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6
* +kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r
* +KqCKIw
* +3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0
* +rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS
* +/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl
* /T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt>
* <AgentID><![CDATA[218]]></AgentID> </xml>
*
* 企业收到post请求之后应该
* 1.解析出url上的参数,包括消息体签名(msg_signature),时间戳(timestamp)以及随机数字串(nonce)
* 2.验证消息体签名的正确性。
* 3.将post请求的数据进行xml解析,并将<Encrypt>标签的内容进行解密,解密出来的明文即是用户回复消息的明文,明文格式请参考官方文档
* 第2,3步可以用公众平台提供的库函数DecryptMsg来实现。
*/
@POST
@Path("station")
public String receiveMsg(String reqData) {
String msgSignature = request.getParameter("msg_signature");
String timeStamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
// post请求的密文数据
// String sReqData =
// "<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt><AgentID><![CDATA[218]]></AgentID></xml>";
try {
String sMsg = wxcpt.DecryptMsg(msgSignature, timeStamp, nonce,
reqData);
// 解析出明文xml标签的内容进行处理
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(sMsg);
InputSource is = new InputSource(sr);
Document document = db.parse(is);
Element root = document.getDocumentElement();
NodeList nodelist1 = root.getElementsByTagName("Content");
if (nodelist1.item(0) == null)
return "ok";
String Content = nodelist1.item(0).getTextContent();
System.out.println("Co