微信模板消息

任务描述

原本的消息推送分为两个类型,文本消息和图文消息。现在要将其中一部分修改为图文消息。参考: 微信文档 CSDN博客

准备工作

首先应该去微信的官方客服购买消息模板,购买以后会获得template_id_short,即模板库中模板的编号,有“TM**”和“OPENTMTM**”等形式。并且会有对应的模板样式,如下:

{{first.DATA}}
订单号:{{keyword1.DATA}}
商品名称:{{keyword2.DATA}}
收件人姓名:{{keyword3.DATA}}
收件人电话:{{keyword4.DATA}}
收件人地址:{{keyword5.DATA}}
{{remark.DATA}}
您提交的发货订单已发货
订单号:5244030005646
商品名称:某商品
收件人姓名:陈璐
收件人电话:13522211111
收件人地址:广东省 广州市 天河区 科韵北路112号
如有疑问,请尽快联系我们。

注意事项

  1. 模板中的关键字,必须与模板保持一致,否则模板并不会识别。如:{{first.DATA}},最后保存JSON 的时候,名字应为{"first",first}. 2.申请模板之后,模板的存储数量有限,所以需要写方法,将已经获取的模板id(template_id)存放在缓存或者数据库中,下一次以同样的appid和template_id_short去获取template_id时,先判断是否已经在缓存或数据库中存在,若不存在,再去获取。 3.微信中可以存放的模板id数量有限,所以需要方法去判断之前是否申请过模板id,保证模板id不会重复被申请。 4.如果模板出现错误,应该删除更新。 5.如果出现错误,去官方文档中可以查询到错误原因。 /暂时想到的就这么多,如果还有其他,欢迎补充/

###1. 获取access_token的方法

@Component
public class WxCacheManager extends CacheManager<String,Object> {

    @Autowired
    private JedisManager manager;

    @Override
    public int getDbIndex() {
        return IConstants.DB_INDEX_VARIABLE;
    }

    @Override
    public JedisManager getJedisManager() {
        return manager;
    }

    /**
     * 获取指定公众号的access_token
     * @param appid 公众号的appid
     * @return
     */
    public String getTokenFromCache(String appid){
        String access_token = (String)this.getByKey("access_token_" + appid);
        if(Commons.isNull(access_token)){
            String appsecret = WeixinUtil.getAppsecret(appid);
            AccessToken accessToken = WeixinUtil.getAccessToken(appid, appsecret);
            access_token = accessToken.getToken();
            if(!Commons.isNull(access_token)){
                this.setKeyValue("access_token_" + appid,access_token,7000);
            }
        }
        return access_token;
    }

    /**
     * 获得指定公众号的jsApiTicket
     * @param appid 公众号的appid
     * @return
     */
    public String getJsApiTicketFromCache(String appid){
        String jsApiTicket = (String)this.getByKey("jsApiTicket_" + appid);
        if(Commons.isNull(jsApiTicket)){
            JsApiTicket jsTicket = WeixinUtil.getJsTicket(getTokenFromCache(appid));
            jsApiTicket = jsTicket.getTicket();
            if(!Commons.isNull(jsApiTicket)){
                this.setKeyValue("jsApiTicket_" + appid,jsApiTicket,7000);
            }
        }
        return jsApiTicket;
    }

    /**
     * 从缓存中查询微信用户信息
     * @param appid
     * @param openid
     * @return
     */
    public UserInfo getUserInfoFromCache(String appid, String openid){
        UserInfo userinfo = (UserInfo)super.getByKey("userinfo_" + appid + "_" + openid);
        if(Commons.isNull(userinfo)){
            userinfo = WeixinUtil.getUserInfoByOpenid(this.getTokenFromCache(appid),openid);
            if(userinfo!=null){
                super.setKeyValue("userinfo_" + appid + "_" + openid,userinfo,3600);
            }
        }
        return userinfo;
    }

    /**
     * 将微信用户信息添加到缓存
     * @param userinfo
     * @param appid
     */
    public void setUserInfoCache(UserInfo userinfo, String appid){
        if(!Commons.isNull(userinfo) && !Commons.isNull(userinfo.getOpenid()) && !Commons.isNull(appid)){
            this.setKeyValue("userinfo_" + appid + "_" + userinfo.getOpenid(),userinfo,3600);
        }
    }

    /**
     * 从缓存中获取指定公众号信息
     * @param appid
     * @return
     */
    public Wbapp getWbappFromCache(String appid){
        return null;
        /*return (Wbapp)this.getByKey("wbapp_" + appid);*/
    }

