java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java公众号关注、消息推送

Java实现公众号功能、关注及消息推送实例代码

作者:夕四丶

公众号开发近些年是一个比较热门的方向,下面这篇文章主要给大家介绍了关于Java实现公众号功能、关注及消息推送的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

描述

 使用Java实现公众号功能的接入,配合业务实现:

     用户关注、取消关注、推送数据服务、用户在公众号信息转发人工服务等功能

     本文章说明公众号代码配置实现,公众号申请,注册方式,自行查看官网说明

引入依赖

		<!--微信公众号(包括订阅号和服务号)-->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>4.4.2.B</version>
        </dependency>

注册公众号配置

@Slf4j
@Configuration
@RequiredArgsConstructor
@ConditionalOnClass(WxMpService.class)
@EnableConfigurationProperties()
public class WxMpConfiguration {
    private final MpConfigMapper mpConfigMapper;
    private final LogHandler logHandler;
    private final SubscribeHandler subscribeHandler;
    private final UnsubscribeHandler unsubscribeHandler;
    private final TextMsgHandler textMsgHandler;

    /**
     * 用户配置(获取用户客户代码)
     */
    private static Map<String, Integer> MP_USER_CONF = new HashMap<>();

    public static Long getCustomId(String appid) {
        return Long.valueOf(MP_USER_CONF.getOrDefault(appid, 0));
    }

    /**
     * 加载公众号配置,注册Bean对象
     */
	@Bean
    public WxMpService wxMpService() {
    	//这个是数据库公众号信息配置表
        List<MpConfig> mpConfigs = mpConfigMapper.selectList(Wrappers.emptyWrapper());
        if (CollectionUtil.isEmpty(mpConfigs)) {
            log.error("读取配置为空,公众号配置类加载失败!");
            return new WxMpServiceImpl();
        }
        log.info("公众号的配置:{}", JSON.toJSONString(mpConfigs));
        Map<String, WxMpConfigStorage> multiConfigStorages = new HashMap<>(16);
        for (MpConfig mpConfig : mpConfigs) {
            WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
            configStorage.setAppId(mpConfig.getAppid());
            configStorage.setSecret(mpConfig.getSecret());
            configStorage.setToken(mpConfig.getToken());
            configStorage.setAesKey(mpConfig.getAeskey());
            multiConfigStorages.put(mpConfig.getCustomerCode(), configStorage);
            MP_USER_CONF.put(mpConfig.getAppid(), mpConfig.getCustomerId());
        }
        WxMpService mpService = new WxMpServiceImpl();
        mpService.setMultiConfigStorages(multiConfigStorages);
        return mpService;
    }
    
     /**
     * 配置公众号个事件路由,分类处理:关注、取消关注、用户发送消息
     */
    @Bean
    public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
        // 记录所有事件的日志 (异步执行)
        newRouter.rule().handler(this.logHandler).next();
        // 关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).
                event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler).end();
        //取消关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).
 event(WxConsts.EventType.UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
 		//用户往公众号发送消息事件处理
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).
                handler(this.textMsgHandler).end();
        return newRouter;
    }
 }

公众号各事件处理

实现公众号事件处理类

/**
 * 微信公众号AbstractHandler
 */
public abstract class AbstractHandler implements WxMpMessageHandler {
    protected Logger logger = LoggerFactory.getLogger(getClass());
}

实现公众号日志记录处理器

/**
 * 微信公众号日志记录处理器
 */
@Component
public class LogHandler extends AbstractHandler {
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                    Map<String, Object> context, WxMpService wxMpService,
                                    WxSessionManager sessionManager) {
        this.logger.info("【公众号】-记录请求日志,内容:{}", JSON.toJSONString(wxMessage));
        return null;
    }
}

实现公众号用户关注处理器

/**
 * 微信公众号用户关注
 */
@Component
@RequiredArgsConstructor
public class SubscribeHandler extends AbstractHandler {
	//公众号用户表
    private final MpUserParentMapper mpUserParentMapper;
    //小程序用户表(一般公众号和小程序配套使用)
    private final MiniappUserParentMapper miniappUserParentMapper;
    //公众号配置表
    private final MpConfigMapper mpConfigMapper;

