微信公众号如何接入Java后台

有一个这样简单的需求,用户发送消息到公众号,经过Java后台的逻辑处理后,返回处理结果给用户。

1. 编写接入代码

编写代码之前我们需要引入两个依赖。

<!--编解码-->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>

<!--解析xml-->
<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.0.0</version>
</dependency>

我们需要向微信后台暴露一个接口,以供微信调用。这里采用get请求方式,请求路径自己定义。
微信会给我们传signature timestamp nonce echostr 四个参数,我们需要做的是用前三个参数做校验,校验成功之后原封不动的返回echostr
这里需要自定义设置一个TOKEN的值,后续配置用得到。

@RestController
public class WxController {

	public static final String TOKEN = "123456";

    @GetMapping("/wx/echo")
    public String echo(HttpServletRequest req, HttpServletResponse resp) {
        // 1.获取微信传入的4个参数
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");
        // 2.用timestamp, nonce, signature进行校验
        boolean result = check(timestamp, nonce, signature);
        if (result) {
            // 3.校验成功返回echostr
            return echostr;
        }
        return "error!";
    }

	public static boolean check(String timestamp, String nonce, String signature) {
	    // 1.按字典序对TOKEN, timestamp和nonce排序
	    String[] arr = new String[]{TOKEN,timestamp,nonce};
	    Arrays.sort(arr);
	    // 2.将3个参数拼成一个字符串进行sha1加密
	    String str = arr[0]+arr[1]+arr[2];
	    // 3.用commons-codec包中的工具类进行sha1加密
	    str = DigestUtils.sha1Hex(str);
	    // 4.将加密后的字符串和signature比较
	    System.out.println(signature);
	    return str.equalsIgnoreCase(signature);
	}
}

2.公众号配置

登陆公众号后台,选择基本配置。URL填入你的接口地址,Token与步骤1中定义的TOKEN保持一致。简单起见,EncodingAESKey随机生成,消息加密方式选择明文模式。
在这里插入图片描述
点击提交,提示提交成功。
在这里插入图片描述

由于URL使用的是80端口,而后台服务不一定是80端口,所以这里需要用nginx做一些反向代理。

location ~ / {
  proxy_pass http://127.0.0.1:8080;
}

3.接收用户消息

上述操作已经成功连接微信与Java后台,接下来接受用户发送的消息。
当普通微信用户向公众账号发消息时,微信服务器将 POST 消息的 XML 数据包到开发者填写的 URL 上。数据包格式如下。

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>1348831860</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[this is a test]]></Content>
  <MsgId>1234567890123456</MsgId>
  <MsgDataId>xxxx</MsgDataId>
  <Idx>xxxx</Idx>
</xml>

我们写一个post接口,用来解析消息、逻辑处理以及回复消息。路径与步骤二中的URL一致。

@PostMapping("/wx/echo")
public String echoPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // 1.解析消息
    Map<String, String> param = parseRequest(req.getInputStream());
    // 2.逻辑处理(可以根据自身逻辑进行处理,这里略)
    // ...........
    
    // 3.回复消息
    String textMsg = "<xml>" +
                        "<ToUserName><![CDATA["+ param.get("FromUserName")+"]]></ToUserName>" +
                        "<FromUserName><![CDATA["+ param.get("ToUserName")+"]]></FromUserName>" +
                        "<CreateTime>12345678</CreateTime>" +
                        "<MsgType><![CDATA[text]]></MsgType>" +
                        "<Content><![CDATA[你好]]></Content>" +
                    "</xml>";
    return textMsg;
}

// 利用dom4j中的类进行解析
public static Map<String, String> parseRequest(InputStream is) {
    Map<String,String> map = new HashMap();
    // 1. 通过io流得到文档对象
    SAXReader saxReader = new SAXReader();
    Document document = null;
    try {
        document = saxReader.read(is);
    } catch (DocumentException e) {
        e.printStackTrace();
    }
    // 2.通过文档对象得到根节点对象
    Element root = document.getRootElement();
    // 3.通过根节点对象获取所有子节点对象
    List<Element> elements = root.elements();
    // 4.将所有节点放入map
    for (Element element : elements) {
        map.put(element.getName(), element.getStringValue());
    }
    return map;
}

上述代码,无论我们发送什么消息给公众号,公众号都将回复你好
由于微信会进行超时重试,因此需要进行排重。建议使用redis进行排重,这里不做演示。

功能测试

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值