    /**
     * 将公众号信息添加到缓存
     * @param wbapp
     */
    public void setWbappCache(Wbapp wbapp){
        if(!Commons.isNull(wbapp)){
            this.setKeyValue("wbapp_" + wbapp.getAppid(),wbapp,7000);
        }
    }

    /**
     * 从缓存中查询用户基本信息
     * @param id
     * @return
     */
    public WbUser getWbUserFromCache(Long id){
        return null;
        //return (WbUser)super.getByKey(WbUser.class.getCanonicalName() + id);
    }

    /**
     * 将用户基本信息添加到缓存
     * @param wbuser
     */
    public void setWbUserCache(WbUser wbuser){
        if(!Commons.isNull(wbuser)){
            this.setKeyValue(WbUser.class.getCanonicalName() + wbuser.getId(),wbuser,7000);
        }
    }

    public Long getSyncTimesFromCache(String appid){
        return (Long)this.getByKey("wzc_synctimes_" + appid);
    }

    public void setSyncTimesCache(String appid,Long time){
        if(!Commons.isNull(appid) && !Commons.isNull(time)){
            this.setKeyValue("wzc_synctimes_" + appid,time,24*60*60);
        }
    }


}

2. 模板消息类

public class WxTemplate {
	private String template_id;
	private String touser;
	private String url;
	private String topcolor;
	private Map<String,TemplateData> data;
	
	public String getTemplate_id() {
		return template_id;
	}
	public void setTemplate_id(String template_id) {
		this.template_id = template_id;
	}
	public String getTouser() {
		return touser;
	}
	public void setTouser(String touser) {
		this.touser = touser;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getTopcolor() {
		return topcolor;
	}
	public void setTopcolor(String topcolor) {
		this.topcolor = topcolor;
	}
	public Map<String,TemplateData> getData() {
		return data;
	}
	public void setData(Map<String,TemplateData> data) {
		this.data = data;
	}
}

3.设置每条模板消息信息的类

public class TemplateData {
	private String value;
	private String color;
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	
}

4.模板消息使用方法部分

//消息类型
@Service
public class MessageUtil {

	/**
	 * 发送模板消息
	 * @param appid
	 * @param openid
	 * @param template_id  模板id
	 * @param data 模板消息内容
	 * @param url  URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击
	 */
	public static void sendTemplateMessage(String appid, String openid, String template_id, Map<String,TemplateData> data, String url, String template_id_short){
		WxCacheManager wxCacheManager = SpringContextHolder.getBean(WxCacheManager.class);
		WxTemplate wxTemplate = new WxTemplate();
		wxTemplate.setTouser(openid);
		wxTemplate.setTemplate_id(template_id);
		//微信端页面是否有跳转,通过判断跳转链接是否为空来决定,所以当url为空时,将链接设置为""
		if (url==null){
			wxTemplate.setUrl("");
		}else {
			wxTemplate.setUrl(url);
		}
		wxTemplate.setData(data);
		String access_token = wxCacheManager.getTokenFromCache(appid);
		String request_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token;
		JSONObject returnObj = com.xiangshi.wzc.wx.util.MessageUtil.httpRequest(request_url, "POST", JSONObject.fromObject(wxTemplate).toString());
		if(returnObj.containsKey("errcode") && "40037".equals(returnObj.getString("errcode"))) {
			ActiveMQQueue dest = new ActiveMQQueue("Wzc_template_List");
			long delayTime = TimingConstants.DELAY_TIME_TWO_SECOND;
			Map<String,Object> map = new HashMap<String, Object>();
			map.put("appid", appid);
			map.put("openid", openid);
			map.put("template_id", template_id);
			map.put("data", data);
			map.put("url", url);
			map.put("template_id_short", template_id_short);
			JSONObject jsonObject = JSONObject.fromObject(map);
			SendMessage sendMessage = SpringContextHolder.getBean(SendMessage.class);
			sendMessage.sendSingle(jsonObject.toString(), dest, delayTime);
		}
	}

	/**
	 * 获取模板id
	 * @param appid
	 * @param template_id_short  模板库中模板的编号
     * @return
     */
	public static String applyTemplateID(String appid,String template_id_short){
		WxCacheManager wxCacheManager = SpringContextHolder.getBean(WxCacheManager.class);
		String access_token = wxCacheManager.getTokenFromCache(appid);
		String request_url = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=" + access_token;
		Map<String,String> map = new HashMap<String,String>();
		map.put("template_id_short",template_id_short);
		JSONObject resultObj = com.xiangshi.wzc.wx.util.MessageUtil.httpRequest(request_url, "POST", JSONObject.fromObject(map).toString());
		if (resultObj.containsValue("ok")){
			return String.valueOf(resultObj.get("template_id"));
		}else {
			return null;
		}
	}

