1.前期准备

1. 首先需要的是一个能正常运营的微信公众号或者订阅号,根据微信公众平台,使用已授权的用户登录,获取对应的appId 和 开发者密码 appSecret

得到appId和AppSecret是为了后续调用微信官方接口必不可少的参数,例如获取微信基础accessToken则需要以上入参;

2. 设置域名以及ip白名单

ip白名单主要是针对获取acces_token,一般设置成自己服务器的ip地址,因为还需要设置自定义域名,可以关联到服务器地址,从而微信接口请求返回可以有对应的请求地址,例如, 我服务器的ip地址是222.13.11.103 ,那么ip白名单就填入这个地址即可;

设置域名主要做回调地址使用,例如:pay.company.cn,需要根据官方指引,将对应的txt文件放到web服务器的根目录下即可

 在微信授权的时候需要用到其域名

3. 选择合适的消息模板,记住其模板id和点击详情后的内容格式,因为发送模板消息,需要模板id以及内容格式

2.用户微信授权,获取其openId(重要)

这一步非常重要,只有是跟微信对接,都需要得到用户的openId,才能把模板消息发送到对应的用户中,且每个微信用户都有一个唯一的openId,当获取到openId后,建议保存入库;

可参考微信官方文档:开发前必读 | 微信开放文档

这里将会指引你如何将用户进行网页授权也是就

1. 引导用户进入授权页面同意授权,获取code

2. 通过 code 换取网页授权access_token

3. 根据通过网页授权access_token和 openid 获取用户基本信息

以下代码,逻辑跟指引一样,先是构建url地址,然后回调自己定义的方法地址,同时微信会自动带出当前用户的code,然后根据code再次调用授权地址,带出对应的openId,而我们的目的就是获取用户的openId,例如官方示例地址;

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=https://chong.qq.com/php/index.php?d=&c=wxAdapter&m=mobileDeal&showwxpaytitle=1&vb2ctag=4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

代码如下;(敏感的appid和密码以及域名地址需要自己替换)

@Controller
public class MyController {
 
    private static final Logger log = LoggerFactory.getLogger(MyController .class);
 
    // appId
    private static final String appId = "wxc8xxxxcxxxxxx";
 
    // appIdSecret
    private static final String appIdSecret = "60b429xxxxxxxxxxxxxxx";
 
    //1.先查询code
    @RequestMapping("/getCode")
    public String getCode() {
        // 官方地址
        String urlFir = "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid=";
        // 微信申请的域名(提前准备)
        String domain = "http://pay.xxx.cn/wxpay";
        // 自定义跳转方法
        String redirectMethod = "/weixinoauth";
        // 地址进行encode转译 (未转译的地址是:http://pay.xxx.cn/wxpay/weixinoauth)
        // 转译后的地址是: http://pay.xxx.cn/wxpay/weixinoauth
        String encoderUrl = getURLEncoderString(domain   redirectMethod);
        log.info(urlFir  appId   "&redirect_uri="   encoderUrl  "&response_type=code&scope=snsapi_base"   "&state=STATE"   "#wechat_redirect");
        return urlFir   appId   "&redirect_uri="   encoderUrl  "&response_type=code&scope=snsapi_base"   "&state=STATE"   "#wechat_redirect";
    }
 
