Java docking WeChat official account (2) Obtain follow-up and unofficial events/user reply messages

1. Background configuration of official account: click on basic configuration-modify configuration

URL: Fill in the interface address established by the server (the interface must be able to accept get/post requests)

token: write whatever you want

Secret key: automatically generated

 

After configuration, click submit, WeChat will send a get request data to the interface, after the server checks, return the echoStr field in the data sent by WeChat, and WeChat will prompt that the modification is successful.

2. Configure the server interface



    /**
     * 接受微信发送的消息
     *  @param request 公参
     *  @return 返回结果
     */
    @SneakyThrows
    @RequestMapping(value = "/getTencentMsg", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiIgnore
    public void getTencentMsg(HttpServletRequest request, HttpServletResponse response) {
        String method = request.getMethod();
        if(RequestMethodEnum.GET.getDesc().equals(method)){
            String signature = request.getParameter("signature");
            String timestamp = request.getParameter("timestamp");
            String nonce = request.getParameter("nonce");
            String echoStr = request.getParameter("echostr");
            String token = "weiyouzz";
            boolean checkSignature = wxUtils.checkSignature(signature, timestamp, nonce, token);
            if (checkSignature) {
                response.getWriter().write(echoStr+"");
            }
        }else {
            //post请求跟消息相关,往下翻到第三点
        }
    }



//校验微信请求


    /**
     * 验证微信签名
     */
    public boolean checkSignature(String signature, String timestamp,String nonce, String token) {
        // 1.将token、timestamp、nonce三个参数进行字典序排序
        String[] arr = new String[]{token, timestamp, nonce};
        Arrays.sort(arr);
        // 2. 将三个参数字符串拼接成一个字符串进行sha1加密
        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;
        // 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信
        return tmpStr != null && tmpStr.equals(signature.toUpperCase());
    }

    private static String byteToStr(byte[] byteArray) {
        StringBuilder strDigest = new StringBuilder();
        for (int i = 0; i < byteArray.length; i++) {
            strDigest.append(byteToHexStr(byteArray[i]));
        }
        return strDigest.toString();
    }

    private static String byteToHexStr(byte mByte) {
        char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F'};
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }
//可能用到的包
import java.util.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import lombok.SneakyThrows;
import springfox.documentation.annotations.ApiIgnore;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

RequestMethodEnum enumeration build yourself or copy the following

public enum RequestMethodEnum {

    /** get*/
    GET(1,"GET"),
    /** post*/
    POST(2,"POST");

    private final Integer code;
    private final String desc;

    RequestMethodEnum(Integer id, String name){
        this.code = id;
        this.desc = name;
    }

    public Integer getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }
}

3. Get the message and respond, or use the above interface, but the request method is post

        else {
            // 预先设定返回的 response 类型为 xml
            tencentAdvertisingService.getMessage(request,response);
        }
    @Override
    public void getMessage(HttpServletRequest request, HttpServletResponse response) {
        try {
            response.setHeader("Content-type", "application/xml");
            // 读取参数,解析Xml为map
            Map<String, String> map = wxUtils.transferXmlToMap(wxUtils.readRequest(request));
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(map));
            if(ObjectUtils.isNotEmpty(jsonObject)){
                String msgType = jsonObject.getString("MsgType");
                String toUserName = jsonObject.getString("ToUserName");
                String fromUserName = jsonObject.getString("FromUserName");
                String createTime = jsonObject.getString("CreateTime");
                

                //回复,可以回复表情,蓝色可点击链接文字等
                String content ;
                if (TencentMsgTypeConstant.EVENT.equals(msgType)) {//关注自动回复
                    content = "[Party]终于等到你!欢迎你的关注!\n" +
                            "<a href=\"https://www.baidu.com\">百度</a>\n" +
                            "\n" +
                            "<a href=\"https://www.csdn.net\">CSDN</a>\n" +
                            "\n" +
                            "/:rose点击<a href=\"https://www.csdn.net\">【CSDN】</a>看更多优质博客\n" +
                            "/:gift点击<a href=\"https://www.csdn.net\">【CSDN】</a>看更多优质博客";
                } else {//收到消息自动回复
                    content = "/:sun已经收到您的消息~\n" +
                            ">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +
                            ">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +
                            ">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +
                            ">> <a href=\"https://www.csdn.net\">【CSDN】</a>\n" +
                            ">> <a href=\"https://www.csdn.net\">【CSDN】</a>";
                }
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(getXmlReturnMsg(fromUserName,toUserName,System.currentTimeMillis() / 1000,content));
            }
        }catch (Exception e){log.info(e.getMessage());}
    }






    //工具类
    public Map transferXmlToMap(String strxml) throws IOException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
        if (null == strxml || "".equals(strxml)) {
            return null;
        }
        Map m = new HashMap();
        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = null;
        try {
            doc = builder.build(in);
        } catch (JDOMException e) {
            // 统一转化为 IO 异常输出
            throw new IOException(e.getMessage());
        }
        // 解析 DOM
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if (children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }
            m.put(k, v);
        }
        //关闭流
        in.close();
        return m;
    }

    /**
     * 辅助 transferXmlToMap 方法递归提取子节点数据
     */
    private String getChildrenText(List<Element> children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator<Element> it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List<Element> list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }

    /**
     * 读取 request body 内容作为字符串
     *
     * @param request
     * @return
     * @throws IOException
     */
    public String readRequest(HttpServletRequest request) throws IOException {
        InputStream inputStream;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String str;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((str = in.readLine()) != null) {
            sb.append(str);
        }
        in.close();
        inputStream.close();
        return sb.toString();
    }
    /**
     * 构建普通消息
     * @param toUser 接收方账号(openId)
     * @param fromUser 开发者账号
     * @param createTime 创建时间,整型
     * @param content 内容
     * @return 回复消息
     */
    public String getXmlReturnMsg(String toUser,String fromUser,Long createTime,String content) {
        return "<xml>\n" +
                "  <ToUserName><![CDATA["+toUser+"]]></ToUserName>\n" +
                "  <FromUserName><![CDATA["+fromUser+"]]></FromUserName>\n" +
                "  <CreateTime>"+createTime+"</CreateTime>\n" +
                "  <MsgType><![CDATA[text]]></MsgType>\n" +
                "  <Content><![CDATA["+content+"]]></Content>\n" +
                "</xml>";
    }

Guess you like

Origin blog.csdn.net/qq_37928038/article/details/123416947