简介
微信小程序发送消息推送到用户微信上
基础流程
- 用户登录 :获取微信提供的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)//缓存openidthat.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) => {
//得到openidlet 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,//用户openidtemplateId: tmplIds,//模板iduserName: 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")@ResponseBodypublic 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");//模板消息idsubscribeMessage.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);//把集合给大的datasubscribeMessage.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);}
//
//@PostConstructpublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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;}};}