    /**
     * 编码
     * @param str
     * @return
     */
    public static String getURLEncoderString(String str) {
        String result = "";
        if (null == str) {
            return "";
        }
        try {
            result = java.net.URLEncoder.encode(str, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }
 
    //2.根据code获取openId
    @GetMapping("/wxpay/weixinoauth")
    public void weixinOauth(@RequestParam String code,@RequestParam String state) throws Exception {
        log.info("获取code:{}",code);
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
                  appId   "&secret="   appIdSecret   "&code="   code   "&grant_type=authorization_code";
        Map<String, Object> paramMap = null;
        String res = HttpUtil.get(url, paramMap);
        String openid = JSONObject.parseObject(res).getString("openid");
        log.info("根据code查询得到openId:{}",openid);
 
    }
}

需要在微信开发工具输入127.0.0.1/getCode,因为授权页面必须要在微信客户端中打开,所以需要下载微信开发工具,微信开发工具地址:开发前必读 | 微信开放文档

 下载安装后,需要使用已配置了开发者权限的微信账号登录

然后系统会打印出跳转地址和openId ,该工具会自动跳转/getCode返回的Url并且回调我们的方法 /wxpay/weixinoauth 进行获取用户code,再构建授权url地址j获取openId

打印情况如下(敏感信息已打码):

 如果正常到了这里,则说明成功了一半了。

3.获取微信基础accessToken

需要获取微信的基础accessToken用于构建模板消息发送的url入参,且该accessToken有效期只有两小时(下面简称token),因此当调用一下方法一次后,就可以将其放入redis中,设置过期时间(低于两小时);

    @GetMapping("/getToken")
    public void getAccessToken() throws Exception{
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="  appId  "&secret="   appIdSecret;
        String res = HttpUtil.get(url);
        JSONObject jsonObject = JSONObject.parseObject(res);
        String accessToken = jsonObject.getString("access_token");
        log.info("accessToken:{}", accessToken);
    }

代码会报错,但不影响获取token,日志打印如下; 保存token后续调用发送微信模板消息需要用到;

若出现了无效的ip地址错误,则确认ip白名单是否设置再去

4. 调用微信模板方法发送消息

这一步很简单,通过以上获取的 openId, accessToken 和 前期准备的模板id即可,我们只需要封装模板内容,再调用官方url即可

自定义DTO

@Data
@ToString
public class WeChatTemplateMsg {
    /**
     * 消息
     */
    private String value;
    /**
     * 消息颜色
     */
    private String color;
 
 
    public WeChatTemplateMsg(String value) {
        this.value = value;
        this.color = "#173177";
    }
 
    public WeChatTemplateMsg(String value, String color) {
        this.value = value;
        this.color = color;
    }
}
    @GetMapping("/sendMessage")
    public  String sendMessage() {
        // 模板参数
        Map<String, WeChatTemplateMsg> sendMag = new HashMap<String, WeChatTemplateMsg>();
 
        // openId代表一个唯一微信用户,即微信消息的接收人
        String openId = "oNB9p1BpVJEquxxxxxxxxx";
        // 公众号的模板id(也有相应的接口可以查询到)
        String templateId = "B0YStqTYdjHhY9Da9Sy2NM7xxxxxxxxxxx";
        // 微信的基础accessToken
        String accessToken = "57_LubK-8NKQc6C7jsLMxvdHaI0ju4x3-HPWEFhh7GKkw9fKbWhuxxoZyX4GaVIn6y4yO7RKfSlCyHdedKJlHUMZkd8457nKm0TOoaVkbzK1HCZ4g4gZdrmAGBylGBOZu9yxxxxxxxxxxxxxxxx";
        String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="   accessToken;
 
        /**
         *  其他模板可以从模板库中自己添加
         * 模板ID
         * B0YStqTYdjHhY9Da9Sy2NM7HXxxxxxxxxxxxxxx
         * 开发者调用模板消息接口时需提供模板ID
         * 标题
         * 产品兑付成功提醒
         * 行业
         * 金融业 - 证券|基金|理财|信托
         * 详细内容
         * {{first.DATA}}
         * 产品名称:{{keyword1.DATA}}
         * 当期兑付本金:{{keyword2.DATA}}
         * 当期兑付利息:{{keyword3.DATA}}
         * 已兑付期数:{{keyword4.DATA}}
         * 兑付日期:{{keyword5.DATA}}
         * {{remark.DATA}}
         */
        sendMag.put("first", new WeChatTemplateMsg("f123"));
        sendMag.put("keyword1", new WeChatTemplateMsg("111"));
        sendMag.put("keyword2", new WeChatTemplateMsg("222"));
        sendMag.put("keyword3", new WeChatTemplateMsg("333"));
        sendMag.put("keyword4", new WeChatTemplateMsg("444"));
        sendMag.put("remark", new WeChatTemplateMsg("r555"));
        RestTemplate restTemplate = new RestTemplate();
        //拼接base参数
        Map<String, Object> sendBody = new HashMap<>();
        sendBody.put("touser", openId);               // openId
        sendBody.put("url", "www.baidu.com");         // 点击模板信息跳转地址
        sendBody.put("topcolor", "#FF0000");          // 顶色
        sendBody.put("data", sendMag);                   // 模板参数
        sendBody.put("template_id", templateId);      // 模板Id
        ResponseEntity<String> forEntity = restTemplate.postForEntity(url, sendBody, String.class);
        log.info("结果是: {}",forEntity.getBody());
        JSONObject jsonObject = JSONObject.parseObject(forEntity.getBody());
        // 0
        String messageCode = jsonObject.getString("errcode");
        // 2431260672639467520
        String msgId = jsonObject.getString("msgid");
        System.out.println("messageCode : "   messageCode   ", msgId: "  msgId);
        return forEntity.getBody();
    }

 结果是:

可能需要的依赖:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.4.0</version>
</dependency>

总结

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

从零开始讲解Java微信公众号消息推送实现的更多相关文章

  1. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  3. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  4. Java实现世界上最快的排序算法Timsort的示例代码

    Timsort 是一个混合、稳定的排序算法,简单来说就是归并排序和二分插入排序算法的混合体,号称世界上最好的排序算法。本文将详解Timsort算法是定义与实现,需要的可以参考一下

  5. Java日期工具类的封装详解

    在日常的开发中,我们难免会对日期格式化,对日期进行计算,对日期进行校验,为了避免重复写这些琐碎的逻辑,我这里封装了一个日期工具类,方便以后使用,直接复制代码到项目中即可使用,需要的可以参考一下

  6. Java设计模式之模板方法模式Template Method Pattern详解

    在我们实际开发中,如果一个方法极其复杂时,如果我们将所有的逻辑写在一个方法中,那维护起来就很困难,要替换某些步骤时都要重新写,这样代码的扩展性就很差,当遇到这种情况就要考虑今天的主角——模板方法模式

  7. Java 中 Class Path 和 Package的使用详解

    这篇文章主要介绍了Java 中 Class Path和Package的使用详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

  8. java SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源)

    这篇文章主要介绍了java SpringBoot 分布式事务的解决方案(JTA+Atomic+多数据源),文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下

  9. Java一维数组和二维数组元素默认初始化值的判断方式

    这篇文章主要介绍了Java一维数组和二维数组元素默认初始化值的判断方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  10. java实现emqx设备上下线监听详解

    这篇文章主要为大家介绍了java实现emqx设备上下线监听详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部