JAVA对接公众号(二、处理微信服务器发来的消息)

一、验证公众号配置的服务器信息.

须知:处理微信服务器发来的消息之前必须先通过公众号配置的服务器验证

获取AccessToken,里面的HttpClientUtil类可以从我csdn资源中找

/**
     * 获取AccessToken
     *
     * @return
     */
    public String getAccessToken() {
        log.info("\n获取accessToken~");
        String appid = null;
        String secret = null;
        appid = wxmpProperties.getAppId();
        secret = wxmpProperties.getAppSecret();
        //查询token是否存在
        String key = "tjcloud" + appid + "_AccessToken";
        String accessToken = (String) redisUtil.get(key);
        // 存在直接返回,不存在重新获取AccessToken
        if (!StringUtils.isBlank(accessToken)) {
            log.info("\n从缓存中取到的AccessToken为:{}", accessToken);
            return accessToken;
        }
        // 获取AccessToken的url
        String grantType = "client_credential";
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grantType + "&appid=" + appid + "&secret=" + secret;
        // 获取到AccessToken
        accessToken = HttpClientUtil.get(url);
        log.info("\n重新获取到的AccessToken为:{}", accessToken);
        Map<String, Object> map = null;
        try {
            map = objectMapper.readValue(accessToken, Map.class);
        } catch (IOException e) {
            log.error("公众号异常通知-获取AccessToken-转化异常", e);
        }
        if (map.get("errcode") != null || map.get("errmsg") != null) {
            String errcode = String.valueOf(map.get("errcode"));
            String errmsg = String.valueOf(map.get("errmsg"));
            if (!errcode.equals("0")) {
                log.error("获取token失败:code=" + errcode + "msg=" + errmsg);
                return "";
            }
        }
        accessToken = String.valueOf(map.get("access_token"));
        // 把AccessToken存入缓存中,并设置过期时间,因为access_token的过期时间是两小时,我们缓存的时间一定要小于两小时,
        redisUtil.set(key, accessToken, 5000);
        return accessToken;
    }

controller控制层

    @Autowired
    private TdCMpLoginService mpLoginService;

	/**
	 * 处理微信服务器发来的消息
	 */
	@PostMapping("/serverCheck")
    public String doPost(HttpServletRequest request, HttpServletResponse response) {
        // 调用核心服务类接收处理请求
        return mpLoginService.processRequest(request);
    }

service业务层

TdCMpLoginService.java

    String processRequest(HttpServletRequest request);

TdCMpLoginServiceImpl.java
从代码中可以看出微信服务器可以通过post方式访问我们的接口,把消息类型和事件传过来,我们可以根据不同的类型和事件来做出相应的操作,我这里只对订阅和取消订阅的操作进行了存储。