	/**
	 * 获取模板列表
	 * @param appid
	 * @return
     */
	public static JSONArray getTemplateList(String appid) {
		WxCacheManager wxCacheManager = SpringContextHolder.getBean(WxCacheManager.class);
		String access_token = wxCacheManager.getTokenFromCache(appid);
		String request_url = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=" + access_token;
		JSONObject resultObj = com.xiangshi.wzc.wx.util.MessageUtil.httpRequest(request_url, "GET", null);
		if(resultObj.containsKey("template_list")) {
			return resultObj.getJSONArray("template_list");
		} else {
			return null;
		}
	}

	/**
	 * 根据模板id删除模板
	 * @param appid
	 * @param template_id
     */
	public static void deleteTemplateById(String appid, String template_id) {
		WxCacheManager wxCacheManager = SpringContextHolder.getBean(WxCacheManager.class);
		String access_token = wxCacheManager.getTokenFromCache(appid);
		String request_url = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token=" + access_token;
		Map<String, String> map = new HashMap<String, String>();
		map.put("template_id", template_id);
		com.xiangshi.wzc.wx.util.MessageUtil.httpRequest(request_url, "POST", JSONObject.fromObject(map).toString());
	}

	public static void main(String[] args){

	}
}

5.获取模板id的时候,判断模板是否已经存在,更新模板id

@Service
public class MessageWxTemplateServiceImpl extends BaseServiceImpl<MessageWxTemplate> implements MessageWxTemplateService {

    @Autowired
    private MessageWxTemplateDao messageWxTemplateDao;
    @Autowired
    private WxCacheManager cacheManager;

    private static final String CACHE_PREFIX = "WXTemplateID_";

    private static final Integer TIME_ONE_DAY_SECOND = 24 * 60 * 60;

    @Override
    protected BaseDao<MessageWxTemplate> getBaseDao() {
        return messageWxTemplateDao;
    }

    @Override
    public String getApplyTemplateID(String appid, String template_id_short){
        String templateid = (String) cacheManager.getByKey(CACHE_PREFIX+appid+"_"+template_id_short);
        if(templateid==null){
            MessageWxTemplate messageWxTemplate = new MessageWxTemplate();
            messageWxTemplate.setTemplate_id_short(template_id_short);
            messageWxTemplate.setAppid(appid);
            messageWxTemplate = messageWxTemplateDao.selectOne(messageWxTemplate);
            if(messageWxTemplate==null){
                templateid = MessageUtil.applyTemplateID(appid,template_id_short);
                messageWxTemplate = new MessageWxTemplate();
                messageWxTemplate.setTemplate_id_short(template_id_short);
                messageWxTemplate.setAppid(appid);
                messageWxTemplate.setTemplate_id(templateid);
                this.insert(messageWxTemplate);
                return templateid;
            } else {
                setTemplateCache(messageWxTemplate);
                return messageWxTemplate.getTemplate_id();
            }
        } else {
            return templateid;
        }
    }

    @Override
    public String updateTemplateID(String appid, String template_id, String template_id_short) {
        //1-1.获取模板编号在数据库中对应的信息
        MessageWxTemplate query = new MessageWxTemplate();
        query = new MessageWxTemplate();
        query.setAppid(appid);
        query.setTemplate_id_short(template_id_short);
        MessageWxTemplate template = messageWxTemplateDao.selectOne(query);
        if (!Commons.isNull(template)) {
            //1-2.清除缓存中数据
            delTemplateCache(appid, template_id_short);
            //1-3.将此错误模板信息从数据库删除
            messageWxTemplateDao.deleteById(template.getId());
        }
        //1-4.获取数据库中平台所有的模板信息
        query = new MessageWxTemplate();
        query.setAppid(appid);
        List<MessageWxTemplate> templates = messageWxTemplateDao.selectList(query);
        //2.获取微信中平台所有的模板信息
        JSONArray templatesWX = MessageUtil.getTemplateList(appid);
        //3.比对,将错误的模板删掉(删掉的是所有的错误模板)
        boolean next = true;
        if (!Commons.isNull(templates) && templates.size() > 0
                && !Commons.isNull(templatesWX) && templatesWX.size() > 0 ) {
            for (int i = 0; i < templatesWX.size(); i++) {
                JSONObject templateInfo = templatesWX.getJSONObject(i);
                //表示此模板是否需要删除,默认需要删除
                boolean b = true;
                if (templateInfo.containsKey("template_id")) {
                    //3-1.循环比较微信中的模板是否也在数据库中
                    for (MessageWxTemplate mwt : templates) {
                        //3-1-1.此模板存在,不需要删除
                        if (templateInfo.getString("template_id").equals(mwt.getTemplate_id())) {
                            b = true;
                            break;
                        }
                    }
                    if (!b) {
                        //3-1-2.此模板存在,需要删除
                        MessageUtil.deleteTemplateById(appid, templateInfo.getString("template_id"));
                    }
                }
            }
        } else if ((Commons.isNull(templates) || templates.size() == 0)
                && !Commons.isNull(templatesWX) && templatesWX.size() > 0 ) {
            for (int i = 0; i < templatesWX.size(); i++) {
                JSONObject templateInfo = templatesWX.getJSONObject(i);
                if (templateInfo.containsKey("template_id")) {
                    MessageUtil.deleteTemplateById(appid, templateInfo.getString("template_id"));
                }
            }
        }
        //5.根据template_id_short获取新的template_id
        String new_template_id = MessageUtil.applyTemplateID(appid, template_id_short);
        if (Commons.isNull(new_template_id)) {
            return null;
        }
        return new_template_id;
    }

