小程序服务消息通知集成

微信接口文档https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/template-message.html
调用微信服务消息的请求接口为https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN
还有一个地址为微信公众号的消息推送接口https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN
这里用服务消息的接口而不是公众号消息推送的接口,公众号接口需要付费开通权限
关于服务推送form_id问题

  • form_id有时效性,网上有说7天,但文档中没有维护。
  • form_id用过一次就失效。
  • form_id要真机提供才有效

1.模板实体类

public class TemplateData {
	
	private String value;
	//color在服务消息通知中废弃,但在公众号消息通知仍存在
	private String color;

	public TemplateData(String value,String color){
        this.value = value;
        this.color = color;
    }
	//get set 省略
}
public class TemplateMessage {
	/** 接收者openid */
	private String touser;
	/** 所需下发的模板消息的id */
	private String templateId;
	/**小程序要跳转的页面url*/
	private String page;
	/**  
	 * 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
	 * */
	private String formId;
	/** 模板数据 */
	private Map<String,TemplateData> data;
	/** 模板需要放大的关键词,不填则默认无放大 */
	private String emphasiseyword;	
	//get set 省略
}

2.获取token

public class AccessTokenRequestHandler extends RequestHandler {

	public AccessTokenRequestHandler(HttpServletRequest request,
			HttpServletResponse response) {
		super(request, response);
	}

	private static String access_token = "";
	/**
	 * 获取小程序凭证access_token
	 * @return
	 */
	public static String getMinAccessToken() {
		if ("".equals(access_token)) {// 如果为空直接获取
			return getMinTokenReal();
		}

		if (tokenIsExpire(access_token)) {// 如果过期重新获取
			return getMinTokenReal();
		}
		return access_token;
	}
	/**
	 * 实际获取小程序access_token的方法
	 * @return
	 */
	protected static String getMinTokenReal() {
		//获取token所需参数url,grant_type,appid,appsecret用自己的
		String requestUrl = TOKENURL + "?grant_type=" +GRANT_TYPE + "&appid="
				+ APPID + "&secret=" + APPSECRET;
		String resContent = "";
		TenpayHttpClient httpClient = new TenpayHttpClient();
		httpClient.setMethod("GET");
		httpClient.setReqContent(requestUrl);
		if (httpClient.call()) {
			resContent = httpClient.getResContent();
			if (resContent.indexOf(ConstantUtil.ACCESS_TOKEN) > 0) {
				access_token = JsonUtil.getJsonValue(resContent, ConstantUtil.ACCESS_TOKEN);
			} else {
				System.out.println("获取access_token值返回错误!!!");
			}
		} else {
			System.out.println("后台调用通信失败");
			System.out.println(httpClient.getResponseCode());
			System.out.println(httpClient.getErrInfo());
			// 有可能因为网络原因,请求已经处理,但未收到应答。
		}

		return access_token;
	}
}

3.发起https请求并获取结果

public class WeixinUtil {
	
	private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);  
	  
    /** 
     * 发起https请求并获取结果 
     *  
     * @param requestUrl 请求地址 
     * @param requestMethod 请求方式(GET、POST) 
     * @param outputStr 提交的数据 
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
     */  
    public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {  
        StringBuffer buffer = new StringBuffer();  
        try {  
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
            TrustManager[] tm = { new MyX509TrustManager() };  
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
            sslContext.init(null, tm, new java.security.SecureRandom());  
            // 从上述SSLContext对象中得到SSLSocketFactory对象  
            SSLSocketFactory ssf = sslContext.getSocketFactory();  
  
            URL url = new URL(requestUrl);  
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
            httpUrlConn.setSSLSocketFactory(ssf);  
  
            httpUrlConn.setDoOutput(true);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  
            // 设置请求方式(GET/POST)  
            httpUrlConn.setRequestMethod(requestMethod);  
  
            if ("GET".equalsIgnoreCase(requestMethod))  
                httpUrlConn.connect();  
  
            // 当有数据需要提交时  
            if (null != outputStr) {  
                OutputStream outputStream = httpUrlConn.getOutputStream();  
                // 注意编码格式,防止中文乱码  
                outputStream.write(outputStr.getBytes("UTF-8"));  
                outputStream.close();  
            }  
  
            // 将返回的输入流转换成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
  
            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 释放资源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  
              
        } catch (ConnectException ce) {  
            log.error("Weixin server connection timed out.");  
        } catch (Exception e) {  
            log.error("https request error:{}", e);  
        }  
        return buffer.toString();  
    }  
  
}

