推送消息业务逻辑:
首先获取access token,再设置用户,消息内容等参数,请求接口,并解析返回的错误码。微信统一消息服务接口信息如下:
Access token获取说明:Token每天最多获取200次,一次2小时失效,所以不能每次调用推送消息方法时都通过接口获取access token。设计专门获取token的方法,把token保存到redis,每两个小时刷新redis库中的token。业务程序获取token在redis中获取。
Access token获取接口参考资料:
补充说明:
如果微信已有的模板不满足业务需求则需要申请模板。
方法:登录微信公众号,在模板库中添加模板。注意需要7-15天的审核期。
package com.troy.emergency.rescue.service; import com.troy.emergency.rescue.dto.WeiXinMessageDTO; import net.sf.json.JSONObject; /** * 创建者: apple * 创建时间:2019/10/14. * 功能模块: 微信小程序的服务接口 */ public interface WeixinService { /** * 根据微信小程序的appId和密钥获取token */ public void getTokenAndSetRedis() throws Exception; /** * 从redis中获取accessToken */ public String getAccessTokenFromRedis() throws Exception; /** * 统一消息服务 */ public void senMessage( WeiXinMessageDTO weiXinMessageDTO) throws Exception; }
package com.troy.emergency.rescue.service.impl; import com.troy.emergency.rescue.dto.WeiXinMessageDTO; import com.troy.emergency.rescue.service.WeixinService; import com.troy.emergency.rescue.utils.HttpUtils; import com.troy.keeper.common.core.base.service.RedisService; import net.sf.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.HashMap; import java.util.Map; @Service @Transactional public class WeixinServiceImpl implements WeixinService { @Autowired private RedisService redisService; private String accessTokenKey = "accessToken"; //获取微信小程序token的url @Value("${application.tokenUrl}") private String tokenUrl; //微信小程序的appid @Value("${application.appId}") private String appId; //微信小程序密钥 @Value("${application.appSecret}") private String appSecret; //微信公众号消息模板id @Value("${application.templateId}") private String templateId ; //公众号的appid @Value("${application.mpAppId}") private String mpAppId; //微信统一消息服务url @Value("${application.sendMessageUrl}") private String sendMessageUrl; /** * 根据微信小程序的appId和密钥获取token--已测试 */ public void getTokenAndSetRedis() throws Exception{ Map<String, String> params = new HashMap<>(); params.put("grant_type", "client_credential"); params.put("appid", appId); params.put("secret", appSecret); String jstoken = HttpUtils.sendGet( tokenUrl, params); String accessToken = JSONObject.fromObject(jstoken).getString( "access_token"); // 获取到token并赋值保存 redisService.set(accessTokenKey,accessToken); } public String getAccessTokenFromRedis() throws Exception{ String accessToken = redisService.get(accessTokenKey); if(accessToken == null || "".equals(accessToken)){ this.getTokenAndSetRedis(); } return redisService.get(accessTokenKey); } /** * 向特定的用户推送消息--未测试 */ public void senMessage( WeiXinMessageDTO weiXinMessageDTO) throws Exception{ String token = this.getAccessTokenFromRedis(); JSONObject result = new JSONObject(); JSONObject obj = new JSONObject(); JSONObject mp_template_msg = new JSONObject(); JSONObject data = setMessageData(weiXinMessageDTO); //消息不提供小程序跳转和url跳转,需要测试设置为空是否可以 String path = sendMessageUrl + token; obj.put("touser", weiXinMessageDTO.getUserOpenId()); mp_template_msg.put("appid",mpAppId); mp_template_msg.put("template_id", templateId); mp_template_msg.put("url",null); mp_template_msg.put("miniprogram", null); mp_template_msg.put("data", data); obj.put("mp_template_msg", mp_template_msg); result = HttpUtils.post(path, obj); //解析微信的错误码 Object errCode = result.get("errcode"); Object errMsg = result.get("errmsg"); if(errCode == null || !errCode.toString().equals("0")){ throw new RuntimeException(errMsg.toString()); } } /** * 设置消息的Json内容 * @param dto * @return */ private JSONObject setMessageData(WeiXinMessageDTO dto){ JSONObject data = new JSONObject(); String color = "#173177"; String firstValue = "您好,您有新的待办任务需要处理!"; String valueKey = "value"; String colorKey = "color"; String remarkValue = "请尽快登录系统进行处理!"; //信息的开始 JSONObject first = new JSONObject(); first.put(valueKey,firstValue); first.put(colorKey,color); data.put("first",first); //流程编号 JSONObject keyword1 = new JSONObject(); keyword1.put(valueKey,dto.getProcessNo()); keyword1.put(colorKey,color); data.put("keyword1",keyword1); //流程名称 JSONObject keyword2 = new JSONObject(); keyword2.put(valueKey,dto.getProcessName()); keyword2.put(colorKey,color); data.put("keyword2",keyword2); //流程标题 JSONObject keyword3 = new JSONObject(); keyword3.put(valueKey,dto.getProcessType()); keyword3.put(colorKey,color); data.put("keyword3",keyword3); //申请人 JSONObject keyword4 = new JSONObject(); keyword4.put(valueKey,dto.getApplicant()); keyword4.put(colorKey,color); data.put("keyword4",keyword4); //申请时间 JSONObject keyword5 = new JSONObject(); keyword5.put(valueKey,dto.getAppliedDate()); keyword5.put(colorKey,color); data.put("keyword5",keyword5); //信息结束语 JSONObject remark = new JSONObject(); remark.put(valueKey,remarkValue); remark.put(colorKey,color); data.put("remark",remark); return data; }
package com.troy.emergency.rescue.utils.schedule; import com.troy.emergency.rescue.service.WeixinService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; /** * 创建者: apple * 创建时间:2019/10/14. * 功能模块:定时任务-每两个小时刷新一次accesstoken */ @Component public class WeiXinQtzJob { @Autowired private WeixinService weixinService; @Scheduled(cron = "0 0 0/2 * * ?") //每两个小时执行一次 public void getTokenUpdateRedis(){ try { System.out.println("定时任务getTokenUpdateRedis开始" + new Date()); weixinService.getTokenAndSetRedis(); System.out.println("定时任务getTokenUpdateRedis结束"+ new Date()); }catch (Exception e){ e.printStackTrace(); } } }
}