    @Override
    public void insert(MessageWxTemplate entity) {
        if(entity==null||entity.getTemplate_id_short()==null||entity.getAppid()==null||entity.getTemplate_id()==null){
            return;
        }
        super.insert(entity);
        setTemplateCache(entity);
    }

    private void setTemplateCache(MessageWxTemplate entity){
        cacheManager.setKeyValue(CACHE_PREFIX+entity.getAppid()+"_"+entity.getTemplate_id_short(),
                entity.getTemplate_id(),
                TIME_ONE_DAY_SECOND);
    }

    private void delTemplateCache(String appid, String template_id_short){
        cacheManager.deleteByKey(CACHE_PREFIX+appid+"_"+template_id_short);
    }
}

6.发送模板消息

//获取模板id
                        String template_id = messageWxTemplateService.getApplyTemplateID(appid,"OPENTM*********");
                        if (template_id!=null||template_id!="") {
                            messages.setMsgtype("模板通知");
                            //修改为模板消息
                            //{{first.DATA}}
                            TemplateData first = new TemplateData();
                            first.setValue("您提交的发货订单已发货");
                            first.setColor("#173177 ");
                            //订单内容:{{keyword1.DATA}}
                            TemplateData keyword1 = new TemplateData();
                            keyword1.setValue(order.getProname());
                            keyword1.setColor("#173177 ");
                            //物流服务:{{keyword2.DATA}}
                            TemplateData keyword2 = new TemplateData();
                            keyword2.setValue(deliverOrder.getExpress());
                            keyword2.setColor("#173177 ");
                            //快递单号:{{keyword3.DATA}}
                            TemplateData keyword3 = new TemplateData();
                            keyword3.setValue(deliverOrder.getExpressno());
                            keyword3.setColor("#173177 ");
                            //收货信息:{{keyword4.DATA}}
                            TemplateData keyword4 = new TemplateData();
                            StringBuffer receiveMessage = new StringBuffer();
                            receiveMessage.append(deliverOrder1.getConsignee());
                            receiveMessage.append("  ");
                            receiveMessage.append(deliverOrder1.getConsigneemobile());
                            receiveMessage.append("  ");
                            receiveMessage.append(deliverOrder1.getP_c_d());
                            receiveMessage.append(" ");
                            receiveMessage.append(deliverOrder1.getAddress());
                            keyword4.setValue(receiveMessage.toString());
                            keyword4.setColor("#173177 ");
                            //{{remark.DATA}}
                            TemplateData remark = new TemplateData();
                            remark.setValue("\n如有疑问,请尽快联系我们。");
                            remark.setColor("#173177 ");
                            Map<String, TemplateData> data = new HashMap<>();
                            data.put("first", first);
                            data.put("keyword1", keyword1);
                            data.put("keyword2", keyword2);
                            data.put("keyword3", keyword3);
                            data.put("keyword4", keyword4);
                            data.put("remark", remark);
                            MessageUtil.sendTemplateMessage(appid,
                                    wbUser1.getOpenid(),
                                    template_id,
                                    data,
                                    Commons.getClientServer() + "/wzc/order/" + order.getId() + "?state=" + appid,
                                    "OPENTM************");

最后的话

本来写工作日志是不打算公开的,毕竟觉得自己看看就好了,但是之前有人跟我说,公开之后,让别人看到,有人指出不足,会更好,所以还是公开好了~"OPENTM************"然后这一部分是被我手动注释掉了。写东西完全按照自己的思维来,比较乱。就是这样。

转载于:https://my.oschina.net/LYQ19941105/blog/846881

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值