第一次做微信推送消息这一块,所以整理出来供大家参考,有不对或不完善的地方,希望大家多多指教。
先附上官方的开发文档https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
然后,有几个我遇到的问题,如果各位在开发的过程中遇到了,请一定要注意。
一、做微信相关的开发,一定会和openId打交道,这里需要说明一下,openId只是一个公众号和一个微信用户之间唯一存在的id,而不是微信用户的唯一id,举个栗子:你关注了公众号A以后,公众号A会得到一个你的openid,你关注公众号B,公众号B也会拿到你的openId,但是,需要注意的是,这两个openId,不是一样的。
我在开发的时候,做的是一个公众号里嵌套一个微信小程序,需要注意的是,微信小程序获取到的openid和我这个公众号产生的openId也是不一样的。
话不多说,上代码:
首先,根据微信官方api文档,建立一个传输数据类型类
public class Data_style { 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; } }
接下来就是创建你要在模板中传输的数据
public class Data { private Data_style first; private Data_style keyword1; private Data_style keyword2; private Data_style remark; public Data_style getFirst() { return first; } public void setFirst(Data_style first) { this.first = first; } public Data_style getKeyword1() { return keyword1; } public void setKeyword1(Data_style keyword1) { this.keyword1 = keyword1; } public Data_style getKeyword2() { return keyword2; } public void setKeyword2(Data_style keyword2) { this.keyword2 = keyword2; } public Data_style getRemark() { return remark; } public void setRemark(Data_style remark) { this.remark = remark; } }
然后是模板
public class NewOrdersTemplate { private String touser; //用户OpenID private String template_id; //模板消息ID private String url; //URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)。 private String topcolor; //标题颜色 private Data data; //详细内容 public String getTouser() { return touser; } public void setTouser(String touser) { this.touser = touser; } public String getTemplate_id() { return template_id; } public void setTemplate_id(String templateId) { template_id = templateId; } 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 Data getData() { return data; } public void setData(Data data) { this.data = data; } }
接下来就进入正题了
public class Template { private static Logger log = LoggerFactory.getLogger(Template.class); /** * 发送模板消息 * appId 公众账号的唯一标识 * appSecret 公众账号的密钥 * openId 用户标识 */ public static void send_template_message(String appId, String appSecret, String openId,String userName,Long weChatId,Long userId,String format1) { //因为我申请的模板是需要填写当前时间戳的,所以在这里我获取了当前的时间 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH时mm分"); String format = simpleDateFormat.format(new Date()); Token token = CommonUtil.getToken(appId, appSecret);//这里要注意,如果你是申请的正式公众号的话,获取token的时候,一定要在后台加上你的ip,不然获取token的时候会报错 String access_token = token.getAccessToken(); String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+access_token; String templateId = "";//填写申请的模板id String goUrl = "";//填写点击推送的消息需跳转到的url Data_style first = new Data_style(); Data_style keyword1 = new Data_style(); Data_style keyword2 = new Data_style(); Data_style remark = new Data_style(); NewOrdersTemplate temp = new NewOrdersTemplate(); Data data = new Data(); first.setValue(format); first.setColor("#173177"); keyword1.setValue("绑定成功"); keyword1.setColor("#173177"); keyword2.setValue(userName); keyword2.setColor("#173177"); remark.setValue(""); remark.setColor("#173177"); data.setFirst(first); data.setKeyword1(keyword1); data.setKeyword2(keyword2); data.setRemark(remark); temp.setTouser(openId); temp.setTemplate_id(templateId); temp.setUrl(goUrl); temp.setTopcolor("#173177"); temp.setData(data); String jsonString = JSONObject.fromObject(temp).toString().replace("day", "Day"); JSONObject jsonObject = CommonUtil.httpsRequest(url, "POST", jsonString); System.out.println(jsonObject); int result = 0; if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { result = jsonObject.getInt("errcode"); log.error("错误 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } log.info("模板消息发送结果:"+result); } }
工具类
public class CommonUtil { private static Logger log = LoggerFactory.getLogger(CommonUtil.class); // 凭证获取(GET) public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; /** * 发送 https 请求 * * @param requestUrl 请求地址 * @param requestMethod 请求方式(GET、POST) * @param outputStr 提交的数据 * @return JSONObject(通过 JSONObject.get(key) 的方式获取 JSON 对象的属性值) */ public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; 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 conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(ssf); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); // 设置请求方式(GET/POST) conn.setRequestMethod(requestMethod); // 当 outputStr 不为 null 时,向输出流写数据 if (null != outputStr) { OutputStream outputStream = conn.getOutputStream(); // 注意编码格式 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = conn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; StringBuffer buffer = new StringBuffer(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } // 释放资源 bufferedReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; conn.disconnect(); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (ConnectException ce) { log.error(" 连接超时:{}", ce); } catch (Exception e) { log.error("https 请求异常:{}", e); } return jsonObject; } /** * 获取接口访问凭证 * * @param appid 凭证 * @param appsecret 密钥 * @return */ public static Token getToken(String appid, String appsecret) { Token token = null; String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret); // 发起GET请求获取凭证 JSONObject jsonObject = httpsRequest(requestUrl, "GET", null); if (null != jsonObject) { try { token = new Token(); token.setAccessToken(jsonObject.getString("access_token")); token.setExpiresIn(jsonObject.getInt("expires_in")); } catch (JSONException e) { token = null; // 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return token; } }
token类
public class Token { //接口访问凭证 private String accessToken; //接口有效期,单位:秒 private int expiresIn; public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } }
MyX509TrustManager类
public class MyX509TrustManager implements X509TrustManager{ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }