微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应

http://blog.csdn.net/u013076997/article/details/52814139

一、模板消息

使用场景:当用户注册成功,支付成功的时候,为了方便提醒用户,或者为了提醒卖家发货时,可以用到模板消息。

模板消息的使用方法如下:
1、打开微信公众平台,功能————模板消息
微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应

或者也可以在添加功能插件中

微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应

2、添加模板前,需要确定一下微信公众号注册时营业执照的行业;行业选定后,提交审核,审核时间1天到1周不等;

3、审核成功后,微信就会按照所选的行业,提供模板库,然后当我们需要模板信息时,就从模板库中添加;注:最多只能选择25个模板,当然这肯定足够用了;

微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应

4、模板添加完成之后,就涉及如何使用了:

    拿注册来举例,注册成功后,在注册成功方法中调用模板消息接口发送消息:

①注册成功之后的调用的方法:

[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. /** 
  2.      * 注册成功之后发送模板信息 
  3.      * @param openid 
  4.      */  
  5.     private void sendRegisterTemplate(){  
  6.         try {  
  7.             Model first = new Model("恭喜您,注册成功!""#000000");  
  8.             Model keyword1 = new Model("张三""#000000");  
  9.             Model keyword2 = new Model("131XXXXXXX""#000000");  
  10.             Model remark = new Model("开始尽情的购物吧!""#000000");  
  11.             RegisterData data = new RegisterData(first, keyword1, keyword2, remark);  
  12.             TemplateReserve template = new TemplateReserve(data);  
  13.             template.setTouser("接收信息人的openid");//openId  
  14.             template.setTemplate_id("在模板库中添加的模板信息的id");//模版消息Id  
  15.             template.setUrl("用户点击模板信息后跳转的地址");//模版点击后链接的地方  
  16.             template.setTopcolor("模板头部的颜色");//模版头颜色  
  17.             AdvancedUtil.sendTemplate("调用接口所需的token", template);  
  18.         } catch (Exception e) {  
  19.             e.printStackTrace();  
  20.         }  
  21.     }  


②调用接口方法


[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. /** 
  2.      * 发送模版消息 
  3.      * @param accessToken 接口访问凭证 
  4.      * @param template 消息模版 
  5.      *  
  6.      * */  
  7.     public static void sendTemplate(String accessToken,BaseTemplate template){  
  8.         String requestUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";  
  9.         requestUrl = requestUrl.replace("ACCESS_TOKEN",accessToken);  
  10.         String postData = JSONObject.fromObject(template).toString();  
  11.         JSONObject jsonObject = WSPostUtil.httpsRequest(requestUrl, "POST", postData);  
  12.         System.out.println(jsonObject.toString());  
  13.         try {  
  14.             int errorCode = jsonObject.getInt("errcode");  
  15.             String errorMsg = jsonObject.getString("errmsg");  
  16.             if(errorCode==0){  
  17.                 log.info("模版发送成功 errcode:{} errmsg:{}", errorCode, errorMsg);  
  18.             }else{  
  19.                 log.error("模版发送失败 errcode:{} errmsg:{}", errorCode, errorMsg);  
  20.             }  
  21.         } catch (Exception e) {  
  22.             log.error("模版消息发送异常,"+e.getMessage());  
  23.         }  
  24.     }  

③httpRequest方法

[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. /** 
  2.      * 发送https请求 
  3.      *  
  4.      * @param requestUrl 请求地址 
  5.      * @param requestMethod 请求方式(GET、POST) 
  6.      * @param outputStr 提交的数据 
  7.      * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
  8.      */  
  9.     public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {  
  10.         JSONObject jsonObject = null;  
  11.         try {  
  12.             // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
  13.             TrustManager[] tm = { new MyX509TrustManager() };  
  14.             SSLContext sslContext = SSLContext.getInstance("SSL""SunJSSE");  
  15.             sslContext.init(null, tm, new java.security.SecureRandom());  
  16.             // 从上述SSLContext对象中得到SSLSocketFactory对象  
  17.             SSLSocketFactory ssf = sslContext.getSocketFactory();  
  18.   
  19.             URL url = new URL(requestUrl);  
  20.             HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();  
  21.             conn.setSSLSocketFactory(ssf);  
  22.               
  23.             conn.setDoOutput(true);  
  24.             conn.setDoInput(true);  
  25.             conn.setUseCaches(false);  
  26.             // 设置请求方式(GET/POST)  
  27.             conn.setRequestMethod(requestMethod);  
  28.   
  29.             // 当outputStr不为null时向输出流写数据  
  30.             if (null != outputStr) {  
  31.                 OutputStream outputStream = conn.getOutputStream();  
  32.                 // 注意编码格式  
  33.                 outputStream.write(outputStr.getBytes("UTF-8"));  
  34.                 outputStream.close();  
  35.             }  
  36.   
  37.             // 从输入流读取返回内容  
  38.             InputStream inputStream = conn.getInputStream();  
  39.             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
  40.             BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
  41.             String str = null;  
  42.             StringBuffer buffer = new StringBuffer();  
  43.             while ((str = bufferedReader.readLine()) != null) {  
  44.                 buffer.append(str);  
  45.             }  
  46.   
  47.             // 释放资源  
  48.             bufferedReader.close();  
  49.             inputStreamReader.close();  
  50.             inputStream.close();  
  51.             inputStream = null;  
  52.             conn.disconnect();  
  53.             jsonObject = JSONObject.fromObject(buffer.toString());  
  54.         } catch (ConnectException ce) {  
  55.             log.error("连接超时:{}", ce);  
  56.         } catch (Exception e) {  
  57.             log.error("https请求异常:{}", e);  
  58.         }  
  59.         return jsonObject;  
  60.     }  

④ Model类

[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. public class Model{  
  2.     private String value;   //内容  
  3.     private String color;   //字体颜色  
  4.     public Model(String color) {  
  5.         this.color = color;  
  6.     }  
  7.     public Model() {  
  8.         super();  
  9.     }  
  10.     public Model(String value, String color) {  
  11.         super();  
  12.         this.value = value;  
  13.         this.color = color;  
  14.     }  
  15.     public String getValue() {  
  16.         return value;  
  17.     }  
  18.     public Model setValue(String value) {  
  19.         this.value = value;  
  20.         return this;  
  21.     }  
  22.     public String getColor() {  
  23.         return color;  
  24.     }  
  25.     public Model setColor(String color) {  
  26.         this.color = color;  
  27.         return this;  
  28.     }  
  29. }  

⑤RegisData类
[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. public class RegisterData extends Data{  
  2.     private Model first;//模板开始前描述  
  3.     private Model keyword1;//关键词1  
  4.     private Model keyword2;//关键词2  
  5.     private Model remark;//模板结束描述  
  6.   
  7.     public RegisterData(Model first, Model keyword1, Model keyword2, Model remark) {  
  8.         this.first = first;  
  9.         this.keyword1 = keyword1;  
  10.         this.keyword2 = keyword2;  
  11.         this.remark = remark;  
  12.     }  
  13.   
  14.     public Model getFirst() {  
  15.         return first;  
  16.     }  
  17.   
  18.     public void setFirst(Model first) {  
  19.         this.first = first;  
  20.     }  
  21.   
  22.     public Model getKeyword1() {  
  23.         return keyword1;  
  24.     }  
  25.   
  26.     public void setKeyword1(Model keyword1) {  
  27.         this.keyword1 = keyword1;  
  28.     }  
  29.   
  30.     public Model getKeyword2() {  
  31.         return keyword2;  
  32.     }  
  33.   
  34.     public void setKeyword2(Model keyword2) {  
  35.         this.keyword2 = keyword2;  
  36.     }  
  37.   
  38.     public Model getRemark() {  
  39.         return remark;  
  40.     }  
  41.   
  42.     public void setRemark(Model remark) {  
  43.         this.remark = remark;  
  44.     }  
  45.       
  46. }  

⑥TemplateReverse类

[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. public class TemplateReserve extends BaseTemplate {  
  2.     private Data data;  
  3.       
  4.     public TemplateReserve(Data data){  
  5.         this.data = data;  
  6.     }  
  7.       
  8.     public Data getData() {  
  9.         return data;  
  10.     }  
  11.   
  12.     public void setData(Data data) {  
  13.         this.data = data;  
  14.     }  
  15.       
  16. }  

⑦Data类

[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. public abstract class Data {  
  2.   
  3. }  

⑧BaseTemplate类

[java] view plain copy
 微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应微信公众号开发中遇到的问题——模板信息,自定义回复,一次请求多次相应
  1. /** 
  2.  * 模版消息基类 
  3.  * @author wangrr 
  4.  * */  
  5. public class BaseTemplate {  
  6.   
  7.     private String touser;      //openId  
  8.     private String template_id; //模版消息Id  
  9.     private String url;         //模版点击后链接的地方  
  10.     private String topcolor;    //模版头颜色  
  11.       
  12.     public BaseTemplate() {  
  13.           
  14.     }  
  15.     public String getTouser() {  
  16.         return touser;  
  17.     }  
  18.     public void setTouser(String touser) {  
  19.         this.touser = touser;  
  20.     }  
  21.     public String getTemplate_id() {  
  22.         return template_id;  
  23.     }  
  24.     public void setTemplate_id(String template_id) {  
  25.         this.template_id = template_id;  
  26.     }  
  27.     public String getUrl() {  
  28.         return url;  
  29.     }  
  30.     public void setUrl(String url) {  
  31.         this.url = url;  
  32.     }  
  33.     public String getTopcolor() {  
  34.         return topcolor;  
  35.     }  
  36.     public void setTopcolor(String topcolor) {  
  37.         this.topcolor = topcolor;  
  38.     }  


二、消息自定义回复

有时候我们想根据用户发送特定的内容给用户回复特定的消息;之前有个客户就是想把输入框做成类似于搜索框;譬如我输入“梅西”,梅西的个人简介就回复过来,我输入“库里”,库里的个人信息就回复过来等等;其实很简单,只需要在数据库中维护一个规则表即可,规则表中,把梅西与梅西简介,库里与库里简介对应起来即可;另外可能用户还会发送一些图片,语音,地理位置等特殊信息,这时候我们根据信息的类型回复对应的信息即可;

三、一次请求多次响应

使用微信开发的朋友都知道,有时候发送一个请求,微信会做出两条,三条或者更多次响应,如果程序中没有做处理,可能就会导致数据出错;除了微信提供的“根据msgId进行信息排重”之外,我认为自己程序中也需要一些特殊的处理:
①尽量把一次请求请求完之后,重定向到另外一个方法,这样做是很有必要的;
②尽量使用post提交
③如果碰到特殊的情况,如微信支付完回调方法,是由微信发起的请求,它同样也会请求多次,如果你程序中是这样处理逻辑的:当微信回调后,如果支付成功,就给用户发送支付成功提醒,这时候如果微信对同一订单回调了多次,那你就给用户发送了多次支付提醒,这会吓到用户的。这个时候,可以使用一些状态信息来避免重复提醒;