广告位联系
返回顶部
分享到

微信公众号开发消息推送功能介绍

java 来源:互联网 作者:佚名 发布时间:2023-02-16 22:37:35 人浏览
摘要

微信公众号开发 运行效果 微信公众号简介 微信公众号分为服务号、订阅号、企业号,订阅号可以个人申请,服务号和企业号要有企业资质才可以。 我们所说的微信公众号开发指的是订

微信公众号开发

运行效果

在这里插入图片描述

微信公众号简介

微信公众号分为服务号、订阅号、企业号,订阅号可以个人申请,服务号和企业号要有企业资质才可以。

我们所说的微信公众号开发指的是订阅号和服务号。关于订阅号和服务器的区别,官方是这样解释的

  • 服务号:主要偏向于服务交互(功能类似12315,114,银行,提供绑定信息,服务交互),每月可群发4条消息;服务号**适用人群:媒体、企业、政府或其他组织。
  • 订阅号:主要偏向于为用户传达资讯,(功能类似报纸杂志,为用户提供新闻信息或娱乐趣事),每天可群发1条消息;订阅号**适用人群:个人、媒体、企业、政府或其他组织。

注册微信公众号

进入微信公众号注册页面https://mp.weixin.qq.com/点击公众号右上方的注册按钮,进入注册界面,填写基本信息,选择订阅号, 完成身份认证, 即可。

注册测试公众号

个人订阅号有一些接口是没有权限的,也就是说个人订阅号无法调用一些高级的权限接口,如生成二维码、网页授权、自定义菜单、微信支付这样的接口权限个人订阅号是没有调用权限的, 幸运的是,微信公众平台提供了测试公众账号,测试公众号有很多个人订阅号不具备的权限, 测试公众号的注册地址为:

http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

用微信扫描页面中的二维码进行登录,登录成功后,就可以看到腾讯分配给我们的测试公众号的信息了,如下图所示, 接下来我们就可以搭建环境,进行开发测试了

img

测试公众号的所拥有的接口权限如下:

image.png

image.png

搭建微信本地调试环境

开发基于微信公众号的应用最大的痛苦之处就是调试问题,每次实现一个功能后都需要部署到一个公网服务器进行测试,因为微信用户每次向公众号发起请求时,微信服务器会先接收到用户的请求,然后再转发到我们的服务器上,也就是说,微信服务器是要和我们的服务器进行网络交互,所以我们必须保证我们的服务器外网可以访问到,这种部署到公网服务器进行测试的做法对于我们开发者来说简直是噩梦。所以我们要想一个办法可以做到本地部署,本地调试代码,而要做到这一点,那么我们要解决的问题就是将内网的部署服务器映射到外网,让微信服务器可以正常访问到,幸运的是,借助于第三方软件Ngrok,我们就可以做得到。Ngrok是一个免费的软件Ngrok,使用Ngrok后,我们就可以实现内网穿透,也就是说我们可以将内网的服务器映射到外网给别人访问,这对于我们在本地开发环境中调试微信代码是以及给用户演示一些东西非常快速和有帮助的,因为可以直接使用我们自己的内网的电脑作为服务器。不过需要翻墙访问.常用的内网穿透工具有natapp,ngrok,dingding,关于微信公众号开发,这三个工具我都使用了,只有natapp可以正常开发。

关于natapp的使用网上很多,我在这里就不在介绍了。

natapp成功标志:

在这里插入图片描述

可以通过访问http://xt77eg.natappfree.cc访问到我们本机的服务

微信公众号接入(校验签名)

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

在这里插入图片描述

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

1)将token、timestamp、nonce三个参数进行字典序排序

2)将三个参数字符串拼接成一个字符串进行sha1加密

3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

@Controller

@RequestMapping(value = "wx")

public class WeiController{

 

    /**

     * 公众号appid

     */

    @Value("${wx.appid}")

    private  String appid;

 

    /**

     * 公众号appSecret

     */

    @Value("${wx.secret}")

    private  String secret;

 

    /**

     * 微信消息接收和token验证

     * @param request

     * @param response

     * @throws IOException

     */

    @GetMapping("/weChatToken")

