微信小程序之订阅消息推送java开发

  • 2020 年 1 月 13 日
  • 筆記

2019年10月份微信发布了模板消息整改公告由模板消息更改为订阅消息:

具体公告地址:https://developers.weixin.qq.com/community/develop/doc/00008a8a7d8310b6bf4975b635a401?blockType=1 (悄悄告诉大家,大家没事可以看看评论老有意思了,骂声一片。龙哥:我14亿微信用你们教我怎么做产品吗????)

最可恨的是模板消息2020年1月10日下线。那也就是说从1月10日开始模板消息将不能使用。临近1月10日我出一篇关于订阅消息java开发的文章供大家参考。

先给大家看看最终效果:

一、开发前期资料准备:

1.1、登录微信小程序后台:https://mp.weixin.qq.com/

1.2、寻找Appid和AppSecret配置:路径:首页—》开发—》开发设置。

1.3、选择合适的模板消息进行推送:

1.4、找到模板id:

1.5、下载官方微信开发工具:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

二、小程序订阅消息代码开发:

2.1、创建官方小程序DEMO:

2.2、获取code 打开app.js —>13行—>添加console.log("这就是我的code呀:"+res.code)

代码:  console.log("这就是我的code呀:"+res.code)

2.3、添加一个按钮(可有可无)

2.3、给按钮添加执行函数:

,//记得添加逗号哦。    sendDYMsg: function(e) {      wx.requestSubscribeMessage({        tmplIds: ['ooaZWfK6liHpqDAcnR2hgObdQuh2JqQP2Z_UR6vvraU'],        success(res) {          console.log("可以给用户推送一条中奖通知了。。。");        }      })    }

2.4、获取推送权限:

输出可以给用户推送一条中奖通知了,就可以给用户推送一条消息。用户一直点击—可以一直推送哦~

真机调试页面展示:

三、服务端(java)代码开发:

3.1、老规矩先查看官网腾讯api文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html

3.2、给大家介绍一个关于微信开发的工具类(个人感觉非常优秀,可以自己去看看。):

git地址:https://github.com/Wechat-Group/WxJava

小程序文档地址:http://binary.ac.cn/weixin-java-miniapp-javadoc/

3.2、java工程介绍:

3.3、集成pom文件:

<?xml version="1.0" encoding="UTF-8"?>  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">      <modelVersion>4.0.0</modelVersion>      <parent>          <groupId>org.springframework.boot</groupId>          <artifactId>spring-boot-starter-parent</artifactId>          <version>2.2.2.RELEASE</version>          <relativePath/>      </parent>      <groupId>cn.cnbuilder</groupId>      <artifactId>sendmsg</artifactId>      <version>0.0.1-SNAPSHOT</version>      <name>sendmsg</name>      <description>微信小程序订阅模板消息</description>        <properties>          <!-- base setting -->          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>          <project.build.locales>zh_CN</project.build.locales>          <project.build.jdk>1.8</project.build.jdk>          <!-- lib versions -->          <WxJava.version>3.6.0</WxJava.version>      </properties>        <dependencies>          <dependency>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-starter-web</artifactId>          </dependency>            <!-- 小程序开发包-->          <dependency>              <groupId>com.github.binarywang</groupId>              <artifactId>weixin-java-miniapp</artifactId>              <version>${WxJava.version}</version>          </dependency>            <dependency>              <groupId>org.projectlombok</groupId>              <artifactId>lombok</artifactId>              <optional>true</optional>          </dependency>            <dependency>              <groupId>cn.hutool</groupId>              <artifactId>hutool-all</artifactId>              <version>4.1.21</version>          </dependency>            <dependency>              <groupId>io.springfox</groupId>              <artifactId>springfox-swagger2</artifactId>              <version>2.9.2</version>          </dependency>            <dependency>              <groupId>io.springfox</groupId>              <artifactId>springfox-swagger-ui</artifactId>              <version>2.9.2</version>          </dependency>        </dependencies>      <build>          <plugins>              <plugin>                  <groupId>org.springframework.boot</groupId>                  <artifactId>spring-boot-maven-plugin</artifactId>              </plugin>          </plugins>      </build>  </project>

3.4、增加yml文件:

application.yml  spring:    profiles:      active: dev #选择要用那个配置文件    application-dev.yml  #小程序配置信息  wx:    miniapp:      configs:          - appid: xxxxx            secret: xxxxx            token: xxxxxx            aesKey: xxxxxx            msgDataFormat: JSON  #项目端口号访问路径  server:    port: 12001

3.5、增加配置文件:

