JAVA微信公众号完整版教程扫一扫登录/自动回复/客服消息

开篇整理

之前写过一篇关于微信/企业微信/钉钉授权登录的博文,阅读量还挺高,正好此次在工作中有需要微信公众号扫码登录的项目,利用工作间隙捋一下整个的代码开发流程,本文主要还是以后端JAVA为主,前端其实配合的地方不是很多主要是后端完成大部分的工作。
很多小伙伴其实对于微信公众号的开发文档看的很迷,功能写的很全,但如果第一次开发微信的功能多少都有点懵逼,哈哈哈,我就是懵逼的其中一员!
废话不多说接下来我们开始·····

Maven依赖

 <!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.liyiorg</groupId>
            <artifactId>weixin-popular</artifactId>
            <version>2.8.24</version>
        </dependency>

配置公众测试号

  • 配置信息修改,注意书写外网可访问接口即可

在这里插入图片描述

后续方法中使用的wxService

  • 必要提醒此处配置微信参数,配置好方法即可在后续方法中直接调用微信的WxMpService相当方便建议配置会省很多事情
/**
 * @author hanfeng
 * @date 2021/12/4
 */
@Component
public class WeChatMpConfig {

    @Autowired
    private SysConfigFileUrl configFileUrl;

    @Bean
    public WxMpService wxMpService(){
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
        return wxMpService;
    }

    @Bean
    public WxMpConfigStorage wxMpConfigStorage(){
        WxMpDefaultConfigImpl wxMpDefaultConfig = new WxMpDefaultConfigImpl();
        wxMpDefaultConfig.setAppId(configFileUrl.getMpAppId());
        wxMpDefaultConfig.setSecret(configFileUrl.getMpAppSecret());
        return wxMpDefaultConfig;
    }
}