    public  void weChat(HttpServletRequest request, HttpServletResponse response) {

        boolean isGet = request.getMethod().toLowerCase().equals("get");

        if (isGet) {

            // 微信加密签名

            String signature = request.getParameter("signature");

            // 时间戳

            String timestamp = request.getParameter("timestamp");

            // 随机数

            String nonce = request.getParameter("nonce");

            // 随机字符串

            String echostr = request.getParameter("echostr");

            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败

            if (signature != null && CheckoutUtil.checkSignature(signature, timestamp, nonce)) {

                try {

                    PrintWriter print = response.getWriter();

                    print.write(echostr);

                    print.flush();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

public class CheckoutUtil {

 

 

    public static  String token  = "999";

 

    /**

     * 验证签名

     * @param signature

     * @param timestamp

     * @param nonce

     * @return

     */

    public static boolean checkSignature(String signature, String timestamp, String nonce) {

        String[] arr = new String[] { token, timestamp, nonce };

        // 将token、timestamp、nonce三个参数进行字典序排序

        Arrays.sort(arr);

        StringBuilder content = new StringBuilder();

        for (int i = 0; i < arr.length; i++) {

            content.append(arr[i]);

        }

        MessageDigest md = null;

        String tmpStr = null;

 

        try {

            md = MessageDigest.getInstance("SHA-1");

            // 将三个参数字符串拼接成一个字符串进行sha1加密

            byte[] digest = md.digest(content.toString().getBytes());

            tmpStr = byteToHex(digest );

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        }

        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信

        return tmpStr != null ? tmpStr.equals(signature) : false;

    }

     

    /**

     * 十六进制字节数组转为字符串

     * @param hash

     * @return

     */

    private static String byteToHex(final byte[] hash) {

        Formatter formatter = new Formatter();

        for (byte b : hash) {

            formatter.format("%02x", b);

        }

        String result = formatter.toString();

        formatter.close();

        return result;

    }

进入微信测试公众号管理界面,在接口配置信息中填入映射的外网地址和代码中声明的token,如下图所示:

点击提交,会显示配置成功,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bPMvNxRI-1608702695943)(typora-user-images\image-20201214105001081.png)]

到此,我们的公众号应用已经能够和微信服务器正常通信了,也就是说我们的公众号已经接入到微信公众平台了。

给指定用户推送消息

网页授权获取用户openid

如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息(openId),进而实现业务逻辑。

关于网页授权回调域名的说明:

1、在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;

2、授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com 无法进行OAuth2.0鉴权

3、如果公众号登录授权给了第三方开发者来进行管理,则不必做任何设置,由第三方代替公众号实现网页授权即可

获取用户openId步骤:

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

2、通过code换取openId

代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

@Controller

@RequestMapping(value = "wx")

public class WeiController{

 

 

    private  String appid="微信公众号的appid";

    private  String secret="微信公众号的secret";

 

    /**

     * 获取微信用户code,并重定向获取用户openId

     * @return

     */

    @GetMapping("/getUserCode")

    public String  getUserCode(){

        String backUrl = "http://xt77eg.natappfree.cc/wx/getUserOpenId";

        String getOpenIdUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri="+ backUrl+"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";

        getOpenIdUrl = getOpenIdUrl.replace("APPID",appid);

        return "redirect:" + getOpenIdUrl;

    }

 

    /**

     * 获取用户openId

     * @return

     * @throws IOException

     */

    @GetMapping("/getUserOpenId")

    @ResponseBody

    public  String getUserOpenId()throws IOException{

        //获取code

        String code = request.getParameter("code");

        //换取用户openid

        String url="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

        url=url.replace("APPID", appid).replace("SECRET", secret).replace("CODE", code);

        JSONObject result = Util.doGetJson(url);

        JSONObject jSONObject = JSONObject.parseObject(String.valueOf(result));

        String openid = jSONObject.getString("openid");

        return openid;

    }

给指定用户发送模板信息

首先要准备一个模板,测试号可自定义模板,但在正式公众号我们要申请,或者使用别人已经申请过的模板。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KtE1NG6h-1608702695950)(typora-user-images\image-20201214111214457.png)]

pom:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

<dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-starter-web</artifactId>

       </dependency>

 

       <!--微信模版消息推送三方sdk-->

       <dependency>

           <groupId>com.github.binarywang</groupId>

           <artifactId>weixin-java-mp</artifactId>

           <version>3.3.0</version>

       </dependency>

       <dependency>

           <groupId>org.projectlombok</groupId>

           <artifactId>lombok</artifactId>

           <version>1.18.8</version>

       </dependency>

       <dependency>

           <groupId>com.alibaba</groupId>

           <artifactId>fastjson</artifactId>

           <version>1.2.58</version>

       </dependency>

       <dependency>

           <groupId>org.springframework.boot</groupId>

           <artifactId>spring-boot-test</artifactId>

           <version>2.1.8.RELEASE</version>

           <scope>test</scope>

       </dependency>

       <dependency>

           <groupId>junit</groupId>

           <artifactId>junit</artifactId>

           <scope>test</scope>

       </dependency>

Controller:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

@Controller

@RequestMapping(value = "wx")

public class WeiController{

    @Resource

    PushMessageService pushMessageService;

 

    /**

     * 向每个用户推送消息

     * @return

     */

    @GetMapping("/sendMessage")

    @ResponseBody

    public String sendMessage(){

        String openId =  "用户openId";

        if(!"".equals(openId)){

            AlarmParamsDTO dto = new AlarmParamsDTO("申请进度", "国家奖学金", "申请通过", time, "成功");

            dto.setOpenId(openId);

            pushMessageService.pushMessage(dto);

        }

        return "success";

    }

Service:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

@Service

@Slf4j

public class PushMessageServiceImpl implements PushMessageService{

 

    private  String appid="微信公众号appid";

    private  String secret="微信公众号secret";

 

    /**

     * 给微信公众号某个用户推送信息

     * @param alarmParamsDTO

     */

    @Override

    public void pushMessage(AlarmParamsDTO alarmParamsDTO) {

        //1,配置

        WxMpInMemoryConfigStorage wxStorage = new WxMpInMemoryConfigStorage();

        wxStorage.setAppId(appid);

        wxStorage.setSecret(secret);

        WxMpService wxMpService = new WxMpServiceImpl();

        wxMpService.setWxMpConfigStorage(wxStorage);

        List<WxMpTemplateData> wxMpTemplateData = Arrays.asList(

                new WxMpTemplateData("first",alarmParamsDTO.getFirst(),"#000000"),

                new WxMpTemplateData("keyword1",alarmParamsDTO.getKeyword1(),"#000080"),

                new WxMpTemplateData("keyword2",alarmParamsDTO.getKeyword2(),"#0000FF"),

                new WxMpTemplateData("keyword3",alarmParamsDTO.getKeyword3(),"#FFD700"),

                new WxMpTemplateData("remark",alarmParamsDTO.getRemark(),"#00FF00")

        );

        //2,推送消息

        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()

                .toUser(alarmParamsDTO.getOpenId())

                .templateId("tIDrdFcqFGMsTnc462H49_DbjgXUuIjsqIlQttq7VDE")

                .data(wxMpTemplateData)

                .url("http://www.baidu.com")

                .build();

        try {

            wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);

        } catch (Exception e) {

            System.out.println("推送失败:" + e.getMessage());

        }

 

    }

}

entity:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

@Setter

@Getter

@NoArgsConstructor

@AllArgsConstructor

public class AlarmParamsDTO {

 

 

    /**

     * 推送信息小标题

     */

    private String first;

 

    /**

     * 学生姓名

     */

    private String keyword1;

 

    /**

     * 申请资助类型

     */

    private String keyword2;

 

    /**

     * 申请状态

     */

    private String keyword3;

 

    /**

     * 申请结果

     */

    private String remark;

 

    /**

     * 用户微信openId,唯一标识

     */

    private String openId;

 

    public AlarmParamsDTO(String first, String keyword1, String keyword2, String keyword3, String remark) {

        this.first = first;

        this.keyword1 = keyword1;

        this.keyword2 = keyword2;

        this.keyword3 = keyword3;

        this.remark = remark;

    }

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。

您可能感兴趣的文章 :

原文链接 : https://blog.csdn.net/m0_47740092/article/details/111588455
相关文章
  • SpringCloud OpenFeign基本介绍与实现示例
    介绍 在上面一篇介绍Nacos的文章最后,两个服务的相互调用是用的RestTemplate类完成的。但这种方式不是很推荐,更佳的方式是用OpenFeign组件
  • 微信公众号开发消息推送功能介绍

    微信公众号开发消息推送功能介绍
    微信公众号开发 运行效果 微信公众号简介 微信公众号分为服务号、订阅号、企业号,订阅号可以个人申请,服务号和企业号要有企业资质
  • SpringBoot多controller添加URL前缀的实现方法

    SpringBoot多controller添加URL前缀的实现方法
    前言 在某些情况下,服务的controller中前缀是一致的,例如所有URL的前缀都为/context-path/api/v1,需要为某些URL添加统一的前缀。 能想到的处理
  • Java synchronized重量级锁实现过程浅析

    Java synchronized重量级锁实现过程浅析
    一、什么是重量级锁 当有大量的线程都在竞争同一把锁的时候,这个时候加的锁,就是重量级锁。 这个重量级锁其实指的就是JVM内部的Ob
  • Java synchronized轻量级锁实现过程浅析

    Java synchronized轻量级锁实现过程浅析
    一、什么是轻量级锁 轻量级锁是JDK 6之中加入的新型锁机制,它名字中的轻量级是相对于使用monitor的传统锁而言的。轻量级锁指的是存在多
  • Java两大工具库Commons和Guava使用介绍

    Java两大工具库Commons和Guava使用介绍
    除了操作集合、限流和缓存,Guava还有另一个隐秘的功能:事件总线EventBus机制是发布-订阅模式的实现,不需要显式地注册回调比观察者模式
  • Java中List集合数据修改方式

    Java中List集合数据修改方式
    Java中List集合数据修改 先说写这篇文章的原因 我被提供了一个需求,Excel表格数据导入数据库,按照常理而言是很简单的,但是这个需求不
  • Java实现解析.xlsb文件的教程

    Java实现解析.xlsb文件的教程
    Java解析.Xlsb文件 pom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dependency groupIdorg.apache.poi/groupId artifactIdpoi/artifactId version3.17/version /dependency dependency groupI
  • Java实现国产加密算法SM4的介绍

    Java实现国产加密算法SM4的介绍
    国产SM4加密解密算法概念 SMS4算法是在国内广泛使用的WAPI无线网络标准中使用的加密算法,是一种32轮的迭代非平衡Feistel结构的分组加密算
  • java多线程实现同步锁卖票实战项目

    java多线程实现同步锁卖票实战项目
    同步概念与方法: 窗口类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Ticket implements Runnable{ int tickets=20;//总共20张票 @Override public
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计