WxMaConfiguration文件:    package cn.cnbuilder.sendmsg.config;      import cn.binarywang.wx.miniapp.api.WxMaService;  import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;  import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;  import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;  import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;  import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;  import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;  import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;  import com.google.common.collect.Lists;  import com.google.common.collect.Maps;  import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;  import me.chanjar.weixin.common.error.WxErrorException;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.boot.context.properties.EnableConfigurationProperties;  import org.springframework.context.annotation.Configuration;    import javax.annotation.PostConstruct;  import java.io.File;  import java.util.List;  import java.util.Map;  import java.util.stream.Collectors;    /**   * @author <a href="https://github.com/binarywang">Binary Wang</a>   */  @Configuration  @EnableConfigurationProperties(WxMaProperties.class)  public class WxMaConfiguration {      private WxMaProperties properties;        private static Map<String, WxMaMessageRouter> routers = Maps.newHashMap();      private static Map<String, WxMaService> maServices = Maps.newHashMap();        @Autowired      public WxMaConfiguration(WxMaProperties properties) {          this.properties = properties;      }        public static WxMaService getMaService(String appid) {          WxMaService wxService = maServices.get(appid);          if (wxService == null) {              throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));          }            return wxService;      }        public static WxMaMessageRouter getRouter(String appid) {          return routers.get(appid);      }        @PostConstruct      public void init() {          List<WxMaProperties.Config> configs = this.properties.getConfigs();          if (configs == null) {              throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");          }            maServices = configs.stream()                  .map(a -> {                      WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();                      config.setAppid(a.getAppid());                      config.setSecret(a.getSecret());                      config.setToken(a.getToken());                      config.setAesKey(a.getAesKey());                      config.setMsgDataFormat(a.getMsgDataFormat());                        WxMaService service = new WxMaServiceImpl();                      service.setWxMaConfig(config);                      routers.put(a.getAppid(), this.newRouter(service));                      return service;                  }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));      }        private WxMaMessageRouter newRouter(WxMaService service) {          final WxMaMessageRouter router = new WxMaMessageRouter(service);          router                  .rule().handler(logHandler).next()                  .rule().async(false).content("模板").handler(templateMsgHandler).end()                  .rule().async(false).content("文本").handler(textHandler).end()                  .rule().async(false).content("图片").handler(picHandler).end()                  .rule().async(false).content("二维码").handler(qrcodeHandler).end();          return router;      }        private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) -> {          service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()                  .templateId("此处更换为自己的模板id")                  .formId("自己替换可用的formid")                  .data(Lists.newArrayList(                          new WxMaTemplateData("keyword1", "339208499", "#173177")))                  .toUser(wxMessage.getFromUser())                  .build());          return null;      };        private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {          System.out.println("收到消息:" + wxMessage.toString());          service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())                  .toUser(wxMessage.getFromUser()).build());          return null;      };        private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) -> {          service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")                  .toUser(wxMessage.getFromUser()).build());          return null;      };        private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {          try {              WxMediaUploadResult uploadResult = service.getMediaService()                      .uploadMedia("image", "png",                              ClassLoader.getSystemResourceAsStream("tmp.png"));              service.getMsgService().sendKefuMsg(                      WxMaKefuMessage                              .newImageBuilder()                              .mediaId(uploadResult.getMediaId())                              .toUser(wxMessage.getFromUser())                              .build());          } catch (WxErrorException e) {              e.printStackTrace();          }            return null;      };        private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {          try {              final File file = service.getQrcodeService().createQrcode("123", 430);              WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);              service.getMsgService().sendKefuMsg(                      WxMaKefuMessage                              .newImageBuilder()                              .mediaId(uploadResult.getMediaId())                              .toUser(wxMessage.getFromUser())                              .build());          } catch (WxErrorException e) {              e.printStackTrace();          }            return null;      };    }    WxMaProperties文件:    package cn.cnbuilder.sendmsg.config;    import java.util.List;    import org.springframework.boot.context.properties.ConfigurationProperties;    import lombok.Data;    /**   * @author <a href="https://github.com/binarywang">Binary Wang</a>   */  @Data  @ConfigurationProperties(prefix = "wx.miniapp")  public class WxMaProperties {        private List<Config> configs;        @Data      public static class Config {          /**           * 设置微信小程序的appid           */          private String appid;            /**           * 设置微信小程序的Secret           */          private String secret;            /**           * 设置微信小程序消息服务器配置的token           */          private String token;            /**           * 设置微信小程序消息服务器配置的EncodingAESKey           */          private String aesKey;            /**           * 消息格式,XML或者JSON           */          private String msgDataFormat;      }  }    swagger配置(可配可不配)    package cn.cnbuilder.sendmsg.config;      import io.swagger.annotations.ApiOperation;  import org.springframework.context.annotation.Bean;  import org.springframework.context.annotation.Configuration;  import springfox.documentation.builders.RequestHandlerSelectors;  import springfox.documentation.spi.DocumentationType;  import springfox.documentation.spring.web.plugins.Docket;  import springfox.documentation.swagger2.annotations.EnableSwagger2;    @Configuration  @EnableSwagger2  public class SwaggerConfig {      @Bean      public Docket swaggerSpringMvcPlugin() {          return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).build();      }    }

3.6、根据code获取openid:

code:(重点)只能使用一次,并且只有5分钟有效期。划线,期末考!!!!!

获取openid:

package cn.cnbuilder.sendmsg.controller;    import cn.binarywang.wx.miniapp.api.WxMaService;  import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;  import cn.binarywang.wx.miniapp.bean.WxMaSubscribeData;  import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;  import cn.cnbuilder.sendmsg.config.WxMaConfiguration;  import cn.hutool.json.JSONUtil;  import io.swagger.annotations.Api;  import io.swagger.annotations.ApiImplicitParam;  import io.swagger.annotations.ApiImplicitParams;  import io.swagger.annotations.ApiOperation;  import me.chanjar.weixin.common.error.WxErrorException;  import org.apache.commons.lang3.StringUtils;  import org.springframework.web.bind.annotation.*;    import java.util.ArrayList;    /**  * 微信小程序订阅消息推送接口  * create By KingYiFan on 2019/01/06  */  @Api("微信小程序订阅消息推送接口")  @RestController  @RequestMapping("/wx/msg/{appId}")  public class MsgController {       /**      * 根据code获取openid      * create By KingYiFan 2020/01/06      */     @ApiOperation(value = "根据code获取openid", notes = "根据code获取openid")     @ApiImplicitParams({             @ApiImplicitParam(name = "appId", value = "小程序appId", dataType = "string", paramType = "query"),             @ApiImplicitParam(name = "code", value = "用户code", dataType = "String", paramType = "query")})     @GetMapping("/getOpenidByCode")     public String login(@PathVariable String appId, String code) {         if (StringUtils.isBlank(code)) {             return "code都没有给俺,你哪啥换俺的openid啊?????";         }         try {             final WxMaService wxService = WxMaConfiguration.getMaService(appId);             //根据code获取openid             WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(code);             return session.getOpenid();         } catch (WxErrorException e) {             e.printStackTrace();         }         return "我猜你code肯定失效了........要不就是过期了呢.......您觉得呢???";     }  }	

测试:获取openid

用同样的code进行获取openid,腾讯会返回code已被使用。

3.6、最终环节进行小程序订阅消息推送

订阅消息传参和模板消息是不一样的,需要根据人家规则进行填写,加了正则校验了。

模板消息和订阅消息传参区别:

java代码    /**      * 微信小程序推送订阅消息      * create By KingYiFan on 2020/01/06      */     @ApiOperation(value = "微信小程序推送订阅消息", notes = "微信小程序推送订阅消息")     @ApiImplicitParams({             @ApiImplicitParam(name = "appId", value = "小程序appId", dataType = "string", paramType = "query"),             @ApiImplicitParam(name = "openId", value = "用户openId", dataType = "String", paramType = "query")})     @GetMapping(value = "/sendDYTemplateMessage")     @ResponseBody     public Object sendDYTemplateMessage(@PathVariable String appId, String openId) throws Exception {           WxMaSubscribeMessage subscribeMessage = new WxMaSubscribeMessage();           //跳转小程序页面路径         subscribeMessage.setPage("pages/index/index");         //模板消息id         subscribeMessage.setTemplateId("ooaZWfK6liHpqDAcnR2hgObdQuh2JqQP2Z_UR6vvraU");         //给谁推送 用户的openid (可以调用根据code换openid接口)         subscribeMessage.setToUser(openId);         //==========================================创建一个参数集合========================================================         ArrayList<WxMaSubscribeData> wxMaSubscribeData = new ArrayList<>();    //        订阅消息参数值内容限制说明  //              ---摘自微信小程序官方:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html  //        参数类别 	参数说明 	参数值限制 	   说明  //        thing.DATA 	事物 	20个以内字符 	可汉字、数字、字母或符号组合  //        number.DATA 	数字 	32位以内数字 	只能数字,可带小数  //        letter.DATA 	字母 	32位以内字母 	只能字母  //        symbol.DATA 	符号 	5位以内符号 	只能符号  //        character_string.DATA 	字符串 	32位以内数字、字母或符号 	可数字、字母或符号组合  //        time.DATA 	时间 	24小时制时间格式(支持+年月日) 	例如:15:01,或:2019年10月1日 15:01  //        date.DATA 	日期 	年月日格式(支持+24小时制时间) 	例如:2019年10月1日,或:2019年10月1日 15:01  //        amount.DATA 	金额 	1个币种符号+10位以内纯数字,可带小数,结尾可带“元” 	可带小数  //        phone_number.DATA 	电话 	17位以内,数字、符号 	电话号码,例:+86-0766-66888866  //        car_number.DATA 	车牌 	8位以内,第一位与最后一位可为汉字,其余为字母或数字 	车牌号码:粤A8Z888挂  //        name.DATA 	姓名 	10个以内纯汉字或20个以内纯字母或符号 	中文名10个汉字内;纯英文名20个字母内;中文和字母混合按中文名算,10个字内  //        phrase.DATA 	汉字 	5个以内汉字 	5个以内纯汉字,例如:配送中           //第一个内容: 奖品名称         WxMaSubscribeData wxMaSubscribeData1 = new WxMaSubscribeData();         wxMaSubscribeData1.setName("thing1");         wxMaSubscribeData1.setValue("充气娃娃豪华版");         //每个参数 存放到大集合中         wxMaSubscribeData.add(wxMaSubscribeData1);           // 第二个内容:用户昵称         WxMaSubscribeData wxMaSubscribeData2 = new WxMaSubscribeData();         wxMaSubscribeData2.setName("name6");         wxMaSubscribeData2.setValue("非苍老鸡不娶");         wxMaSubscribeData.add(wxMaSubscribeData2);           // 第三个内容:领取方式         WxMaSubscribeData wxMaSubscribeData3 = new WxMaSubscribeData();         wxMaSubscribeData3.setName("thing7");         wxMaSubscribeData3.setValue("请联系您的专属老鸡");         wxMaSubscribeData.add(wxMaSubscribeData3);           // 第四个内容:专属老师         WxMaSubscribeData wxMaSubscribeData4 = new WxMaSubscribeData();         wxMaSubscribeData4.setName("name3");         wxMaSubscribeData4.setValue("小泽玛利亚老鸡");         wxMaSubscribeData.add(wxMaSubscribeData4);           // 第五个内容:温馨提醒         WxMaSubscribeData wxMaSubscribeData5 = new WxMaSubscribeData();         wxMaSubscribeData5.setName("thing4");         wxMaSubscribeData5.setValue("小撸伤身,强撸灰飞烟灭~");         wxMaSubscribeData.add(wxMaSubscribeData5);           //把集合给大的data         subscribeMessage.setData(wxMaSubscribeData);         //=========================================封装参数集合完毕========================================================           try {             //获取微信小程序配置:             final WxMaService wxService = WxMaConfiguration.getMaService(appId);             //进行推送             wxService.getMsgService().sendSubscribeMsg(subscribeMessage);             return "推送成功";         } catch (Exception e) {             e.printStackTrace();         }         return "推送失败";     }

进行代码推送:

我收到一条消息,我还以为有那个女生给我聊天呢?说不定就告别单身狗了哈哈哈哈~~

竟然发现自己中奖了,吓得我感觉打开:卧槽(奈何自己没文化,一句卧槽行天下。) 好牛逼的奖项!!!

到现在微信小程序订阅消息推送就到此结束了,是不是超级简单那种。

给大家分享一个,只给用户提示一次,下次就不用提示就可以一直发送通知的方案: 微信设置了总是保持以上选择,不在询问按钮,只要把这对勾给点击上。下次点击通知函数,就不会给用户提示哦。 我给点击了按钮,到现在我都没找到从哪能开启这个提示。

终、、本文就是小程序之java推送订阅消息,有什么问题可以联系我。


本文用到的小程序代码和java代码下载路径: https://pan.baidu.com/s/1BE418TlGsICey5EUEYjzcQ 提取码: fagd

鼓励作者写出更好的技术文档,就请我喝一瓶哇哈哈哈哈哈哈哈。。你们的赞助


感谢一路支持我的人。。。。。    Love me and hold me  QQ:69673804(16年老号)  EMAIL:[email protected]  友链交换  如果有兴趣和本博客交换友链的话,请按照下面的格式在评论区进行评论,我会尽快添加上你的链接。

网站名称:猿码优创  网站地址:http://blog.cnbuilder.cn  网站描述:年少是你未醒的梦话,风华是燃烬的彼岸花。  网站Logo/头像: [头像地址](https://blog.cnbuilder.cn/upload/2018/7/avatar20180720144536200.jpg)

欢迎关注猿码优创(联系小优优进内部群哦,新鲜技术优先更新):