微信开发环境搭建

本文采用开发语言为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

原文地址:https://www.cnblogs.com/fengcxx/p/5356884.html