• 微信开发环境搭建


    本文采用开发语言为Java,使用spring mvc框架

    1.申请微信账号

      目前微信账号有服务号、订阅号、企业号三种,根据微信官方的解释这三种的的服务类型有所区别。

        服务号:给企业和组织提供更强大的业务服务与用户管理能力,帮助企业快速实现全新的公众号服务平台。

        订阅号:为媒体和个人提供一种新的信息传播方式,构建与读者之间更好的沟通与管理模式。

        企业号:帮助企业和组织内部建立员工、上下游合作伙伴与企业IT系统间的连接。

           对于个人只允许申请订阅号,不过对于微信的开发人员,微信提供了更方便的测试平台。微信公众平台接口,开发人员通过手机微信扫二维码就可以申请测试账号。

      完成注册之后,会进入测试页面,之后每次通过微信扫码可登录。

     2.配置微信服务器地址

    登录微信公众平台官网后,在测试号管理页面填写服务器地址URL、Token和,其中URL是开发者用来接收微信消息和事件的接口URL。Token可由开发者可以任意填写,用作生成签名。在正式号中还有EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。

    ①、验证服务器地址的有效性,开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:

    参数 描述
    signature

    信加密签名,signature结合了开发者填写的token

    参数和请求中的timestamp参数、nonce参数。

    timestamp 时间戳
    nonce 随机数
    echostr 随机字符串

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

    加密/校验流程如下:

    1. 将token、timestamp、nonce三个参数进行字典序排序

    2. 将三个参数字符串拼接成一个字符串进行sha1加密

    3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
    校验有效性代码如下:

    public static boolean checkSignature(String signature, String timestamp, String nonce,String token) {
            String[] arr = new String[]{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 = byteToStr(digest);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
    
            content = null;
            // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
            return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
        }
    View Code

    完整代码如下:

    @RequestMapping("/weixin")
        public void weixin(HttpServletRequest req, HttpServletResponse resp) {
    
            PrintWriter printWriter = null;
    
            String respMessage = null;
    
            try {
                req.setCharacterEncoding("UTF-8");
                resp.setCharacterEncoding("UTF-8");
                String method = req.getMethod();
    
                // 微信加密签名
                String signature = req.getParameter("signature");
                // 时间戳
                String timestamp = req.getParameter("timestamp");
                // 随机数
                String nonce = req.getParameter("nonce");
                // 随机字符串
                String echostr = req.getParameter("echostr");
    
                if (StringUtils.isNullOrEmpty(signature)
                        || StringUtils.isNullOrEmpty(timestamp)
                        || StringUtils.isNullOrEmpty(nonce)) {
    
                    logger.error("Invalid request.");
                    return;
                }
                // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
                if (SignUtil.checkSignature(signature, timestamp, nonce, "weixin")) {
                    respMessage = echostr;
                }
                if ("POST".equals(method)) {
                    // 调用核心业务类接收消息、处理消息
                    respMessage = weixinMessageDispatcher.processRequest(req);
                }
                printWriter = resp.getWriter();
                if (respMessage != null) {
                    printWriter.write(respMessage);
                }
            } catch (Exception e) {
                logger.error("Failed to process request.", e);
            }
        }
    View Code

    ②、接入微信公众号

      完成以上代码之后,就可以把我们的网站接入微信公众号。因为微信公众号需要访问我们的服务器,所有我们的服务必须在公网上能够访问。

      作为开发人员我们一般使用Ngrok来完成内网穿透,开发测试比较方便,网上教程一大把或者注册个新浪SAE(不过最近云豆消耗好像变多了,java耗云豆较多,php基本不损耗)。启动Ngrok。可以写个批处理方便一键启动。

    call E:软件开发工具Java
    grok
    grok http -subdomain=min 8080

    启动结果:成功之后我们可以通过http://min.ngrok.io访问本地8080端口

    登陆微信公众号测试平台,输入URL和token,单击提交。

    3.接收和回复消息

    ①、接收消息,​当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。消息格式如下

    <xml>
     <ToUserName><![CDATA[toUser]]></ToUserName>
     <FromUserName><![CDATA[fromUser]]></FromUserName> 
     <CreateTime>1348831860</CreateTime>
     <MsgType><![CDATA[text]]></MsgType>
     <Content><![CDATA[test]]></Content>
     <MsgId>1234567890123456</MsgId>
     </xml>
    参数描述
    ToUserName 开发者微信号
    FromUserName 发送方帐号(一个OpenID)
    CreateTime 消息创建时间 (整型)
    MsgType text
    Content 文本消息内容
    MsgId 消息id,64位整型

    ②、回复消息,当服务器接收到一个POST请求,我们可以在响应包(Get)中返回特定XML结构,来对该消息进行响应回复。

    <xml>
    <ToUserName><![CDATA[toUser]]></ToUserName>
    <FromUserName><![CDATA[fromUser]]></FromUserName>
    <CreateTime>12345678</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[你好]]></Content>
    </xml>
    参数是否必须描述
    ToUserName 接收方帐号(收到的OpenID)
    FromUserName 开发者微信号
    CreateTime 消息创建时间 (整型)
    MsgType text
    Content 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)

    实现代码:

    public String processRequest(HttpServletRequest request) {
            String respMessage = null;
            try {
                // 默认返回的文本消息内容
                String respContent = "Help";
                // xml请求解析
                Map<String, String> requestMap = MessageUtil.parseXml(request);
                // 打印报文
                logger.info("requestMessage map is :" + requestMap.toString());
    
                // 发送方帐号(open_id)
                String fromUserName = requestMap.get("FromUserName");
                // 公众帐号
                String toUserName = requestMap.get("ToUserName");
                // 消息类型
                String msgType = requestMap.get("MsgType");
                // 消息内容
                String content = requestMap.get("Content");
    
                // 返回信息
                TextMessage textMessage = new TextMessage();
                textMessage.setToUserName(fromUserName);
                textMessage.setFromUserName(toUserName);
                textMessage.setCreateTime(new Date().getTime());
                textMessage.setMsgType("text");
                textMessage.setFuncFlag(0);
        
                // 文本消息
                if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
                    if ("hi".equals(content)) {
                        respMessage = "helloworld";
                    }
                }
    
                if (StringUtils.isNullOrEmpty(respMessage)) {
                    textMessage.setContent(respContent);
                    respMessage = MessageUtil.textMessageToXml(textMessage);
                }
                textMessage.setContent(respMessage);
                respMessage = MessageUtil.textMessageToXml(textMessage);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            logger.info("respMessage  is" + respMessage);
    
            return respMessage;
        }
    View Code

    BaseMessage.java:

    package com.min.message;
    
    public class BaseMessage {
        // 接收方帐号(收到的OpenID)
        private String ToUserName;
        // 开发者微信号
        private String FromUserName;
        // 消息创建时间 (整型)
        private long CreateTime;
        // 消息类型(text/music/news)
        private String MsgType;
        // 位0x0001被标志时,星标刚收到的消息
        private int FuncFlag;
    
        public String getToUserName() {
            return ToUserName;
        }
    
        public void setToUserName(String toUserName) {
            ToUserName = toUserName;
        }
    
        public String getFromUserName() {
            return FromUserName;
        }
    
        public void setFromUserName(String fromUserName) {
            FromUserName = fromUserName;
        }
    
        public long getCreateTime() {
            return CreateTime;
        }
    
        public void setCreateTime(long createTime) {
            CreateTime = createTime;
        }
    
        public String getMsgType() {
            return MsgType;
        }
    
        public void setMsgType(String msgType) {
            MsgType = msgType;
        }
    
        public int getFuncFlag() {
            return FuncFlag;
        }
    
        public void setFuncFlag(int funcFlag) {
            FuncFlag = funcFlag;
        }
    }
    View Code

    TextMessage.java

    package com.min.message;
    
    public class TextMessage extends BaseMessage {
        private String Content;
    
        public String getContent() {
            return Content;
        }
    
        public void setContent(String content) {
            Content = content;
        }
    }
    View Code

    效果图:

    完工,以上只是最简单的接收文本消息,和回复文本消息。目前微信支持文本消息,图片消息,语音消息,视频消息,小视频消息,地理位置消息,链接消息。

    支持回复文本消息,图片消息,语音消息,视频消息,音乐消息,图文消息。

    以上です。

     源代码下载  密码7774

  • 相关阅读:
    C# 关于X86/X64/AnyCpu 的关系
    MongoDB
    AJAX向服务器发送与请求(四)
    jsplumb事件 easyflow
    Vue接收Asp.Net Core传递的文件并下载,接收application/octetstream类型文件流并下载
    docker安装elasticsearch7.16.3集群
    阿里云镜像站
    虚拟机安装Ubuntu20.04.2 Server TLS
    docker安装elasticsearch7.16.3集群 配置身份认证
    Sqlserver查询阻塞的SQL语句
  • 原文地址:https://www.cnblogs.com/fengcxx/p/5356884.html
Copyright © 2020-2023  润新知