	@Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                    Map<String, Object> context, WxMpService wxMpService,
                                    WxSessionManager sessionManager) throws WxErrorException {

        this.logger.info("【公众号-关注功能】-新关注用户 OPENID: " + wxMessage.getFromUser());

        // 获取微信用户基本信息
        try {
            WxMpUser userWxInfo = wxMpService.getUserService()
                    .userInfo(wxMessage.getFromUser(), null);
            String appId = wxMpService.getWxMpConfigStorage().getAppId();
            Long customerId = WxMpConfiguration.getCustomId(appId);
            logger.info("userWxInfo:{}", userWxInfo);
            if (userWxInfo != null) {
            	//查询数据库,公众号用户表,是否有这个用户
                MpUserParent existMpUser = mpUserParentMapper.selectOneByOpenId(userWxInfo.getOpenId());
                //不存在则新增一条公众号用户记录
                if (existMpUser == null) {
                    MpUserParent mpUser = new MpUserParent();
                    mpUser.setOpenId(userWxInfo.getOpenId());
                    mpUser.setUnionId(userWxInfo.getUnionId());
                    mpUser.setAvatarUrl(userWxInfo.getHeadImgUrl());
                    mpUser.setNickName(userWxInfo.getNickname());
                    mpUser.setCustomerId(customerId);
                    mpUserParentMapper.insert(mpUser);
                    //检测是否有跟小程序账号关联
                    MiniappUserParent maUserParent = miniappUserParentMapper.selectOneByUnionId(mpUser.getUnionId(), customerId);
                    if (maUserParent != null && StringUtil.isBlank(maUserParent.getMpOpenId())) {
                        maUserParent.setMpOpenId(mpUser.getOpenId());
                        maUserParent.setUpdateTime(new Date());
                        miniappUserParentMapper.updateById(maUserParent);
                        this.logger.info("【公众号-关注功能】-公众号账号和小程序绑定成功!unionId:{},mpOpenId:{} ", mpUser.getUnionId(), mpUser.getOpenId());
                    }
                } else {
                    //之前有关注过的,无需重复写入,更改关注状态即可
                    MpUserParent updateUser = new MpUserParent();
                    updateUser.setMpId(existMpUser.getMpId());
                    updateUser.setFollowStatus(1);
                    updateUser.setUpdateTime(new Date());
                    updateUser.setCustomerId(customerId);
                    updateUser.setUnionId(userWxInfo.getUnionId());
                    mpUserParentMapper.updateById(updateUser);
                }
			}
        } catch (WxErrorException e) {
            if (e.getError().getErrorCode() == 48001) {
                this.logger.error("【公众号-关注功能】-该公众号没有获取用户信息权限!");
            }
            logger.error("【公众号-关注功能异常】-异常信息:{}", e);
        }
		WxMpXmlOutMessage responseResult = null;
        try {
            responseResult = this.handleSpecial(wxMessage);
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
        }
        if (responseResult != null) {
            return responseResult;
        }
        String appId = wxMpService.getWxMpConfigStorage().getAppId();
        try {
            logger.info("获取公众号appid:{}", appId);
            MpConfig miniappConfig = mpConfigMapper.selectByAppid(appId);
            //关注公众号,发送消息给用户
            return new TextBuilder().build("感谢关注,将持续为您推送信息", wxMessage, wxMpService);
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
        }
		return null;
    }
    
    /**
     * 处理特殊请求,比如如果是扫码进来的,可以做相应处理
     */
    private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage) throws Exception {
        //TODO
        return null;
    }
}

实现公众号用户取消关注处理器

/**
 * 微信公众号用户取消关注
 */
@Component
@RequiredArgsConstructor
public class UnsubscribeHandler extends AbstractHandler {
    private final MpUserParentMapper mpUserParentMapper;
    private final MpConfigMapper mpConfigMapper;
	@Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                                    Map<String, Object> context, WxMpService wxMpService,
                                    WxSessionManager sessionManager) {
        String openId = wxMessage.getFromUser();
        this.logger.info("取消关注用户 OPENID: " + openId);
        //更新关注状态为取消关注状态
        UpdateWrapper<MpUserParent> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("openId", openId);
        updateWrapper.eq("followStatus", 1);
        MpUserParent updateMpUser = new MpUserParent();
        updateMpUser.setFollowStatus(2);
        //不删除公众号用户信息,修改关注状态值即可
        mpUserParentMapper.update(updateMpUser, updateWrapper);
        String appId = wxMpService.getWxMpConfigStorage().getAppId();
        logger.info("获取公众号appid:{}",appId);
        MpConfig miniappConfig = mpConfigMapper.selectByAppid(appId);
        //取消关注,发送信息给用户
        return new TextBuilder().build("已退订", wxMessage, wxMpService);
    }
}

实现公众号用户发送消息处理器

@Slf4j
@Component
@RequiredArgsConstructor
public class TextMsgHandler extends AbstractHandler {