配置服务器所需接口

  • 后端需写两个接口接受微信服务器的回调即上方/wechat/callback接口,名称无所谓只要外网能访问到就行。可参考微信开发文档配置地址微信官方接口说明如下:
    在这里插入图片描述

  • 服务器验证-具体实现逻辑代码如下(直接CV进行实验即可)注意:此处接受方法为GET上方图片有说明,所以此接口只是配合微信做一个服务器验证操作

	 /**
     * 微信验证回调
     *
     * @param request
     * @param response
     */
    @GetMapping(value = "/callback")
    public void init(HttpServletRequest request, HttpServletResponse response) {
        log.info("==微信回调Token验证==");
        try {
            String nonce = request.getParameter("nonce");
            String timestamp = request.getParameter("timestamp");
            String signature = request.getParameter("signature");
            String echoStr = request.getParameter("echostr");
            //1.对三个字符进行排序
            List<String> params = CollUtil.newArrayList(nonce, timestamp, #此处填写上方服务器配置所填写的Token);
            Collections.sort(params);
            //list转换成string
            String tmpStr = ArrayUtil.toString(params);
            //2.将三个参数字符串转换成字符串进行sha1加密
            String sha1 = SecureUtil.sha1(tmpStr);
            log.info("加密之前:" + signature + "加密之后" + sha1);
            //3.比对两者的加密参数是否相等
            if (sha1.equals(signature)) {
                //4.验证成功返回给微信服务器消息验证
                OutputStream outputStream = response.getOutputStream();
                outputStream.write(URLUtil.encode(echoStr).getBytes());
                outputStream.flush();
                outputStream.close();
                log.info("微信验证成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 服务器事件推送-微信官方说明如下:微信对应文档说明
    在这里插入图片描述
  • 接收微信服务器事件推送接口POST方法,完成此步骤即可实现接受微信的事件推送,具体思路根据微信回调的事件不同进行不同的处理,此处只是举例子不一定要写 注意:此方法为POST
	/**
     * 微信推送事件处理
     *
     * @param request
     * @param response
     */
    @PostMapping(value = "/callback")
    public void Event(HttpServletRequest request, HttpServletResponse response) {

        log.info("==微信推送事件回调处理==");
        //依赖于dom4j 框架自带该依赖包springboot框架中
        SAXReader saxReader = new SAXReader();
        try {
            BufferedReader reader = request.getReader();
            org.dom4j.Document read = saxReader.read(reader);
            Element rootElement = read.getRootElement();
            Iterator iterator = rootElement.elementIterator();
            Map<String, Object> map = new HashMap<>();
            //此步骤主要为了拿到微信回调的xml参数进行map处理方便后续使用
            while (iterator.hasNext()) {
                Element element = (Element) iterator.next();
                map.put(element.getName(), element.getStringValue());
            }
            //获取对应的参数值 需要看具体的字段对应的含义参考上方图片中有
            String ticket = map.get("Ticket") + "";
            log.info("ticket===" + ticket);
            String eventType = map.get("Event") + "";
            log.info("eventType===" + eventType);
            String toUserName = map.get("ToUserName") + "";
            log.info("toUserName===" + toUserName);
            String fromUserName = map.get("FromUserName") + "";
            log.info("fromUserName===" + fromUserName);
            String createTime = map.get("CreateTime") + "";
            log.info("createTime===" + createTime);
            String msgType = map.get("MsgType") + "";
            log.info("msgType===" + msgType);
            //此步骤目前可不要 但后续扫码登录会用到,所以将ticket存储到redis中方便后续调用
            //如未配置redis可暂时删除
            /**if (StrUtil.isNotEmpty(ticket) && !"null".equals(ticket)) {
                log.info(WX_TICKET_KEY_PREFIX + ticket);
                redisService.setCacheMap(WX_TICKET_KEY_PREFIX + ticket, map);
                redisService.expire(WX_TICKET_KEY_PREFIX + ticket,10L,TimeUnit.MINUTES);
            }*/
            //判断是否重复通知
            if (wxMessageKey.exists(fromUserName + "-" + toUserName + "-" + createTime)) {
                log.info(fromUserName+"微信消息通知重复");
                return;
            }
            //如果为事件类型 VIEW 为授权登录无需发送消息通知
            if ("event".equals(msgType)&&!"VIEW".equals(eventType)) {
                List<WxMpKefuMessage> keFuMessages = new ArrayList<>();
                /**处理订阅事件 即用户关注公众号操作*/
                 if("subscribe".equals(eventType)){
                     WxMpKefuMessage subscribeKeFuMessage = new WxMpKefuMessage();
                     subscribeKeFuMessage.setToUser(fromUserName);
                     subscribeKeFuMessage.setMsgType(WX_MESSAGE_TEXT);
                     subscribeKeFuMessage.setContent("欢迎来到CSDN \n\n工作时间:08:30 - 17:30");
                     keFuMessages.add(subscribeKeFuMessage);
                 } else if("unsubscribe".equals(eventType)){
                     //取消关注公众号目前不做记录
                 }
                 //扫码登录后发送客服消息提示文字
                WxMpKefuMessage keFuMessage = new WxMpKefuMessage();
                keFuMessage.setToUser(fromUserName);
                keFuMessage.setMsgType(WX_MESSAGE_TEXT);
                keFuMessage.setContent("您好,您已登录成功!");
                keFuMessages.add(keFuMessage);
                //处理取消订阅消息 此方法具体逻辑在下方
                this.doSendKeFusMessage(keFuMessages);
                log.info("eventType:" + eventType + ",fromUserName:" + fromUserName + ",toUserName:" + toUserName + ",msgType:" + msgType + ",createTime:" + createTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
	/**
     * 客服接口-发消息
     *
     * @param lstWxMpTemplate
     */
    public void doSendKeFusMessage(List<WxMpKefuMessage> lstWxMpTemplate) {
        WxMpKefuService kefuService = wxMpService.getKefuService();
        for (WxMpKefuMessage news : lstWxMpTemplate) {
            try {
                boolean message = kefuService.sendKefuMessage(news);
                log.info("发送客服消息结果:" + message);
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

获取微信accessToken

  • 此处获取accessToken方法具体如下:
 @ApiOperation("获取token")
    @GetMapping("/token")
    public String accessToken() {
        String accessToken = "";
        try {
        	//此处依然为存入redis如不需要可直接忽略
            /**Object token = redisService.getCacheObject(WX_TOKEN_KEY_PREFIX);
            if (token != null) {
                return token.toString();
            }*/
            //这里的accessToken与通过code获取的token不同需存储到缓存留着调用
            WxMpApiUrl.Other getAccessTokenUrl = WxMpApiUrl.Other.GET_ACCESS_TOKEN_URL;
            String url = String.format(
                    getAccessTokenUrl.getPrefix() + getAccessTokenUrl.getPath(),
                    wxMpConfigStorage.getAppId(),
                    wxMpConfigStorage.getSecret());
            accessToken = HttpUtil.get(url);
            JSONObject jsonObject = JSONUtil.parseObj(accessToken);
            if (jsonObject.getStr("access_token") != null) {
                accessToken = jsonObject.getStr("access_token");
               /* redisService.setCacheObject(WX_TOKEN_KEY_PREFIX, accessToken, WX_EXPIRATION, TimeUnit.SECONDS);*/
            }
            log.info("获取token:" + accessToken);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return accessToken;
    }
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>