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文件:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
cn.cnbuilder
sendmsg
0.0.1-SNAPSHOT
sendmsg
微信小程序订阅模板消息
UTF-8
zh_CN
1.8
3.6.0
org.springframework.boot
spring-boot-starter-web
com.github.binarywang
weixin-java-miniapp
${WxJava.version}
org.projectlombok
lombok
true
cn.hutool
hutool-all
4.1.21
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
org.springframework.boot
spring-boot-maven-plugin
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 Binary Wang
*/
@Configuration
@EnableConfigurationProperties(WxMaProperties.class)
public class WxMaConfiguration {
private WxMaProperties properties;
private static Map routers = Maps.newHashMap();
private static Map 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 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 Binary Wang
*/
@Data
@ConfigurationProperties(prefix = "wx.miniapp")
public class WxMaProperties {
private List 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 = 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://download.csdn.net/download/weixin_39984161/12089252
没有积分可以移步到:https://blog.cnbuilder.cn/archives/wxdymsg
鼓励作者写出更好的技术文档,就请我喝一瓶哇哈哈哈哈哈哈哈。。你们的赞助决定我更新的速度哦!
微信:
支付宝:
感谢一路支持我的人。。。。。
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)
欢迎关注猿码优创(联系小优优进内部群哦,新鲜技术优先更新):