小程序 订阅消息 java 后台 前端WX
泛域名ssl证书 239元1年送1个月、单域名39元1年,Sectigo(原Comodo证书)全球可信证书,强大的兼容性,高度安全性,如有问题7天内可退、可开发票
加微信VX 18718058521 备注SSL证书
【腾讯云】2核2G4M云服务器新老同享99元/年,续费同价
简介
微信小程序发送消息推送到用户微信上
基础流程
用户登录 :获取微信提供的openid
开发者去微信公众平台 申请模板:获得模板id
授权消息推送:在小程序中调用 wx.requestSubscribeMessage方法
成功后将数据保存到后台 消息推送表 中
在需要发送消息推送时:查询 消息推送表 如果有,使用 消息推送表 的数据调用接口 subscribeMessage.send
细节流程
1.1用户微信登录(缓存opid)
1.2用户普通登录(无opid)
2 消息推送申请
2.1用户授权
2.1.1无opid(弹框要求 微信登录(类似第一步)
2.1.2有opid(继续
2.2获得了授权的模板id和opid
3传输到后台,后台存储到消息推送表,参数:模板id,opid,用户名称,身份证。默认参数:是否发送为N,创建时间,主键 ,发送时间为空
4后台定时器,查询到要发送的用户时,查询消息推送表,修改发送状态为Y,更新发送时间,然后发送微信小程序消息推送
代码
1用户微信小程序登录
wx.login({ success: res => { console.log(res); // 发送 res.code 到后台换取 openId, sessionKey, unionId request.post('后台用小程序id和密钥获取Openid的接口.do', { code: res.code }).then((res) => { console.log(res); let result = JSON.parse(res.result); wx.setStorageSync('openid',result.openid)//缓存openid that.setData({ sessionKey: result.session_key }) }); } })
2 小程序消息推送授权
let templateId = '模板id'; wx.requestSubscribeMessage({ tmplIds: [templateId], success (res) { console.log(res); if(res.模板id =='reject'){//被拒绝 }else{//同意 //获取缓存的openid,可能是之前用户登录时存放的 let opid = wx.getStorageSync('openid'); //如果有OPID,直接发送 if(opid){ //执行保存到后台的操作 that.saveSubMssage(opid,templateId); }else{ wx.showToast({ title: '需要关联微信账号', icon: 'success', duration: 2000 }) //和登录授权一样 wx.login({ success: res => { console.log(res); // 发送 res.code 到后台换取 openId, sessionKey, unionId request.post('后台换取用户id的接口', { code: res.code }).then((res) => { //得到openid let result = JSON.parse(res.result); wx.setStorageSync('openid',result.openid) opid=res.openid; //执行保存到后台的操作 that.saveSubMssage(opid,templateId); }); } }) } } }, error(res){ console.log(res); wx.showToast({ title: '授权出现错误', icon: 'none', duration: 2000 }) } })
saveSubMssage(openid,tmplIds){ let that = this; request.Post('后台保存用户同意消息推送的接口.do', { openId: openid,//用户openid templateId: tmplIds,//模板id userName: encodeURI(that.data.userName),//中文乱码处理 idCard: that.data.idCard//身份证 }).then((res) => { console.log(res); wx.showToast({ title: '授权成功', icon: 'success', duration: 2000 }) //退出页面 setTimeout(function() { wx.navigateBack({ changed: true }); }, 2000); });
3 后台保存用户同意消息推送的接口
@RequestMapping(value="/SaveMessageAuthority.do" ,produces = "application/json;charset=UTF-8") @ResponseBody public String SaveMessageAuthority(String openId,String templateId,String userName ,String idCard) throws Exception { try { WeChatMessageAuthorityPO weChatMessageAuthority = new WeChatMessageAuthorityPO(); weChatMessageAuthority.setOpenId(openId); weChatMessageAuthority.setTemplateId(templateId); weChatMessageAuthority.setIdCard(idCard); // String temp = request.getParameter("studentName"); if(StringUtils.isNotEmpty(userName)){ userName = java.net.URLDecoder.decode(userName,"UTF-8"); weChatMessageAuthority.setUserName(userName); } weChatMessageAuthority.setCreateDate(new Date()); weChatMessageAuthority.setIsSend(BaseStaticParameter.NO); iWxMassageAuthorityService.saveOrUpdate(weChatMessageAuthority); }catch (Exception e){ e.printStackTrace(); return "false"; } return "true"; }
4 后台发送推送信息
public static boolean sendNearRemindMessage(String openId,String serveName,String windowName,String lineNumber,String waitNumber,String msg) throws Exception { WxMaSubscribeMessage subscribeMessage = new WxMaSubscribeMessage(); //跳转小程序页面路径 subscribeMessage.setPage("pages/index/index"); //模板消息id subscribeMessage.setTemplateId(WxMaConfiguration.templateId); //给谁推送 用户的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(serveName); wxMaSubscribeData.add(wxMaSubscribeData1); WxMaSubscribeData wxMaSubscribeData2 = new WxMaSubscribeData(); wxMaSubscribeData2.setName("thing6"); wxMaSubscribeData2.setValue(windowName); wxMaSubscribeData.add(wxMaSubscribeData2); WxMaSubscribeData wxMaSubscribeData3 = new WxMaSubscribeData(); wxMaSubscribeData3.setName("character_string2"); wxMaSubscribeData3.setValue(lineNumber); wxMaSubscribeData.add(wxMaSubscribeData3); WxMaSubscribeData wxMaSubscribeData4 = new WxMaSubscribeData(); wxMaSubscribeData4.setName("number3"); wxMaSubscribeData4.setValue(waitNumber); wxMaSubscribeData.add(wxMaSubscribeData4); WxMaSubscribeData wxMaSubscribeData5 = new WxMaSubscribeData(); wxMaSubscribeData5.setName("thing5"); wxMaSubscribeData5.setValue(msg);//"快到您了,请关注窗口和叫号情况" wxMaSubscribeData.add(wxMaSubscribeData5); //把集合给大的data subscribeMessage.setData(wxMaSubscribeData); //=========================================封装参数集合完毕======================================================== try { System.out.println(JsonUtil.toJSONString(subscribeMessage)); //获取微信小程序配置: final WxMaService wxService = WxMaConfiguration.getMaService(WxMaConfiguration.appid); //进行推送 wxService.getMsgService().sendSubscribeMsg(subscribeMessage); return true; } catch (Exception e) { e.printStackTrace(); System.out.println(e.toString()); } return false; }
5 微信maven(微信调用方式可选)
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-miniapp</artifactId> <version>3.6.0</version> </dependency>
6 WxMaConfiguration
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.WxMaMessage; 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 cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage; 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 me.chanjar.weixin.common.session.WxSessionManager; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import java.io.File; import java.util.Map; /** * create by zhaojiong * 22-8-16 */ @Configuration public class WxMaConfiguration { //叫号 public final static String jh_templateId = " 消息模板id"; //排队 public final static String pd_templateId = "消息模板id"; public final static String appid = "按情况填写"; public final static String secret = "按情况填写"; public final static String token = "按情况填写"; public final static String aesKey = "按情况填写"; public final static String msgDataFormat = "JSON"; // private static Map<String, WxMaMessageRouter> routers = Maps.newHashMap(); private static Map<String, WxMaService> maServices = Maps.newHashMap(); // // 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() { WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); config.setAppid(appid); config.setSecret(secret); config.setToken(token); config.setAesKey(aesKey); config.setMsgDataFormat(msgDataFormat); WxMaService service = new WxMaServiceImpl(); service.setWxMaConfig(config); routers.put(appid, this.newRouter(service)); maServices.put(appid, service); } // 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 = new WxMaMessageHandler() { @Override public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) throws WxErrorException { 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 = new WxMaMessageHandler() { @Override public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) throws WxErrorException { System.out.println("收到消息:" + wxMessage.toString()); service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson()) .toUser(wxMessage.getFromUser()).build()); return null; } }; private final WxMaMessageHandler textHandler = new WxMaMessageHandler() { @Override public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) throws WxErrorException { service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息") .toUser(wxMessage.getFromUser()).build()); return null; } }; private final WxMaMessageHandler picHandler = new WxMaMessageHandler() { @Override public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) throws WxErrorException { 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 = new WxMaMessageHandler() { @Override public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) throws WxErrorException { 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; } }; }