    private final static Integer TEXT_TYPE = 1;
    @Override
    public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
        String content = wxMessage.getContent();
        log.info("【公众号-消息】-用户:{} , 发送消息:{}, ", wxMessage.getFromUser(), content);
        // 获取微信用户基本信息
        try {
            String appId = wxMpService.getWxMpConfigStorage().getAppId();
            Long customerId = WxMpConfiguration.getCustomId(appId);
            //自动回复匹配的关键字
            MpAutoReplyDTO autoReply = InitConfDataUtil.getAutoReply(customerId, content);
            if (autoReply != null) {
                Integer replyType = autoReply.getReplyType();
                String reply = autoReply.getReply();
                if (TEXT_TYPE.equals(replyType)) {
                	//文字处理
                    return new TextBuilder().build(reply, wxMessage, wxMpService);
                } else {
                	//图片处理
                    return new ImageBuilder().build(reply, wxMessage, wxMpService);
                }
            } else {
                //自动回复没有匹配的就转到人工
                WxMpXmlOutMessage build = new TextBuilder().build(wxMessage.getContent(), wxMessage, wxMpService);
                //msgType设置固定值就转到人工:transfer_customer_service
                build.setMsgType("transfer_customer_service");
                return build;
            }
        } catch (Exception e) {
            log.info("回复失败e:{}", e);
        }
        return null;
    }
}

用户消息事件分类处理Builder

定义处理抽象类

//该类定义处理标准,后续根据业务自行扩展
public abstract class AbstractBuilder {
    protected final Logger logger = LoggerFactory.getLogger(getClass());
    public abstract WxMpXmlOutMessage build(String content,
                                            WxMpXmlMessage wxMessage, WxMpService service);
}

实现处理抽象类–子类–文本消息

public class TextBuilder extends AbstractBuilder {
    @Override
    public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
                                   WxMpService service) {
        return WxMpXmlOutMessage.TEXT().content(content)
                .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
                .build();
    }
}

实现处理抽象类–子类–图片消息

public class ImageBuilder extends AbstractBuilder {
    @Override
    public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
                                   WxMpService service) {
        return WxMpXmlOutMessage.IMAGE().mediaId(content)
                .fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
                .build();
    }
}

公众号模板消息推送

以上实现了Java整合公众号,后续业务扩展,需要往关注公众号的用户进行相关的消息推送,消息推送前,

需要在微信公众号申请推送模板,拿到对应的模板ID,这个有用,生成推送消息时,需要往模板填充信息,

如何申请公众号模板,自行参考下官网说明

/**
 * 微信公众号信息推送
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MpMsgPush {
	//微信的公众号推送处理类
    private final WxMpService wxMpAgentService;
    //数据库公众号模板消息表
    private final MpTemplateManage mpTemplateManage;

 	/**
     * 发送微信模板信息
     *
     * @param mpPushDTO 推送信息实体类
     * @return 是否推送成功
     */
    @Async
    public Boolean sendTemplateMsg(MpPushDTO mpPushDTO) {
        log.info("【公众号告警模板信息推送】-推送信息:{}", JSONObject.toJSONString(mpPushDTO));
        Long customerId = mpPushDTO.getCustomerId();
        String name = mpPushDTO.getMpName();
        //选择往哪个公众号发送模板消息,这个上面注册公众号的Bean的时候已经注入
        WxMpService wxMpService = wxMpAgentService.switchoverTo(mpPushDTO.getCustomerCode());
        //自己搞的一个枚举,根据当前的消息实体类信息,来判断使用哪个模板ID
        String templateId = TemplateConfConstant.getWXTemplateConf(customerId, mpPushTypeEnum.getValue());
        // 获取模板消息接口
        WxMpTemplateMessage templateMessage = mpTemplateManage.getWarnTemplate(mpPushDTO, templateId, name);
        if (templateMessage != null) {
            log.info("发送消息:{}", JSONObject.toJSONString(templateMessage));
        } else {
            log.error("获取消息模板为空!");
            return false;
        }
        String msgId = null;
        try {
            Long parentId = mpPushDTO.getParentId();
            String imeiNo = mpPushDTO.getImeiNo();
            // 发送模板消息
            msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (Exception e) {
            log.error("【公众号模板信息推送】-推送失败,异常信息:", e);
        }
        log.warn("·==++--·推送公众号模板信息:{}·--++==·", msgId != null ? "成功" : "失败");
        return msgId != null;
    }
    
	/**
     * 获取提醒模板
     *
     * @param mpPushDTO
     * @return
     */
    public WxMpTemplateMessage getWarnTemplate(MpPushDTO mpPushDTO, String templateId, String name) {
        // 发送模板消息接口
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                // 接收者openid
                .toUser(mpPushDTO.getOpenId())
                // 模板id
                .templateId(templateId)
                .build();
        StringBuilder keyword1 = new StringBuilder();
        keyword1.append(mpPushDTO.getStudentName()).
                append("(").append(mpPushDTO.getImeiNo()).append(")");
        // 添加模板数据
        templateMessage.addData(new WxMpTemplateData("first", "您好,你有一条新的提醒"))
                .addData(new WxMpTemplateData("keyword1", keyword1.toString()))
                .addData(new WxMpTemplateData("keyword2", mpPushDTO.getTemplateType()))
                .addData(new WxMpTemplateData("remark", name + "智能推送系统"));
        return templateMessage;
    }


}

总结 

到此这篇关于Java实现公众号功能、关注及消息推送的文章就介绍到这了,更多相关Java公众号关注、消息推送内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文