接入微信公众号并接收推送消息(Java)

首先需要确认一点,一旦接入第三方服务器,微信就认为你已经具备了开发能力,像自动回复、关键词回复、自定义菜单这些功能,微信公众平台就不再提供了(需要开发者调用相关接口),停用服务器之后,这些功能也就恢复了,二者是互斥的。

一 填写服务器配置

  依照官方文档步骤一配置时会显示URL验证失败,原因是在设置第三方服务器时微信会发送一个GET请求给第三方服务器,只有收到服务器正确回应后才能设置成功。 规则如下:

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

二 URL接入验证

  由官方文档介绍可知,当我们填入url与token的值,并提交后,微信发送的GET请求携带4个参数,而signature参数结合了timestamp参数、nonce参数来做的加密签名,我们在后台需要对该签名进行校验,看是否合法。通过微信传入的timestamp与nonce做相同算法的加密操作,若结果与微信传入的signature相同,即为合法,则原样返回echostr参数,代表接入成功,否则不做处理,则接入失败。

接入验证代码示例
String sha1 = SHA1Util.getSHA1(TOCKEN, request.getParameter("timestamp"), request.getParameter("nonce"));
if (!request.getParameter("signature").equals(sha1)) {
    log.warn("未知来源请求");
    return;
}
if (request.getParameter("echostr") != null) {
    response.getWriter().write(request.getParameter("echostr"));
    return;
}
SHA1工具类示例
import lombok.extern.slf4j.Slf4j;

import java.security.MessageDigest;
import java.util.Arrays;


public class SHA1Util {

    /**
     * 用SHA1算法生成安全签名
     *
     * @param params 包含用于校验的字符串,包括: token,timestamp,nonce等
     * @return 安全签名
     */
    public static String getSHA1(String... params) {
        try {

            String[] array = params.clone();
            StringBuilder sb = new StringBuilder();
            // 字符串字典排序
            Arrays.sort(array);
            for (String anArray : array) {
                if (anArray != null) {
                    sb.append(anArray);
                }
            }
            String str = sb.toString();
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuilder hexstr = new StringBuilder();
            String shaHex;
            for (byte aDigest : digest) {
                shaHex = Integer.toHexString(aDigest & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            //...
        }
    }
}

三 接收微信推送消息

  在公众号接入第三方服务器后,微信会将消息以XML形式推送的我们的服务器,流程如下图所示:
在这里插入图片描述
官方文档所示,微信会将数据以XML格式放在POST请求体中,我们可以使用SpringMvc解析XML参数或手动使用XML工具类解析数据。由于微信发送的请求类型不是application/xml,暂未找到合适自动解析方式,所以使用手动解析。

XML工具类示例
import java.io.StringReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

public static <T> T convertToObject(String xml, Class<T> clazz) {
T _clazz = null;
   StringReader reader = null;
   try {
       JAXBContext context = JAXBContext.newInstance(clazz);
       Unmarshaller unmarshaller = context.createUnmarshaller();
       reader = new StringReader(xml);
       _clazz = (T) unmarshaller.unmarshal(reader);
   } catch (Exception e) {
       throw new RuntimeException(e);
   }finally{
       if(reader!=null){
           reader.close();
       }
   }
   return _clazz;
}

不同类型的消息返回的数据不一定相同,如需要接收多种消息,建议按消息类型维护不同的实体类接收参数并抽取公共参数(如CreateTime,MsgType等)。

接收实体类示例
import lombok.Data;
import lombok.ToString;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@Data
@XmlRootElement(name = "xml")


public class WechatMessageVo{

    /**
     * 开发者微信号
     */
    @XmlElement(name="ToUserName")
    private String ToUserName;

    /**
     * 发送方帐号(一个OpenID)
     */
    @XmlElement(name="FromUserName")
    private String FromUserName;

    /**
     * 消息创建时间 (整型)
     */
    @XmlElement(name="CreateTime")
    private Long CreateTime;

    /**
     * 消息类型
     */
    @XmlElement(name="MsgType")
    private String MsgType;

    /**
     * 消息内容
     */
    @XmlElement(name="Content")
    private String Content;

    /**
     * 消息id
     */
    @XmlElement(name="MsgId")
    private String MsgId;
}

拿到消息内容后可按不同的业务逻辑具体实现

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值