4.发送

public class WXMsgRun {
	public static TemplateMessage TemplateMessage(String opinid, String pagepath, String formId,
			Map<String, TemplateData> data, String emphasiseyword) {
		TemplateMessage templateMessage = new TemplateMessage();
		templateMessage.setTouser(opinid);
		templateMessage.setPagepath(pagepath);
		templateMessage.setFormId(formId);
		templateMessage.setData(data);
		templateMessage.setEmphasiseyword(emphasiseyword);
		return templateMessage;
	}
	/**
	 * 
	 */
	public static void sendOrderPayMessage(String...  相关模板字段的值自己配) {
		Map<String, TemplateData> data = new HashMap<String, TemplateData>();
		data.put("keyword1", new TemplateData(xxxxx, null));
		data.put("keyword2", new TemplateData(yyyyy, null));
		sendMessage(opinid, page, data, formId, null);
	}

	/**
	 * 
	* @param opinid 被推送用户的openid
	* @param page 消息推送后小程序跳转的页面路径
	* @param data 封装的主体数据
	* @param formId 小程序提交的表单id
	* @param emphasiseyword 需要强调的关键字段  格式为 "keyword1.DATA"
	 */
	public static void sendMessage(String opinid,String page,
			Map<String, TemplateData> data, String formId, String emphasiseyword) {
		sendWechatMsgToUser(opinid, page, formId, data, emphasiseyword);
	}

	private static void sendWechatMsgToUser(TemplateMessage templateMessage) {
		WXSendMsgJob job = new WXSendMsgJob(TemplateMessage);
		//我的方法用线程处理,也可不用,只是个demo
		ThreadPoolManager.getInstance().addExecuteTask(job);
	}
}
public class WXMessageUtil {

	private static Logger log = LoggerFactory.getLogger(WXMessageUtil.class);

	public static JSONObject dataJsonmsg(Map<String, TemplateData> data) {
        JSONObject json = new JSONObject();
        for (Map.Entry<String,TemplateData> entry : data.entrySet()) {
            JSONObject keyJson = new JSONObject();
            TemplateData  dta=  entry.getValue();
            keyJson.put("value",dta.getValue());
            keyJson.put("color", dta.getColor());
            json.put(entry.getKey(), keyJson);
        }
        return json;
    }

	/**
	 * 发送微信消息(模板消息)
	 * 
	 * @param touser    用户 OpenID
	 * @param templatId 模板消息ID
	 * @return
	 */
	public static JSONObject sendWechatMsgToUser(String touser, String templatId, String page, String formId, 
			Map<String, TemplateData> data, String emphasiseyword) {
//		String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="
//				+ AccessTokenRequestHandler.getAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token="
				+ AccessTokenRequestHandler.getMinAccessToken();
		JSONObject json = new JSONObject();
		JSONObject jsonDataMsg = dataJsonmsg(data);
		
		json.put("touser", touser);
		json.put("template_id", templatId);
		json.put("page", page);
		json.put("form_id", formId);
		json.put("data", jsonDataMsg);
		json.put("emphasis_keyword", emphasiseyword);
		System.out.println("post数据包"+json.toString());
		JSONObject parseObject = null;
		try {
			String requestMethod = "POST";
			String result = WeixinUtil.httpRequest(url, requestMethod, json.toString());
			parseObject = JSON.parseObject(result);
			log.info("发送微信消息返回信息:" + parseObject);
			log.info("发送微信消息返回信息编码:" + parseObject.get("errcode"));
			String errmsg = (String) parseObject.get("errmsg");
	        log.info("获取模板编号返回信息:" + errmsg);
			if (!"ok".equals(errmsg)) { // 如果为errmsg为ok,则代表发送成功
				log.info("失败信息" + parseObject.toJSONString());
				//失败处理
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return parseObject;
	}
}

猜你喜欢

转载自blog.csdn.net/pianpiannia/article/details/88537953