/**
     * @Description: 处理微信服务器发来的消息
     * @Param: [request]
     * @return: java.lang.String
     * @Author: XQD
     * @Date:2021/9/17 10:19
     */
    @Transactional
    @Override
    public String processRequest(HttpServletRequest request) {
        // xml格式的消息数据
        String respXml = null;
        // 默认返回的文本消息内容
        String respContent;
        try {
            // 调用parseXml方法解析请求消息
            Map<String, String> requestMap = WeChatUtil.parseXml(request);
            // 消息类型
            String msgType = requestMap.get(WeChatContant.MsgType);
            log.info("\n消息类型:{}", msgType);
            String mes = null;
            // 文本消息
            if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_TEXT)) {
                respContent = "您发送的是文本消息!";
                respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
            }
            // 图片消息
            else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_IMAGE)) {
                respContent = "您发送的是图片消息!";
                respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
            }
            // 语音消息
            else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_VOICE)) {
                respContent = "您发送的是语音消息!";
                respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
            }
            // 视频消息
            else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_VIDEO)) {
                respContent = "您发送的是视频消息!";
                respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
            }
            // 地理位置消息
            else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_LOCATION)) {
                respContent = "您发送的是地理位置消息!";
                respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
            }
            // 链接消息
            else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_LINK)) {
                respContent = "您发送的是链接消息!";
                respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
            }
            // 事件推送
            else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件类型
                String eventType = requestMap.get(WeChatContant.Event);
                log.info("\n事件类型为:{}", eventType);
                // 关注
                if (eventType.equals(WeChatContant.EVENT_TYPE_SUBSCRIBE)) {
                    log.info("\n搜索关注公众号!");
                    subscribeMPUserInfo(null, requestMap.get(WeChatContant.FromUserName));
                    respContent = "谢谢您的关注!";
                    respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                }
                // 取消关注
                else if (eventType.equals(WeChatContant.EVENT_TYPE_UNSUBSCRIBE)) {
                    unsubscribeMPUserInfo(requestMap.get(WeChatContant.FromUserName));
                    // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
                }
                // 扫描带参数二维码
                else if (eventType.equals(WeChatContant.EVENT_TYPE_SCAN)) {
                    // TODO 处理扫描带参数二维码事件
                }
                // 上报地理位置
                else if (eventType.equals(WeChatContant.EVENT_TYPE_LOCATION)) {
                    // TODO 处理上报地理位置事件
                }
                // 自定义菜单
                else if (eventType.equals(WeChatContant.EVENT_TYPE_CLICK)) {
                    // TODO 处理菜单点击事件
                }
            }
            mes = mes == null ? "不知道你在干嘛" : mes;
            if (respXml == null) {
                respXml = WeChatUtil.sendTextMsg(requestMap, mes);
            }
            log.info("\n返回的数据:" + respXml);
            return respXml;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

	/**
     * @Description: 订阅的公众号用户信息存入数据库
     * @Param: [openId]
     * @return: void
     * @Author: XQD
     * @Date:2021/1/4 17:45
     */
    public void subscribeMPUserInfo(String projectId, String openId) {
        String accessToken = getAccessToken();
        if (StringUtils.isBlank(accessToken)){
            log.info("\n accessToken为空");
        }else {
            String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
            String mpUserInfo = HttpClientUtil.get(url);
            Map<String, Object> map = null;
            try {
                map = objectMapper.readValue(mpUserInfo, Map.class);
            } catch (IOException e) {
                log.error("公众号异常通知-获取用户信息转化异常", e);
            }
            QueryWrapper<TdCMpLogin> mpStaffLoginQueryWrapper = new QueryWrapper<>();
            mpStaffLoginQueryWrapper.eq("open_id", openId)
                    .eq("status", 0);
            TdCMpLogin mpLogin = mpLoginMapper.selectOne(mpStaffLoginQueryWrapper);
            if (mpLogin == null) {
                mpLogin = new TdCMpLogin();
                mpLogin.setId(GeneratorIDUtil.generatorId())
                        .setOpenId(openId)
                        .setNickName((String) map.get("nickname"))
                        .setHeadImageUrl((String) map.get("headimgurl"))
                        .setSex((Integer) map.get("sex"))
                        .setSubscribe((Integer) map.get("subscribe"))
                        .setUnionId((String) map.get("unionid"))
                        .setCountry((String) map.get("country"))
                        .setProvince((String) map.get("province"))
                        .setCity((String) map.get("city"));
                mpLoginMapper.insert(mpLogin);
                log.info("\n公众号用户信息添加成功 openId = {}", openId);
            } else {
                mpLogin.setSubscribe(1);
                mpLoginMapper.updateById(mpLogin);
                log.info("\n公众号用户信息修改成功 openId = {}", openId);
            }
        }

    }

    /**
     * @Description: 取消订阅用户
     * @Param: [projectId, openId]
     * @return: void
     * @Author: XQD
     * @Date:2021/1/4 17:45
     */
    public void unsubscribeMPUserInfo(String openId) {
        UpdateWrapper<TdCMpLogin> mpLoginUpdateWrapper = new UpdateWrapper<>();
        mpLoginUpdateWrapper.set("subscribe", 0)
                .eq("open_id", openId);
        if (update(mpLoginUpdateWrapper)) {
            log.info("\n取消关注的用户操作成功 openId = {}", openId);
        } else {
            log.info("\n取消关注的用户操作失败 openId = {}", openId);
        }
    }

常量类:WeChatContant.java

/**
 * @ClassName: WeChatContant
 * @Description: TODO
 * @Authror: XQD
 * @Date: 2021/1/4 15:37
 */
public class WeChatContant {


    // Token
    public static final String TOKEN = "zch";
    // 文本
    public static final Object REQ_MESSAGE_TYPE_TEXT = "text";
    // 图片
    public static final Object REQ_MESSAGE_TYPE_IMAGE = "image";
    // 语音
    public static final Object REQ_MESSAGE_TYPE_VOICE = "voice";
    // 视频
    public static final Object REQ_MESSAGE_TYPE_VIDEO = "video";
    // 地理位置
    public static final Object REQ_MESSAGE_TYPE_LOCATION = "location";
    // 链接
    public static final Object REQ_MESSAGE_TYPE_LINK = "link";
    // 消息类型
    public static final Object REQ_MESSAGE_TYPE_EVENT = "event";
    // 事件类型:订阅,扫码订阅
    public static final Object EVENT_TYPE_SUBSCRIBE = "subscribe";
    // 事件类型:取消订阅
    public static final Object EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
    // 事件类型:已关注后扫码推送类型
    public static final Object EVENT_TYPE_SCAN = "SCAN";
    // 事件类型:上报地理位置事件
    public static final Object EVENT_TYPE_LOCATION = "LOCATION";
    // 事件类型:自定义菜单事件
    public static final Object EVENT_TYPE_CLICK = "CLICK";

    // 开发者微信号
    public static final String ToUserName = "ToUserName";
    // 发送方账号(一个OpenID)
    public static final String FromUserName = "FromUserName";
    // 消息类型
    public static final String MsgType = "MsgType";
    // 内容
    public static final String Content = "Content";
    // 事件类型
    public static final String Event = "Event";
    // 事件KEY值
    public static final String EventKey = "EventKey";
    // 二维码的ticket
    public static final String Ticket = "Ticket";

公众号用户的表结构
在这里插入图片描述
也可以根据返回的数据自行获取需要用到的数据
官网地址:https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值