微信公众账号第三方平台全网发布源码(java)- 实战测试通过

[java]  view plain copy
  1. package org.jeecgframework.web.rest.controller;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.PrintWriter;  
  6. import java.security.MessageDigest;  
  7. import java.security.NoSuchAlgorithmException;  
  8. import java.util.Arrays;  
  9. import java.util.Calendar;  
  10. import java.util.Date;  
  11. import java.util.HashMap;  
  12. import java.util.List;  
  13. import java.util.Map;  
  14.   
  15. import javax.servlet.http.HttpServletRequest;  
  16. import javax.servlet.http.HttpServletResponse;  
  17.   
  18. import org.apache.commons.lang.StringUtils;  
  19. import org.dom4j.Document;  
  20. import org.dom4j.DocumentException;  
  21. import org.dom4j.DocumentHelper;  
  22. import org.dom4j.Element;  
  23. import org.jeecgframework.core.util.LogUtil;  
  24. import org.jeecgframework.core.util.ResourceUtil;  
  25. import org.jeecgframework.core.util.oConvertUtils;  
  26. import org.jeecgframework.web.system.service.SystemService;  
  27. import org.jeewx.api.core.exception.WexinReqException;  
  28. import org.jeewx.api.mp.aes.AesException;  
  29. import org.jeewx.api.mp.aes.WXBizMsgCrypt;  
  30. import org.jeewx.api.third.JwThirdAPI;  
  31. import org.jeewx.api.third.model.ApiComponentToken;  
  32. import org.springframework.beans.factory.annotation.Autowired;  
  33. import org.springframework.stereotype.Controller;  
  34. import org.springframework.web.bind.annotation.RequestMapping;  
  35.   
  36. import weixin.open.entity.base.WeixinOpenAccountEntity;  
  37.   
  38. /** 
  39.  * 微信公众账号第三方平台全网发布源码(java) 
  40.  * @author: jeewx开源社区 
  41.  * @网址:www.jeewx.com 
  42.  * @论坛:www.jeecg.org 
  43.  * @date 20150801 
  44.  */  
  45. @Controller  
  46. @RequestMapping("/openwx")  
  47. public class OpenwxController {  
  48.   
  49.       
  50.       
  51.     private final String APPID = "???";  
  52.       
  53.       
  54.     /** 
  55.      * 微信全网测试账号 
  56.      */  
  57.     private final static String COMPONENT_APPID = "???";  
  58.     private final String COMPONENT_APPSECRET = "???";  
  59.     private final static String COMPONENT_ENCODINGAESKEY = "?????";  
  60.     private final static String COMPONENT_TOKEN = "?????";  
  61.     @Autowired  
  62.     private SystemService systemService;  
  63.       
  64.       
  65.      /** 
  66.      * 授权事件接收 
  67.      *  
  68.      * @param request 
  69.      * @param response 
  70.      * @throws IOException 
  71.      * @throws AesException 
  72.      * @throws DocumentException 
  73.      */  
  74.     @RequestMapping(value = "/event/authorize")  
  75.     public void acceptAuthorizeEvent(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException, DocumentException {  
  76. //       LogUtil.info("微信第三方平台---------微信推送Ticket消息10分钟一次-----------"+ DataUtils.getDataString(DataUtils.yyyymmddhhmmss));  
  77.          processAuthorizeEvent(request);  
  78.          output(response, "success"); // 输出响应的内容。  
  79.     }  
  80.       
  81.     @RequestMapping(value = "/authorCallback")  
  82.     public void authorCallback(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException, DocumentException {  
  83.         String auth_code = request.getParameter("auth_code");  
  84.         String expires_in = request.getParameter("auth_code");  
  85.           
  86.     }  
  87.       
  88.       
  89.     /** 
  90.      * 一键授权功能 
  91.      * @param request 
  92.      * @param response 
  93.      * @throws IOException 
  94.      * @throws AesException 
  95.      * @throws DocumentException 
  96.      */  
  97.     @RequestMapping(value = "/goAuthor")  
  98.     public void goAuthor(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException, DocumentException {  
  99.         ApiComponentToken apiComponentToken = new ApiComponentToken();  
  100.         apiComponentToken.setComponent_appid(COMPONENT_APPID);  
  101.         apiComponentToken.setComponent_appsecret(COMPONENT_APPSECRET);  
  102.         WeixinOpenAccountEntity  entity = getWeixinOpenAccount(APPID);  
  103.         apiComponentToken.setComponent_verify_ticket(entity.getTicket());  
  104.         try {  
  105.             String component_access_token = JwThirdAPI.getAccessToken(apiComponentToken);  
  106.             //预授权码  
  107.             String preAuthCode = JwThirdAPI.getPreAuthCode(COMPONENT_APPID, component_access_token);  
  108.             String url = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid="+COMPONENT_APPID+"&pre_auth_code="+preAuthCode+"&redirect_uri="+ResourceUtil.getConfigByName("domain")+"/rest/openwx/authorCallback";  
  109.             response.sendRedirect(url);  
  110.         } catch (WexinReqException e) {  
  111.             e.printStackTrace();  
  112.         }  
  113.           
  114.     }  
  115.       
  116.       
  117.       
  118.     @RequestMapping(value = "{appid}/callback")  
  119.     public void acceptMessageAndEvent(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException, DocumentException {  
  120.         String msgSignature = request.getParameter("msg_signature");  
  121.         //LogUtil.info("第三方平台全网发布-------------{appid}/callback-----------验证开始。。。。msg_signature="+msgSignature);  
  122.         if (!StringUtils.isNotBlank(msgSignature))  
  123.             return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息  
  124.    
  125.         StringBuilder sb = new StringBuilder();  
  126.         BufferedReader in = request.getReader();  
  127.         String line;  
  128.         while ((line = in.readLine()) != null) {  
  129.             sb.append(line);  
  130.         }  
  131.         in.close();  
  132.    
  133.         String xml = sb.toString();  
  134.         Document doc = DocumentHelper.parseText(xml);  
  135.         Element rootElt = doc.getRootElement();  
  136.         String toUserName = rootElt.elementText("ToUserName");  
  137.    
  138.         //微信全网测试账号  
  139. //        if (StringUtils.equalsIgnoreCase(toUserName, APPID)) {  
  140. //           LogUtil.info("全网发布接入检测消息反馈开始---------------APPID="+ APPID +"------------------------toUserName="+toUserName);  
  141.            checkWeixinAllNetworkCheck(request,response,xml);  
  142. //        }  
  143.     }  
  144.       
  145.     /** 
  146.      * 处理授权事件的推送 
  147.      *  
  148.      * @param request 
  149.      * @throws IOException 
  150.      * @throws AesException 
  151.      * @throws DocumentException 
  152.      */  
  153.     public void processAuthorizeEvent(HttpServletRequest request) throws IOException, DocumentException, AesException {  
  154.         String nonce = request.getParameter("nonce");  
  155.         String timestamp = request.getParameter("timestamp");  
  156.         String signature = request.getParameter("signature");  
  157.         String msgSignature = request.getParameter("msg_signature");  
  158.    
  159.         if (!StringUtils.isNotBlank(msgSignature))  
  160.             return;// 微信推送给第三方开放平台的消息一定是加过密的,无消息加密无法解密消息  
  161.         boolean isValid = checkSignature(COMPONENT_TOKEN, signature, timestamp, nonce);  
  162.         if (isValid) {  
  163.             StringBuilder sb = new StringBuilder();  
  164.             BufferedReader in = request.getReader();  
  165.             String line;  
  166.             while ((line = in.readLine()) != null) {  
  167.                 sb.append(line);  
  168.             }  
  169.             String xml = sb.toString();  
  170. //            LogUtil.info("第三方平台全网发布-----------------------原始 Xml="+xml);  
  171.             String encodingAesKey = COMPONENT_ENCODINGAESKEY;// 第三方平台组件加密密钥  
  172.             String appId = getAuthorizerAppidFromXml(xml);// 此时加密的xml数据中ToUserName是非加密的,解析xml获取即可  
  173.             //LogUtil.info("第三方平台全网发布-------------appid----------getAuthorizerAppidFromXml(xml)-----------appId="+appId);  
  174.             WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, encodingAesKey, COMPONENT_APPID);  
  175.             xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml);  
  176. //            LogUtil.info("第三方平台全网发布-----------------------解密后 Xml="+xml);  
  177.             processAuthorizationEvent(xml);  
  178.         }  
  179.     }  
  180.       
  181.     /** 
  182.      * 保存Ticket 
  183.      * @param xml 
  184.      */  
  185.     void processAuthorizationEvent(String xml){  
  186.         Document doc;  
  187.         try {  
  188.             doc = DocumentHelper.parseText(xml);  
  189.             Element rootElt = doc.getRootElement();  
  190.             String ticket = rootElt.elementText("ComponentVerifyTicket");  
  191.             if(oConvertUtils.isNotEmpty(ticket)){  
  192.                 LogUtil.info("8、推送component_verify_ticket协议-----------ticket = "+ticket);  
  193.                 WeixinOpenAccountEntity  entity = getWeixinOpenAccount(APPID);  
  194.                 entity = entity==null?new WeixinOpenAccountEntity():entity;  
  195.                 entity.setTicket(ticket);  
  196.                 entity.setAppid(APPID);  
  197.                 entity.setGetTicketTime(new Date());  
  198.                 systemService.saveOrUpdate(entity);  
  199.             }  
  200.         } catch (DocumentException e) {  
  201.             e.printStackTrace();  
  202.         }  
  203.     }  
  204.       
  205.     /** 
  206.      * 获取授权账号信息 
  207.      * @param appid 
  208.      * @return 
  209.      */  
  210.     WeixinOpenAccountEntity getWeixinOpenAccount(String appid){  
  211.         WeixinOpenAccountEntity  entity = null;  
  212.         List<WeixinOpenAccountEntity> ls = systemService.findByProperty(WeixinOpenAccountEntity.class"appid", appid);  
  213.         if(ls!=null && ls.size()!=0){  
  214.              entity = ls.get(0);  
  215.         }  
  216.         return entity;  
  217.     }  
  218.       
  219.     /** 
  220.      * 获取授权的Appid 
  221.      * @param xml 
  222.      * @return 
  223.      */  
  224.     String getAuthorizerAppidFromXml(String xml) {  
  225.         Document doc;  
  226.         try {  
  227.             doc = DocumentHelper.parseText(xml);  
  228.             Element rootElt = doc.getRootElement();  
  229.             String toUserName = rootElt.elementText("ToUserName");  
  230.             return toUserName;  
  231.         } catch (DocumentException e) {  
  232.             // TODO Auto-generated catch block  
  233.             e.printStackTrace();  
  234.         }  
  235.         return null;  
  236.     }  
  237.      
  238.       
  239.     public void checkWeixinAllNetworkCheck(HttpServletRequest request, HttpServletResponse response,String xml) throws DocumentException, IOException, AesException{  
  240.         String nonce = request.getParameter("nonce");  
  241.         String timestamp = request.getParameter("timestamp");  
  242.         String msgSignature = request.getParameter("msg_signature");  
  243.    
  244.         WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, COMPONENT_ENCODINGAESKEY, COMPONENT_APPID);  
  245.         xml = pc.decryptMsg(msgSignature, timestamp, nonce, xml);  
  246.    
  247.         Document doc = DocumentHelper.parseText(xml);  
  248.         Element rootElt = doc.getRootElement();  
  249.         String msgType = rootElt.elementText("MsgType");  
  250.         String toUserName = rootElt.elementText("ToUserName");  
  251.         String fromUserName = rootElt.elementText("FromUserName");  
  252.    
  253. //        LogUtil.info("---全网发布接入检测--step.1-----------msgType="+msgType+"-----------------toUserName="+toUserName+"-----------------fromUserName="+fromUserName);  
  254. //        LogUtil.info("---全网发布接入检测--step.2-----------xml="+xml);  
  255.         if("event".equals(msgType)){  
  256. //           LogUtil.info("---全网发布接入检测--step.3-----------事件消息--------");  
  257.              String event = rootElt.elementText("Event");  
  258.              replyEventMessage(request,response,event,toUserName,fromUserName);  
  259.         }else if("text".equals(msgType)){  
  260. //           LogUtil.info("---全网发布接入检测--step.3-----------文本消息--------");  
  261.              String content = rootElt.elementText("Content");  
  262.              processTextMessage(request,response,content,toUserName,fromUserName);  
  263.         }  
  264.     }  
  265.       
  266.       
  267.     public void replyEventMessage(HttpServletRequest request, HttpServletResponse response, String event, String toUserName, String fromUserName) throws DocumentException, IOException {  
  268.         String content = event + "from_callback";  
  269. //        LogUtil.info("---全网发布接入检测------step.4-------事件回复消息  content="+content + "   toUserName="+toUserName+"   fromUserName="+fromUserName);  
  270.         replyTextMessage(request,response,content,toUserName,fromUserName);  
  271.     }  
  272.    
  273.     public void processTextMessage(HttpServletRequest request, HttpServletResponse response,String content,String toUserName, String fromUserName) throws IOException, DocumentException{  
  274.         if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){  
  275.             String returnContent = content+"_callback";  
  276.             replyTextMessage(request,response,returnContent,toUserName,fromUserName);  
  277.         }else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){  
  278.             output(response, "");  
  279.             //接下来客服API再回复一次消息  
  280.             replyApiTextMessage(request,response,content.split(":")[1],fromUserName);  
  281.         }  
  282.     }  
  283.    
  284.     public void replyApiTextMessage(HttpServletRequest request, HttpServletResponse response, String auth_code, String fromUserName) throws DocumentException, IOException {  
  285.         String authorization_code = auth_code;  
  286.         // 得到微信授权成功的消息后,应该立刻进行处理!!相关信息只会在首次授权的时候推送过来  
  287.         System.out.println("------step.1----使用客服消息接口回复粉丝----逻辑开始-------------------------");  
  288.         try {  
  289.             ApiComponentToken apiComponentToken = new ApiComponentToken();  
  290.             apiComponentToken.setComponent_appid(COMPONENT_APPID);  
  291.             apiComponentToken.setComponent_appsecret(COMPONENT_APPSECRET);  
  292.             WeixinOpenAccountEntity  entity = getWeixinOpenAccount(APPID);  
  293.             apiComponentToken.setComponent_verify_ticket(entity.getTicket());  
  294.             String component_access_token = JwThirdAPI.getAccessToken(apiComponentToken);  
  295.               
  296.             System.out.println("------step.2----使用客服消息接口回复粉丝------- component_access_token = "+component_access_token + "---------authorization_code = "+authorization_code);  
  297.             net.sf.json.JSONObject authorizationInfoJson = JwThirdAPI.getApiQueryAuthInfo(COMPONENT_APPID, authorization_code, component_access_token);  
  298.             System.out.println("------step.3----使用客服消息接口回复粉丝-------------- 获取authorizationInfoJson = "+authorizationInfoJson);  
  299.             net.sf.json.JSONObject infoJson = authorizationInfoJson.getJSONObject("authorization_info");  
  300.             String authorizer_access_token = infoJson.getString("authorizer_access_token");  
  301.               
  302.               
  303.             Map<String,Object> obj = new HashMap<String,Object>();  
  304.             Map<String,Object> msgMap = new HashMap<String,Object>();  
  305.             String msg = auth_code + "_from_api";  
  306.             msgMap.put("content", msg);  
  307.               
  308.             obj.put("touser", fromUserName);  
  309.             obj.put("msgtype""text");  
  310.             obj.put("text", msgMap);  
  311.             JwThirdAPI.sendMessage(obj, authorizer_access_token);  
  312.         } catch (WexinReqException e) {  
  313.             e.printStackTrace();  
  314.         }  
  315.           
  316.     }     
  317.       
  318.     /** 
  319.      * 验证是否过期 
  320.      * @param accessTokenExpires 
  321.      * @return 
  322.      */  
  323.     boolean isExpired(long accessTokenExpires){  
  324.         return false;  
  325.     }  
  326.       
  327.     /** 
  328.      * 回复微信服务器"文本消息" 
  329.      * @param request 
  330.      * @param response 
  331.      * @param content 
  332.      * @param toUserName 
  333.      * @param fromUserName 
  334.      * @throws DocumentException 
  335.      * @throws IOException 
  336.      */  
  337.     public void replyTextMessage(HttpServletRequest request, HttpServletResponse response, String content, String toUserName, String fromUserName) throws DocumentException, IOException {  
  338.         Long createTime = Calendar.getInstance().getTimeInMillis() / 1000;  
  339.         StringBuffer sb = new StringBuffer();  
  340.         sb.append("<xml>");  
  341.         sb.append("<ToUserName><![CDATA["+fromUserName+"]]></ToUserName>");  
  342.         sb.append("<FromUserName><![CDATA["+toUserName+"]]></FromUserName>");  
  343.         sb.append("<CreateTime>"+createTime+"</CreateTime>");  
  344.         sb.append("<MsgType><![CDATA[text]]></MsgType>");  
  345.         sb.append("<Content><![CDATA["+content+"]]></Content>");  
  346.         sb.append("</xml>");  
  347.         String replyMsg = sb.toString();  
  348.           
  349.         String returnvaleue = "";  
  350.         try {  
  351.             WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, COMPONENT_ENCODINGAESKEY, COMPONENT_APPID);  
  352.             returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), "easemob");  
  353. //            System.out.println("------------------加密后的返回内容 returnvaleue: "+returnvaleue);  
  354.         } catch (AesException e) {  
  355.             e.printStackTrace();  
  356.         }  
  357.         output(response, returnvaleue);  
  358.     }  
  359.       
  360.       
  361.     public static void main(String[] args) {  
  362.          Long createTime = Calendar.getInstance().getTimeInMillis() / 1000;  
  363.          String replyMsg = "LOCATIONfrom_callback";  
  364.            
  365.          String returnvaleue = "";  
  366.          try {  
  367.              WXBizMsgCrypt pc = new WXBizMsgCrypt(COMPONENT_TOKEN, COMPONENT_ENCODINGAESKEY, COMPONENT_APPID);  
  368.              returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), "easemob");  
  369.              System.out.println(returnvaleue);  
  370.          } catch (AesException e) {  
  371.              e.printStackTrace();  
  372.          }  
  373.     }  
  374.     /** 
  375.      * 工具类:回复微信服务器"文本消息" 
  376.      * @param response 
  377.      * @param returnvaleue 
  378.      */  
  379.     public void output(HttpServletResponse response,String returnvaleue){  
  380.         try {  
  381.             PrintWriter pw = response.getWriter();  
  382.             pw.write(returnvaleue);  
  383. //          System.out.println("****************returnvaleue***************="+returnvaleue);  
  384.             pw.flush();  
  385.         } catch (IOException e) {  
  386.             e.printStackTrace();  
  387.         }  
  388.     }  
  389.       
  390.     /** 
  391.      * 判断是否加密 
  392.      * @param token 
  393.      * @param signature 
  394.      * @param timestamp 
  395.      * @param nonce 
  396.      * @return 
  397.      */  
  398.     public static boolean checkSignature(String token,String signature,String timestamp,String nonce){  
  399.         System.out.println("###token:"+token+";signature:"+signature+";timestamp:"+timestamp+"nonce:"+nonce);  
  400.            boolean flag = false;  
  401.            if(signature!=null && !signature.equals("") && timestamp!=null && !timestamp.equals("") && nonce!=null && !nonce.equals("")){  
  402.               String sha1 = "";  
  403.               String[] ss = new String[] { token, timestamp, nonce };   
  404.               Arrays.sort(ss);    
  405.               for (String s : ss) {    
  406.                sha1 += s;    
  407.               }    
  408.        
  409.               sha1 = AddSHA1.SHA1(sha1);    
  410.        
  411.               if (sha1.equals(signature)){  
  412.                flag = true;  
  413.               }  
  414.            }  
  415.            return flag;  
  416.        }  
  417. }  
  418.   
  419.   
  420. class AddSHA1 {  
  421.     public static String SHA1(String inStr) {  
  422.         MessageDigest md = null;  
  423.         String outStr = null;  
  424.         try {  
  425.             md = MessageDigest.getInstance("SHA-1");     //选择SHA-1,也可以选择MD5  
  426.             byte[] digest = md.digest(inStr.getBytes());       //返回的是byet[],要转化为String存储比较方便  
  427.             outStr = bytetoString(digest);  
  428.         }  
  429.         catch (NoSuchAlgorithmException nsae) {  
  430.             nsae.printStackTrace();  
  431.         }  
  432.         return outStr;  
  433.     }  
  434.       
  435.       
  436.     public static String bytetoString(byte[] digest) {  
  437.         String str = "";  
  438.         String tempStr = "";  
  439.           
  440.         for (int i = 0; i < digest.length; i++) {  
  441.             tempStr = (Integer.toHexString(digest[i] & 0xff));  
  442.             if (tempStr.length() == 1) {  
  443.                 str = str + "0" + tempStr;  
  444.             }  
  445.             else {  
  446.                 str = str + tempStr;  
  447.             }  
  448.         }  
  449.         return str.toLowerCase();  
  450.     }  
  451. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值