微信第三平台全网发布小结

在微信第三方平台方创建成功并最终开发测试完毕,提交全网发布申请时,微信服务器会通过自动化测试的方式,检测服务的基础逻辑是否可用,在确保基础可用的情况下,才会允许公众号第三方平台提交全网发布,全网发布的逻辑比较简单,官网说得也很清楚,如果逻辑没问题的小伙伴还是失败,那就可能是加解密的时候参数写错了,一定要仔细排查。
配置:
接收ticket的地址:http:xxxx.cn /common/ticket
接收消息和事件的地址:http:xxxx.cn /common/mp/{APPID}
这两个地址只要在第三方平台配置时和项目保持统一即可。
以下为具体代码:

@RequestMapping(value = "/common/ticket", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
public @ResponseBody String ticket(HttpServletRequest req, String authorization_code,String entCode,HttpServletResponse resp) {

        logger.info("接收到微信传来的ticket数据流...");

        String msgSignature = req.getParameter("msg_signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
                try {
            BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String encStr = sb.toString();
            if(logger.isDebugEnabled()){
                logger.debug("encStr:  " + encStr);
            }

            if (encStr != null) {
                WXBizMsgCrypt pc = new WXBizMsgCrypt(MpParams.WX_OPEN_TOKEN, MpParams.WX_OPEN_AESKEY, MpParams.WX_OPEN_APPID);  // 构造加解密参数
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                StringReader sr = new StringReader(encStr);
                InputSource is = new InputSource(sr);
                Document document = db.parse(is);
                Element root = document.getDocumentElement();
                NodeList nodelist1 = root.getElementsByTagName("Encrypt");
                String encrypt = nodelist1.item(0).getTextContent();
                if(logger.isDebugEnabled()){
                    logger.debug("encrypt:  " + encrypt);
                }

                String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
                String fromXML = String.format(format, encrypt);
                String resultXml = pc.decryptMsg(msgSignature, timestamp,nonce, fromXML);   //检验消息的真实性,并且获取解密后的明文
                if(StringUtils.isNotEmpty(xmlMap.get("InfoType")) && "component_verify_ticket".equals(xmlMap.get("InfoType"))){
                    String componentVerifyTicket = xmlMap.get("ComponentVerifyTicket");
                    logger.info("微信服务器发送过来的ticket:  " + componentVerifyTicket);
                    }
     } catch (Exception e) {
            String str = "解析微信服务器发送的消息流失败...";
            logger.error(str, e);
        }
   return "success";
}

由于ticket在我们的项目中比较有用,所以会解密,如果只是为了全网发布,方法体中只需要一句话:return “success”;

    /**
     * @Description 消息接口
     * @author mlingwei mlingwei@foxmail.com
     */
    @RequestMapping(value = " /common/mp/{APPID}", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
    public void wxmessage(@PathVariable("APPID")String APPID, HttpServletRequest req, HttpServletResponse resp) {
        String msgSignature = req.getParameter("msg_signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        //开始解密
        BufferedReader br = new BufferedReader(new InputStreamReader(req.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
           sb.append(line);
        }
        br.close();
        String encStr = sb.toString();
        if(logger.isDebugEnabled()){
           logger.debug("encStr:  " + encStr);
        }

        if (encStr != null) {
                WXBizMsgCrypt pc = new WXBizMsgCrypt(MpParams.WX_OPEN_TOKEN, MpParams.WX_OPEN_AESKEY, MpParams.WX_OPEN_APPID);  // 构造加解密参数
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                StringReader sr = new StringReader(encStr);
                InputSource is = new InputSource(sr);
                Document document = db.parse(is);
                Element root = document.getDocumentElement();
                NodeList nodelist1 = root.getElementsByTagName("Encrypt");
                String encrypt = nodelist1.item(0).getTextContent();
                if(logger.isDebugEnabled()){
                    logger.debug("encrypt:  " + encrypt);
        }

  String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
  String fromXML = String.format(format, encrypt);
  String resultXml = pc.decryptMsg(msgSignature, timestamp,nonce, fromXML);   //检验消息的真实性,并且获取解密后的明文
  //判断消息类型
              // 将xml转为map对象
  Map<String, String> map = MessageUtils.xmlToMap(resultXml);

  String toUserName = map.get("ToUserName"); // 开发者微信号
  String fromUserName = map.get("FromUserName"); // 发送方帐号(一个OpenID)
  String createTime = map.get("CreateTime"); // 消息创建时间 (整型)
  String msgType = map.get("MsgType"); // text
  String content = map.get("Content"); // 文本消息内容,文本换行 ‘\n’
  String msgId = map.get("MsgId"); // 消息id,64位整型
  String event = map.get("Event"); // 事件类型,如CLICK
  String eventKey = map.get("EventKey"); // 事件KEY值,与自定义菜单接口中KEY值对应
if(APPID.equals("wx570bc396a51b8ff8")){
    if("text".equals(msgType)){
          if("TESTCOMPONENT_MSG_TYPE_TEXT".equals(content)){  
             String returnContent = content+"_callback";  
             replyTextMessage(request,response,returnContent,toUserName,fromUserName,appid);  
        }else if(StringUtils.startsWithIgnoreCase(content, "QUERY_AUTH_CODE")){  
            output(response, "");  
            //接下来客服API再回复一次消息  
            replyApiTextMessage(request,response,content.split(":")[1],fromUserName,appid);  
        } 
     }
    //如果是事件消息
    if("event").equals(msgType)){
       event = event + "from_callback";
       replyTextMessage(req, resp, event, toUserName, fromUserName, nonce);
    }
}

//回复文本消息
    /** 
     * 回复微信服务器"文本消息" 
     * @param request 
     * @param response 
     * @param content 
     * @param toUserName 
     * @param fromUserName 
     * @throws DocumentException 
     * @throws IOException 
     */  
    public String replyTextMessage(HttpServletRequest request, HttpServletResponse response, String content, String toUserName, String fromUserName, String nonce) throws DocumentException, IOException {  
        Long createTime = Calendar.getInstance().getTimeInMillis() / 1000;  

        StringBuffer sb = new StringBuffer();  
        sb.append("<xml>");  
        sb.append("<ToUserName><![CDATA["+fromUserName+"]]></ToUserName>");  
        sb.append("<FromUserName><![CDATA["+toUserName+"]]></FromUserName>");  
        sb.append("<CreateTime>"+createTime+"</CreateTime>");  
        sb.append("<MsgType><![CDATA[text]]></MsgType>");  
        sb.append("<Content><![CDATA["+content+"]]></Content>");  
        sb.append("</xml>");  
        String replyMsg = sb.toString(); 

        String returnvaleue = "";  
        try {  
            WXBizMsgCrypt pc = new WXBizMsgCrypt(MpParams.WX_OPEN_TOKEN, MpParams.WX_OPEN_AESKEY, MpParams.WX_OPEN_APPID);  
            returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), nonce);  

        } catch (AesException e) {  
            e.printStackTrace();  
        }  
//        response.reset();
        output(response, returnvaleue);  
        return returnvaleue;
    }  

//回复API文本消息
    public void replyApiTextMessage(HttpServletRequest request, HttpServletResponse response, String auth_code, String fromUserName, String appid) throws DocumentException, IOException {  

            JSONObject getTokenPost = new JSONObject();
            getTokenPost.accumulate("component_appid", MpParams.WX_OPEN_APPID);
            getTokenPost.accumulate("authorization_code", auth_code);
            String getToken = "";

            try {
               getToken = HttpClientUtil.post(
                        "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token="
                                + component_access_token, getTokenPost.toString());
            } catch (IOException e) {
                logger.error("调用获取authorizer_access_token和authorizer_refresh_token接口失败",e);
                e.printStackTrace();
            }
            JSONObject getTokenJson = JSONObject.fromObject(getToken);
            JSONObject authorization_info = getTokenJson.getJSONObject("authorization_info");
            //authorizer_access_token
            String authorizer_access_token = authorization_info.getString("authorizer_access_token");
            //调用客服接口
            String msg = auth_code + "_from_api"; 
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("touser", fromUserName);
            jsonObject.put("msgtype", "text");
            JSONObject text = new JSONObject();
            text.put("content", msg);
            jsonObject.put("text", text);
            String getInfo = "";
            try {
                getInfo = HttpClientUtil.post(
                        "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="
                                + authorizer_access_token, jsonObject.toString());
            } catch (IOException e) {
                logger.error("调用获取公众号基本信息接口失败",e);
                e.printStackTrace();
            }
            logger.info("发送客服消息结果为:" + getInfo);
        } catch (Exception e) {  
            e.printStackTrace();  
        }  

    }  


    /** 
     * 工具类:回复微信服务器"文本消息" 
     * @param response 
     * @param returnvaleue 
     */  
    public void output(HttpServletResponse response,String returnvaleue){  
        try {  
            PrintWriter pw = response.getWriter(); 
            pw.write(returnvaleue);  
            pw.flush();  
            pw.close();            
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    } 

其中有些工具类直接参考了网络上的代码,全网发布只要思路清晰,仔细阅读文档很容易成功,代码中若有不合理的地方欢迎探讨。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值