最近在开发小程序服务端代码,需要实现一个能够实现消息通知的接口业务,记录一下整个接口业务的开发过程。
先附上微信官方文档:订阅消息
消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。
订阅消息推送位置:服务通知
订阅消息下发条件:开发者通过一定的方式触发用户主动订阅
订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面
新版一次性订阅消息是一种无需用户在弹窗中主动订阅即可向用户下发消息的能力,用户的订阅方式为:
当用户在小程序中进行微信支付后,开发者可将微信支付订单号作为 code 向用户下发服务通知
开发者可在小程序中将触发服务的 button 组件的 open-type 的值设置为 liveActivity,当用户点击 button 后可获得 code ,后续可使用此 code 向用户下发服务通知
此下发方式由平台定义模版,开发者根据自身业务选择模版进行接入。
详见订阅消息接入 Beta开发指南文档。
一次性订阅消息用于解决用户使用小程序后,后续服务环节的通知问题。
开发者在小程序中调用 requestSubscribeMessage 接口后,将向用户展示弹窗,用户可打开自己想要接受的消息开关。用户订阅后,开发者可不限时间地下发一条对应的服务消息;每条消息可单独订阅或退订。
详见小程序订阅消息开发指南文档。
一次性订阅消息可满足小程序的大部分服务场景需求,但线下公共服务领域存在一次性订阅无法满足的场景,如航班延误,需根据航班实时动态来多次发送消息提醒。为便于服务,我们提供了长期性订阅消息,用户订阅一次后,开发者可长期下发多条消息。
目前长期性订阅消息仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。
详见小程序订阅消息开发指南文档。
同时长期订阅消息支持语音提醒与添加提醒能力。
设备订阅消息是一种特殊类型的订阅消息,它属于长期订阅消息类型,且需要完成设备接入才能使用。
设备订阅消息用于在设备触发某些需要人工介入的事件时(例如设备发生故障、设备耗材不足等),向用户发送消息通知。
详见设备订阅消息文档。
先附上微信官方文档:小程序订阅消息(用户通过弹窗订阅)开发指南
在微信公众平台中的小程序后台找到订阅消息功能模块
开通订阅消息:
由于长期性订阅消息,目前仅向政务民生、医疗、交通、金融、教育等线下公共服务开放,后期将逐步支持到其他线下公共服务业务。仅就线下公共服务这一点,长期性订阅消息就和大部分开发者无缘了。所以我们这里只能以使用一次性订阅消息为例。
登录 https://mp.weixin.qq.com 获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用。
选择先要的公共模板,也可以自己定制,但是公共模板已经可以满足我们绝大多数业务场景了
选择或者自己定制一个合适的模板,然后可以进行订阅模板的编辑,当然这都属于前端的工作了,
我们只需要在模板中拿到模板ID即可。
先附上微信官方文档:获取接口调用凭据
获取小程序全局唯一后台接口调用凭据,token有效期为7200s,开发者需要进行妥善保存。
如使用云开发,可通过云调用免维护 access_token 调用。
如使用云托管,也可以通过微信令牌/开放接口服务免维护 access_token 调用。
GET https://api.weixin.qq.com/cgi-bin/token
/**
* 获取接口调用凭证 access_token
*/
private static final String ACCESSTOKEN_GET = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&";
public WxAccessTokenVo getAccessToken() {
WxAccessTokenVo accessTokenVo = null;
/* 这个是redis缓存的:没有的话去掉*/
String wx_access_token = (String) redisTemplate.opsForValue().get("wx_access_token");
if (wx_access_token != null) {
accessTokenVo = new WxAccessTokenVo();
accessTokenVo.setAccess_token(wx_access_token);
return accessTokenVo;
}
String url = ACCESSTOKEN_GET + "appid=" + appId + "&secret=" + appSecret;
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
try {
accessTokenVo = JSON.parseObject(response, WxAccessTokenVo.class);
/* 存储在redis中*/
if (accessTokenVo.getExpire_in() > 0) {
redisTemplate.opsForValue().set("wx_access_token", accessTokenVo.getAccess_token(),
accessTokenVo.getExpire_in(), TimeUnit.SECONDS);
}
} catch (Exception e) {
logger.error("Json转换异常", e);
}
return accessTokenVo;
}
所以在获取到access_token的时候,把access_token存到数据库,或者存到本地缓存,并且还要记录当前时间,后面再用的时候先判断这个access_token有没有超过2个小时,如果超过2个小时的话,就要重新获取了。
附微信官方说明:获取 Access token
先附上微信官方文档:发送订阅消息
该接口用于发送订阅消息。
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN
这里有个需要特别注意的点,我们要给用户发送消息,就必须前端实现引导用户授权,因为用户不点击允许,你是没有办法给用户推送消息的。每一次授权只允许发送一条消息,所以如果你想尽量多的发送消息,就得尽量多的引导用户授权。
@Data
public class AddMessageSubscribeForm { // 前端模板需要的参数
// 小程序的登录凭证code
private String code;
//订阅消息模版id TODO
private String template_id;
//默认跳到小程序首页 TODO
private String page = "pages/index/index";
//推送文字
private Map<String, TemplateData> data;
// 跳转小程序的类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
private String miniprogram_state;
// 进入小程序查看的语言类型:支持zh_CN、en_US、zh_HK、zh_TW,默认为zh_CN
private String lang;
}
@Data
public class WXMssVO {
//用户openid
private String touser;
//订阅消息模版id
private String template_id;
//默认跳到小程序首页 TODO
private String page = "pages/index/index";
//推送内容
private Map<String, TemplateData> data;
// 跳转小程序的类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
private String miniprogram_state;
// 进入小程序查看的语言类型:支持zh_CN、en_US、zh_HK、zh_TW,默认为zh_CN
private String lang;
}
@AllArgsConstructor
@Data
public class TemplateData {
/**
* 消息通知的内容
*/
private String value;
}
/**
* 获取微信用户唯一标识OpenID
*/
private static final String CODE2SESSION_GET = "https://api.weixin.qq.com/sns/jscode2session?";
/**
* code2sessino接口
* @param code
* @return
*/
public WxCode2SessionVo getCode2Session(String code) {
String url = CODE2SESSION_GET + "appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
WxCode2SessionVo code2SessionVo = null;
try {
code2SessionVo = JSON.parseObject(response, WxCode2SessionVo.class);
} catch (Exception e) {
logger.error("Json转换异常", e);
}
return code2SessionVo;
}
/**
* 给用户发送通知
* TODO 参数设置
* @param info
* @return
*/
/**
* 给用户发送消息
*/
public static final String SEND_INFO_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
public String pushMessage(AddMessageSubscribeForm info){
RestTemplate restTemplate = new RestTemplate();
String url = SEND_INFO_URL + getAccessToken().getAccess_token();
// 通过 appId+appsecret+code三个参数获取微信用户信息 获取用户的openid
WxCode2SessionVo code2Session = this.getCode2Session(info.getCode());
if (code2Session == null || (code2Session.getErrcode() != null && code2Session.getErrcode() != 0)) {
return "获取用户微信信息失败:" + code2Session.toString();
}
String openid = code2Session.getOpenid();
// 拼接推送的模板
WXMssVO wxMssVO = new WXMssVO();
wxMssVO.setTouser(openid); // 用户的openId
wxMssVO.setTemplate_id(info.getTemplate_id()); //订阅消息模板id
wxMssVO.setLang(info.getLang()); //语言类型
wxMssVO.setMiniprogram_state(info.getMiniprogram_state()); //跳转小程序类型
//TODO:指定跳转的页面
wxMssVO.setPage(info.getPage());
// TODO: 推送的内容
Map<String, TemplateData> map = new HashMap<>();
map.put("msg", new TemplateData("发消息了"));
wxMssVO.setData(map);
// 发送
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, wxMssVO, String.class);
return responseEntity.getBody();
}
到这里我们就可以完整的实现Java发送小程序消息的功能了。
以上就是今天要分享给大家的内容,本文简单的记录了一下小程序发送通知的开发,很多内容其实都来自官方文档,欢迎大家批评指正、共同进步!