微信开发 一 接入篇

来源:互联网 发布:明源软件怎么样 编辑:程序博客网 时间:2024/06/17 04:53

本例中有些引用的类与方法不做过多介绍,之后会提供完整源码下载,请自行查看。

本篇根据开发者文档-接入指南编写。请对照查看,一些传入与返回参数就不过多介绍。地址为:https://mp.weixin.qq.com/wiki/17/2d4265491f12608cd170a95559800f2d.html

服务器配置

获取开发者信息

这里写图片描述

在项目中配置信息

这里写图片描述

服务器配置信息

这里写图片描述
Token : 必须与代码中配置相同,如本处都为: wechat。
EncodingAESKey : 必须与代码中配置相同。
注意:微信公众服务地址必须以http://或https://开头,分别支持80端口和443端口。微信公众号接口只支持80接口。而Linux 80端口被系统默认。所以必须将80端口请求重定向到8080。具体配置如下:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

验证服务器地址的有效性

编写服务器主路径

该路径与服务器配置信息中URL中配置路径相同。GET请求携带四个参数:

参数 描述 signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 timestamp 时间戳 nonce 随机数 echostr 随机字符串
@Controller@RequestMapping("/core")public class WeChatCoreController {    private static final Logger logger = Logger.getLogger(WeChatCoreController.class);    @Resource       private WeChatCoreService weChatCoreService;    @RequestMapping("/start")    public void start(HttpServletRequest request, HttpServletResponse response) {        logger.info("===========startWeChat============");        try {            // 将请求、响应的编码均设置为UTF-8(防止中文乱码)            request.setCharacterEncoding("UTF-8");            response.setCharacterEncoding("UTF-8");            PrintWriter out = response.getWriter();            String method = request.getMethod();            if(method.equals("GET")) {                String signature = request.getParameter("signature");           // 微信加密签名                String timestamp = request.getParameter("timestamp");           // 时间戳                String nonce = request.getParameter("nonce");                   // 随机数                String echostr = request.getParameter("echostr");               // 随机字符串                System.out.println("确认配置>>>>>>>>>signature="+signature+"  ,timestamp="+timestamp);                if(signature != null && timestamp != null) {                    // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败                    if (weChatCoreService.checkSignature(signature, timestamp, nonce)) {                        out.print(echostr);                    }                }            } else if(method.equals("POST")) {                System.out.println("=================New Message==================");                String respMessage = weChatCoreService.processRequest(request);                out.print(respMessage);            }            out.close();        } catch (Exception e) {            e.printStackTrace();        }    }}

验证有效性

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。

加密/校验流程如下:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

public boolean checkSignature(String signature, String timestamp, String nonce) {        logger.info("==========checkSignature==========");        String[] arr = new String[] { WeChatCertificate.WECHAT_TOKEN, timestamp, nonce };        // 将token、timestamp、nonce三个参数进行字典序排序        Arrays.sort(arr);        StringBuilder content = new StringBuilder();        for (int i = 0; i < arr.length; i++) {            content.append(arr[i]);        }        MessageDigest md = null;        String tmpStr = null;        try {            md = MessageDigest.getInstance("SHA-1");            // 将三个参数字符串拼接成一个字符串进行sha1加密            byte[] digest = md.digest(content.toString().getBytes());            tmpStr = StringUtil.byteToStr(digest);        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        }        content = null;        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;    }

业务逻辑

此后用户每次向公众号发送消息、或者产生自定义菜单点击事件时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,然后开发者可以依据自身业务逻辑进行响应,例如回复消息等。

用户向公众号发送消息时,公众号方收到的消息发送者是一个OpenID,是使用用户微信号加密后的结果,每个用户对每个公众号有一个唯一的OpenID。

本方法中有些调用类与方法将之后章节中介绍说明

/**     * 处理用户发送的消息     */    public String processRequest(HttpServletRequest request) {        logger.info("==========processRequest==========");        String respMessage = null;        try {            Map< String, String> requestMap = new HashMap< String, String>();            //安全模式,消息包为纯密文,需要开发者加密和解密,安全系数高  注:java.security.InvalidKeyException:illegal Key Size 请参考Remark文件 第二条            WXBizMsgCrypt pc = new WXBizMsgCrypt(WeChatCertificate.WECHAT_TOKEN, WeChatCertificate.WECHAT_ENCODINGAESKEY, WeChatCertificate.WECHAT_APPID);            String encrypt_type =request.getParameter("encrypt_type");              if (encrypt_type == null || encrypt_type.equals("raw")) {       //不用加密                  requestMap = XMLUtil.parseXml(request);                     // xml请求解析            } else {                                                        //需走加解密流程                String msgSignature = request.getParameter("msg_signature");// 微信加密签名                     String timeStamp = request.getParameter("timestamp");       // 时间戳                      String nonce = request.getParameter("nonce");               // 随机数                  String encryptMsg = StringUtil.inputStream2String(request.getInputStream()); //密文                   String data = pc.decryptMsg(msgSignature, timeStamp, nonce, encryptMsg);                 requestMap = XMLUtil.parseXml(data);                        // xml请求解析            }            String msgType = requestMap.get("MsgType");         // 消息类型            String xmlStr = requestMap.get("wechatXML");        // 用户传来的xml            System.out.println("Receive information>>>"+xmlStr);            logger.info("Receive information:>>>"+xmlStr);            switch(msgType) {                case WeChatEntitiesType.REQ_MESSAGE_TYPE_IMAGE      : respMessage = ImageRespMsg.test(xmlStr); break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_VOICE      : respMessage = VoiceRespMsg.test(xmlStr); break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_VIDEO      : respMessage = VideoRespMsg.test(xmlStr); break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_SHORTVIDEO : respMessage = VideoRespMsg.test(xmlStr); break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_LINK       : respMessage = TextRespMsg.test(xmlStr);  break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_LOCATION   : respMessage = TextRespMsg.test(xmlStr);  break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_TEXT : {                    String content = requestMap.get("Content");                    switch(content) {                        case "news" :                             respMessage = NewsRespMsg.test(xmlStr);                            break;                        case "music" :                             respMessage = MusicRespMsg.test(xmlStr);                            break;                        default : respMessage = TextRespMsg.test(xmlStr);                    }                }   break;                case WeChatEntitiesType.REQ_MESSAGE_TYPE_EVENT      : {                    String event = requestMap.get("Event");                    String wechatXML = requestMap.get("wechatXML");                    switch(event) {                        case WeChatEntitiesType.EVENT_TYPE_CLICK :                             MenuClickEvent.requestMessage(wechatXML);                            break;                        case WeChatEntitiesType.EVENT_TYPE_VIEW :                             MenuViewEvent.requestMessage(wechatXML);                    }                    respMessage = TextRespMsg.test(xmlStr);                 }   break;                default :  respMessage = TextRespMsg.test(xmlStr);            }            //对返回消息进行加密。注:微信测试号不支持加密模式。测试需注释加解密过程//          respMessage = pc.encryptMsg(respMessage, System.currentTimeMillis()+"", "xxxxxx");            System.out.println("returned messages>>>"+respMessage);            logger.info("returned messages:>>>"+respMessage);        } catch(Exception e) {            e.printStackTrace();        }        return respMessage;    }
0 0
原创粉丝点击