微信开发(Java)

来源:互联网 发布:最伟大的皇帝知乎 编辑:程序博客网 时间:2024/06/07 13:02

本文转载于:http://blog.csdn.net/zhutulang/article/details/50614042

微信公众号入门笔记(一)启用服务器配置

首先你要有个公众号,去https://mp.weixin.qq.com/注册。现在个人只能注册订阅号,订阅号有些接口是不开放的,没办法我们只好先看看它开放的接口了。

 

我们登录后台,去看一下公众平台开发者文档,“开发者必读”里面的“接入指南”。我建议你认真读一下这篇指南。

 

我简单说一下微信公众号开发是怎么回事。在你有了个微信公众号之后,你还要有个服务器(你可以用百度bae,或者新浪sae或者阿里云服务器),登录微信公众号后台,在最左边的菜单“开发”—“基本配置”里,你可以启用服务器配置。



 

 

在这里,你填入服务器地址url和token(具体看文档)。你要确保你填的url能够响应。那么,当别人向你的公众号发消息时,微信服务器会将该消息发送到你配置的url,然后会将你的url的响应返回给别人。大致的流程就是这样。

 

指南上写的很清楚了,并提供有PHP代码示例,我们要做的就是把它翻译成Java版的。我参考了这篇博客http://m.blog.csdn.NET/blog/bd_zengxinxin/19357163,第一篇接入的代码比较简单,所以基本直接拷贝自它,特此说明,另外这篇博客现在访问不了了。

 

事实上,我们在这第一篇要做的就是配置提供一个能响应微信服务器器的url。那么,微信后台怎么确保你填的url有效呢?当你在服务器配置中填上你的url点击确定后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带四个参数:

参数

描述

signature

微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

timestamp

时间戳

nonce

随机数

echostr

随机字符串

 

你的url要能响应这个请求,首先你要对其进行校验,“若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。”

校验方法如下:

 

加密/校验流程如下:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

 

不知你看到了这里会不会有疑问?你是否会想:如果我不校验,直接返回echostr参数内容呢?微信后台允许我配置成功吗?笔者亲试过,答案是可以!为什么呢?因为只要你配置的url返回了echostr,那么微信后台就认为你的url能正确响应,是可用的。至于你是否真的去做了校验,微信服务器并不知道。你之所以要校验是为了确认请求是来自微信服务器,反正微信告诉了你校验方式,你不去校验,由此带来的安全问题就是你自己的事了。

处理get请求的controller类如下:

    /**      *@ClassName: WeixinController      *@Description: 响应Controller      *@author zhutulang      *@date 2016年1月4日      *@version V1.0      */      @Controller       @RequestMapping("/weixinCon")      public class WeixinController {                              private Logger log =Logger.getLogger(WeixinController.class);                                @RequestMapping(method =RequestMethod.GET)                 public void get(HttpServletRequest request,HttpServletResponse response) {                              log.info("请求进来了...");                       // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。                        String signature =request.getParameter("signature");                        // 时间戳                        String timestamp =request.getParameter("timestamp");                        // 随机数                        String nonce =request.getParameter("nonce");                        // 随机字符串                        String echostr =request.getParameter("echostr");                                        PrintWriter out = null;                        try {                            out = response.getWriter();                            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败                            if (SignUtil.checkSignature(signature,timestamp, nonce)) {                                out.print(echostr);                            }                       } catch (IOException e) {                            e.printStackTrace();                        } finally {                            out.close();                            out = null;                        }                    }       }  


PHP是这样的:

<?php    //将timestamp,nonce,token按字典序排序    $timestamp = $_GET['timestamp'];    $nonce     = $_GET['nonce'];    $token     = 'weixin';    $signature = $_GET['signature'];    $array     = array($timestamp,$nonce,$token);    sort( $array );    //将排序后的三个参数拼接之后用shal加密    $tmpstr = implode('',$array);    $tmpstr = shal($tmpstr);    //将加密后的字符串与signature进行对比,判断该请求是否来自微信    if($tmpstr == $signature){        echo $_GET['echostr'];        exit;    }


http://img.mukewang.com/561cc14b0001440707150521.jpg


微信公众号入门笔记(二)响应文本消息


在这篇中,笔者将介绍如何让你的公众号响应接收到的文本消息。

 

在第一篇中,我们配置了url。于是当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

 

如果你看了文档,那么你会知道,发送文本消息时,微信发送的是类似下面的xml数据包:

 

[html] view plain copy
  1. <xml>  
  2. <ToUserName><![CDATA[toUser]]></ToUserName>  
  3. <FromUserName><![CDATA[fromUser]]></FromUserName>  
  4. <CreateTime>1348831860</CreateTime>  
  5. <MsgType><![CDATA[text]]></MsgType>  
  6. <Content><![CDATA[this is atest]]></Content>  
  7. <MsgId>1234567890123456</MsgId>  
  8. </xml>  


 

它们的含义如下:

参数

描述

ToUserName

开发者微信号

FromUserName

发送方帐号(一个OpenID

CreateTime

消息创建时间 (整型)

MsgType

text

Content

文本消息内容

MsgId

消息id,64位整型

 

 

我们在第一篇中写的controller里没有写post方法,那么现在,我们就要提供一个post方法。当普通微信用户A向我们的公众号发送一段文本之后,controller里的post方法就会接收到该请求。我们可以稍微处理下,然后用同样的xml格式返回,微信服务器就会收到该响应。如果说我们要对A用户做出回应,这里有一点要注意的是,我们返回的xml数据中,要记得把ToUserName FromUserName 交换。这个很好理解,因为,我们收到的数据包,发送方是A,接收方是我们的公众号,而我们回应时,发送方是我们的公众号,而接收方是A。记住喽!

 

这么看来,这个post方法实在是太简单了,不是吗?以我这里的例子来说,当我收到文本消息内容Content后,如果Content是1,那么我给A回应“you are the onlyone!”,否则回应"你发给我的信息是:"+Content 。

 

Post方法如下,至于解析xml和生成xml不是我们说的重点,具体请看详细代码。

 

[java] view plain copy
  1. @RequestMapping(method =RequestMethod.POST)   
  2.             public void post(HttpServletRequestrequest, HttpServletResponse response) {     
  3.                      try{  
  4.                                     request.setCharacterEncoding("UTF-8");  
  5.                                     response.setCharacterEncoding("UTF-8");  
  6.                            }catch (UnsupportedEncodingException e1) {  
  7.                                     //TODO Auto-generated catch block  
  8.                                     e1.printStackTrace();  
  9.                            }  
  10.                      PrintWriterout = null;   
  11.                 try {  
  12.                          out= response.getWriter();   
  13.                          StringresponseMsg = null;  
  14.                    
  15.                          TextMsgParserHandlertextMsgParserHandler = new TextMsgParserHandler();  
  16.                          TextMsgtextMsg = textMsgParserHandler.getTextMsg(request.getInputStream());  
  17.                          Stringcontent = textMsg.getContent();  
  18.                          log.info("收到的文本信息是:"+content);  
  19.                          if(content.equals("1")){  
  20.                                    responseMsg= "you are the only one!";  
  21.                          }else{  
  22.                                    responseMsg= "你发给我的信息是:"+content;  
  23.                          }  
  24.                     textMsg.setContent(responseMsg);  
  25.                      
  26.                     //注意这里发送者和接收者交换  
  27.                     String fromUserName = textMsg.getFromUserName();  
  28.                     String toUserName =textMsg.getToUserName();  
  29.                    textMsg.setFromUserName(toUserName);  
  30.                    textMsg.setToUserName(fromUserName);  
  31.                      
  32.                     //将textMsg 转换成xml字符串  
  33.                     String responseXml =TextMsgWriter.getXmlString(textMsg);  
  34.                          out.print(responseXml);  
  35.                    log.info("response="+responseXml);    
  36.                 } catch (Exception e) {  
  37.                     e.printStackTrace();   
  38.                 } finally {   
  39.                     out.close();   
  40.                     out = null;   
  41.                 }   
  42.             }  

            

 

看哥的截图:

 





响应所有消息


在上篇中,我们介绍了如何让你的公众号响应接收到的文本消息。事实上,响应其它类型的消息本质上都是一样的。在这里,我们先不做任何其它的逻辑,而仅仅是对发送给我们的公众号的消息做一个回应。

比如说,当接收到文本消息时返回相应的消息,当接收到语音消息时返回语音识别结果(注:要打开语音识别功能),当收到地理位置信息时返回经纬度和地理位置描述,等等。

 

 

由于我对代码做了重构,改动比较大,因此这里就不一一解析代码了,有兴趣的话自己去看吧。


微信公众号入门笔记(四)获取access_token


以下是微信公众平台开发者文档中截取的内容:

 

access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

接口调用请求说明

http请求方式: GET

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数说明

参数

是否必须

说明

grant_type

获取access_token填写client_credential

appid

第三方用户唯一凭证

secret

第三方用户唯一凭证密钥,即appsecret

返回说明

正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

参数

说明

access_token

获取到的凭证

expires_in

凭证有效时间,单位:秒

 

 

那么,从以上的说明中我们知道:

(1)我们需要以get方式发送https请求。

(2)appid和secret 可以从我们的公众号后台查看。

(3)目前,access_token的有效期目前为2个小时,我们需要提供一个定时刷新机制。并且最好能有一个强制刷新的机制。

 

一、如何发送https请求

对于第一点,用HttpClient包发送https请求,核心思路就是忽略校验过程,代码参考自:

http://blog.csdn.net/rongyongfeikai2/article/details/41659353

 

SSLClient 类如下:

 

[java] view plain copy
  1. package com.dongliushui.util;  
  2.    
  3. importjava.security.cert.CertificateException;  
  4.    
  5. import javax.net.ssl.SSLContext;  
  6. import javax.net.ssl.TrustManager;  
  7. import javax.net.ssl.X509TrustManager;  
  8.    
  9. import org.apache.http.conn.ClientConnectionManager;  
  10. import org.apache.http.conn.scheme.Scheme;  
  11. importorg.apache.http.conn.scheme.SchemeRegistry;  
  12. importorg.apache.http.conn.ssl.SSLSocketFactory;  
  13. importorg.apache.http.impl.client.DefaultHttpClient;  
  14.    
  15. /** 
  16.  *@ClassName: SSLClient 
  17.  *@Description: 用于进行Https请求的HttpClient  
  18.  *@author (代码来源):http://blog.csdn.net/rongyongfeikai2/article/details/41659353 
  19.  *@date 2016年1月8日 
  20.  *@version V1.0 
  21.  */  
  22. public class SSLClient extendsDefaultHttpClient {  
  23.    
  24.          publicSSLClient() throws Exception{   
  25.         super();   
  26.        SSLContext ctx = SSLContext.getInstance("TLS");   
  27.        X509TrustManager tm = new X509TrustManager() {  
  28.    
  29.                             @Override  
  30.                             publicvoid checkClientTrusted(  
  31.                                                java.security.cert.X509Certificate[]chain, String authType)  
  32.                                                throwsCertificateException {  
  33.                                      //TODO Auto-generated method stub  
  34.                                       
  35.                             }  
  36.    
  37.                             @Override  
  38.                             publicvoid checkServerTrusted(  
  39.                                                java.security.cert.X509Certificate[]chain, String authType)  
  40.                                                throwsCertificateException {  
  41.                                      //TODO Auto-generated method stub  
  42.                                       
  43.                             }  
  44.    
  45.                             @Override  
  46.                             publicjava.security.cert.X509Certificate[] getAcceptedIssuers() {  
  47.                                      //TODO Auto-generated method stub  
  48.                                      returnnull;  
  49.                             }   
  50.                 
  51.        };   
  52.        ctx.init(nullnew TrustManager[]{tm}, null);   
  53.        SSLSocketFactory ssf = newSSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);   
  54.        ClientConnectionManager ccm = this.getConnectionManager();   
  55.        SchemeRegistry sr = ccm.getSchemeRegistry();   
  56.        sr.register(new Scheme("https"443, ssf));   
  57.    }         
  58. }  


 

HttpUtil 类如下:

[java] view plain copy
  1. package com.dongliushui.util;  
  2.    
  3. import java.util.ArrayList;  
  4. import java.util.Iterator;  
  5. import java.util.List;  
  6. import java.util.Map;  
  7. import java.util.Map.Entry;  
  8.    
  9. import net.sf.json.JSONObject;  
  10.    
  11. import org.apache.http.HttpEntity;  
  12. import org.apache.http.HttpResponse;  
  13. import org.apache.http.NameValuePair;  
  14. import org.apache.http.client.HttpClient;  
  15. importorg.apache.http.client.entity.UrlEncodedFormEntity;  
  16. importorg.apache.http.client.methods.HttpGet;  
  17. import org.apache.http.client.methods.HttpPost;  
  18. import org.apache.http.entity.StringEntity;  
  19. importorg.apache.http.impl.client.DefaultHttpClient;  
  20. importorg.apache.http.message.BasicNameValuePair;  
  21. import org.apache.http.util.EntityUtils;  
  22.    
  23. /** 
  24.  *@ClassName: HttpUtil 
  25.  * @Description:Http请求工具类 
  26.  *@author zhutulang 
  27.  *@date 2016年1月8日 
  28.  *@version V1.0 
  29.  */  
  30. public class HttpUtil {  
  31.    
  32.          /** 
  33.           * <p>Title: doHttpsPost</p> 
  34.           * <p>Description: 发送https 形式的post请求</p> 
  35.           * @param url 请求url 
  36.           * @param contentType 
  37.           * @param paramMap 参数map 
  38.           * @return 
  39.           * @author zhutulang 
  40.           * @version 1.0 
  41.           */  
  42.          publicstatic byte[] doHttpsPostJson(String url, String contentType, Map<String,String> paramMap){  
  43.                    returnpostJson(1, url, contentType, paramMap);  
  44.          }  
  45.           
  46.          /** 
  47.           * <p>Title: doHttpsPost</p> 
  48.           * <p>Description: 发送http 形式的post请求</p> 
  49.           * @param url 请求url 
  50.           * @param contentType 
  51.           * @param paramMap 参数map 
  52.           * @return 
  53.           * @author zhutulang 
  54.           * @version 1.0 
  55.           */  
  56.          publicstatic byte[] doPostJson(String url, String contentType, Map<String,String> paramMap){  
  57.                   return postJson(0, url, contentType,paramMap);  
  58.          }  
  59.           
  60.          /** 
  61.           * <p>Title: doHttpsGet</p> 
  62.           * <p>Description: 发送https 形式的get请求</p> 
  63.           * @param url 请求url 
  64.           * @param contentType 
  65.           * @return 
  66.           * @author zhutulang 
  67.           * @version 1.0 
  68.           */  
  69.          publicstatic byte[] doHttpsGet(String url, String contentType){  
  70.                    returnget(1, url, contentType);  
  71.          }  
  72.           
  73.          /** 
  74.           * <p>Title: doGet</p> 
  75.           * <p>Description: 发送http 形式的gett请求</p> 
  76.           * @param url 请求url 
  77.           * @param contentType 
  78.           * @return 
  79.           * @author zhutulang 
  80.           * @version 1.0 
  81.           */  
  82.          publicstatic byte[] doGet(String url, String contentType){  
  83.                    returnget(0, url, contentType);  
  84.          }  
  85.           
  86.          /** 
  87.           * <p>Title: post</p> 
  88.           * <p>Description: 发送post请求,表单提交参数</p> 
  89.           * @param type 0:普通post请求  1:https形式的post请求 
  90.           * @param url 请求url 
  91.           * @param contentType  
  92.           * @param paramMap 参数map 
  93.           * @return 
  94.           * @author zhutulang 
  95.           * @version 1.0 
  96.           */  
  97.          privatestatic byte[] postCommon(int type, String url, String contentType,Map<String, String> paramMap){  
  98.                    //响应内容  
  99.              byte[] bs = null;  
  100.               
  101.              HttpClient httpClient = null;  
  102.              HttpPost httpPost = null;  
  103.               
  104.              try {  
  105.                        
  106.                if(type == 0){  
  107.                       //创建发送 http 请求的httpClient实例  
  108.                            httpClient= new DefaultHttpClient();  
  109.                }else if(type == 1){  
  110.                       //创建发送 https 请求的httpClient实例  
  111.                            httpClient= new SSLClient();  
  112.                }  
  113.                 
  114.                // 创建HttpPost  
  115.                httpPost = new HttpPost(url);  
  116.               httpPost.setHeader("content-type", contentType);  
  117.                //设置参数  
  118.                List<NameValuePair> list = newArrayList<NameValuePair>();  
  119.                if(paramMap != null){  
  120.                         Iterator<Entry<String, String>>iterator = paramMap.entrySet().iterator();   
  121.                    while(iterator.hasNext()){   
  122.                        Entry<String,String> elem =(Entry<String, String>) iterator.next();   
  123.                        list.add(newBasicNameValuePair(elem.getKey(),elem.getValue()));   
  124.                    }   
  125.                    if(list.size() > 0){   
  126.                        UrlEncodedFormEntity entity = newUrlEncodedFormEntity(list,"UTF-8");   
  127.                        httpPost.setEntity(entity);   
  128.                    }  
  129.                }  
  130.                // 执行POST请求  
  131.                HttpResponse response =httpClient.execute(httpPost);  
  132.                // 获取响应实体  
  133.                HttpEntity entity = response.getEntity();  
  134.                if(entity != null){  
  135.                         bs = EntityUtils.toByteArray(entity);  
  136.                }  
  137.              } catch (Exception e) {  
  138.                e.printStackTrace();  
  139.              } finally {  
  140.                // 关闭连接,释放资源  
  141.               httpClient.getConnectionManager().shutdown();  
  142.                httpPost = null;  
  143.                httpClient = null;  
  144.              }  
  145.              return bs;  
  146.          }  
  147.           
  148.          /** 
  149.           * <p>Title: post</p> 
  150.           * <p>Description: 发送post请求,json方式提交参数</p> 
  151.           * @param type 0:普通post请求  1:https形式的post请求 
  152.           * @param url 请求url 
  153.           * @param contentType  
  154.           * @param paramMap 参数map 
  155.           * @return 
  156.           * @author zhutulang 
  157.           * @version 1.0 
  158.           */  
  159.          privatestatic byte[] postJson(int type, String url, String contentType, Map<String,String> paramMap){  
  160.                    //响应内容  
  161.              byte[] bs = null;  
  162.               
  163.              HttpClient httpClient = null;  
  164.              HttpPost httpPost = null;  
  165.               
  166.              try {  
  167.                        
  168.                if(type == 0){  
  169.                       //创建发送 http 请求的httpClient实例  
  170.                            httpClient= new DefaultHttpClient();  
  171.                }else if(type == 1){  
  172.                       //创建发送 https 请求的httpClient实例  
  173.                            httpClient= new SSLClient();  
  174.                }  
  175.                 
  176.                // 创建HttpPost  
  177.                httpPost = new HttpPost(url);  
  178.               httpPost.setHeader("content-type", contentType);  
  179.                if(paramMap != null){  
  180.                         Iterator<Entry<String, String>>iterator = paramMap.entrySet().iterator();   
  181.                         // 接收参数json列表   
  182.               JSONObject jsonParam = newJSONObject();   
  183.                    while(iterator.hasNext()){   
  184.                        Entry<String,String> elem =(Entry<String, String>) iterator.next();   
  185.                        jsonParam.put(elem.getKey(),elem.getValue());     
  186.                    }   
  187.                    if(jsonParam.size() > 0){  
  188.                        StringEntity entity = newStringEntity(jsonParam.toString(),"UTF-8");  
  189.                  entity.setContentEncoding("UTF-8");     
  190.                  entity.setContentType("application/json");     
  191.                  httpPost.setEntity(entity);     
  192.                    }  
  193.                }  
  194.                // 执行POST请求  
  195.                HttpResponse response =httpClient.execute(httpPost);  
  196.                // 获取响应实体  
  197.                HttpEntity entity = response.getEntity();  
  198.                if(entity != null){  
  199.                         bs = EntityUtils.toByteArray(entity);  
  200.                }  
  201.              } catch (Exception e) {  
  202.                e.printStackTrace();  
  203.              } finally {  
  204.                // 关闭连接,释放资源  
  205.               httpClient.getConnectionManager().shutdown();  
  206.                httpPost = null;  
  207.                httpClient = null;  
  208.              }  
  209.              return bs;  
  210.          }  
  211.           
  212.          /** 
  213.           * <p>Title: get</p> 
  214.           * <p>Description: 发送get请求</p> 
  215.           * @param type 0:普通get请求  1:https形式的get请求 
  216.           * @param url  请求url 
  217.           * @param contentType 
  218.           * @return 
  219.           * @author zhutulang 
  220.           * @version 1.0 
  221.           */  
  222.          privatestatic byte[] get(int type, String url, String contentType){  
  223.                    //响应内容  
  224.              byte[] bs = null;  
  225.               
  226.              HttpClient httpClient = null;  
  227.              HttpGet httpGet = null;  
  228.               
  229.              try {  
  230.                if(type == 0){  
  231.                       //创建发送 http 请求的httpClient实例  
  232.                            httpClient= new DefaultHttpClient();  
  233.                }else if(type == 1){  
  234.                       //创建发送 https 请求的httpClient实例  
  235.                            httpClient= new SSLClient();  
  236.                }  
  237.                 
  238.                // 创建HttpPost  
  239.                httpGet = new HttpGet(url);  
  240.               httpGet.setHeader("content-type", contentType);  
  241.                // 执行POST请求  
  242.                HttpResponse response =httpClient.execute(httpGet);  
  243.                // 获取响应实体  
  244.                HttpEntity entity = response.getEntity();  
  245.                if(entity != null){  
  246.                         bs = EntityUtils.toByteArray(entity);  
  247.                }  
  248.              } catch (Exception e) {  
  249.                e.printStackTrace();  
  250.              } finally {  
  251.                // 关闭连接,释放资源  
  252.                httpClient.getConnectionManager().shutdown();  
  253.                httpGet = null;  
  254.                httpClient = null;  
  255.              }  
  256.              return bs;  
  257.          }  
  258. }  


二、如何定时刷新access_token

在集群环境中,这个问题可能会比较复杂。我们可能需要考虑到在集群中各个机器的任务调度协调,对于获取到的access_token,我们可能会考虑将它保存在数据库中,或者统一的缓存模块中,比如Redis中。对于单服务器环境,我们大可以直接将其保存在内存中。

定时任务我们经常会用到quartz框架。不过spring也提供有任务调度的模块,我习惯用@Scheduled注解。至于它的使用,大家可自行百度。

以下代码中形如@Value("#{weixinProperties['AppId']}")

是通过spring读取配置文件,如果没见过这样做的朋友也可以自行去查找相关资料。

相关的配置放在一个名为weixin.properties的配置文件中:

#weixin properties

# 你自己的appid和appsecret

AppId=XXXXXXXXX

AppSecret=XXXXXXXXXXXXXXXXXXX

 

#get access_token urlget

get_access_token_url=https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

 

#batchget_material urlpost

batchget_material_url=https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN

 

Spring配置文件中:

[html] view plain copy
  1. <!-- weixin.properties 配置文件 -->  
  2.     <bean id="weixinProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">  
  3.         <property name="locations">  
  4.             <list>  
  5.                 <value>classpath*:weixin.properties</value>  
  6.             </list>  
  7.         </property>  
  8.     </bean>  
  9.     <bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">  
  10.         <property name="properties" ref="weixinProperties" />  
  11.     </bean>   


 

AccessTokenTaker 代码如下:

[java] view plain copy
  1. package com.dongliushui.quartz;  
  2.    
  3. importjava.io.UnsupportedEncodingException;  
  4.    
  5. import org.apache.log4j.Logger;  
  6. importorg.springframework.beans.factory.annotation.Value;  
  7. import org.springframework.scheduling.annotation.Scheduled;  
  8. importorg.springframework.stereotype.Component;  
  9.    
  10. import com.dongliushui.util.HttpUtil;  
  11.    
  12. /** 
  13.  *@ClassName: AccessTokenTaker 
  14.  *@Description: 获取access_token 
  15.  *@author zhutulang 
  16.  *@date 2016年1月10日 
  17.  *@version V1.0 
  18.  */  
  19. @Component  
  20. public class AccessTokenTaker {  
  21.    
  22.          @Value("#{weixinProperties['AppId']}")  
  23.          private  String appId;  
  24.           
  25.          @Value("#{weixinProperties['AppSecret']}")  
  26.          private  String appSecret;  
  27.           
  28.          @Value("#{weixinProperties['get_access_token_url']}")  
  29.          private  String getAccessTokenUrl;  
  30.           
  31.          /** 
  32.           * access_token 
  33.           */  
  34.          privatestatic  String ACCESS_TOKEN = null;  
  35.          /** 
  36.           * 上次更新access_token时间 
  37.           */  
  38.          privatestatic  LongLAST_ACCESS_TOKEN_UPDATE_TIME = null;  
  39.           
  40.          privatestatic Logger log = Logger.getLogger(AccessTokenTaker.class);  
  41.           
  42.          /** 
  43.           * <p>Title: get</p> 
  44.           * <p>Description: 每隔一个小时去获取一次access_token</p> 
  45.           * @author zhutulang 
  46.           * @version 1.0 
  47.           */  
  48.          @Scheduled(fixedRate=3600000)  
  49.          privatevoid getTask(){  
  50.                    get();  
  51.          }  
  52.           
  53.          /** 
  54.           * <p>Title: getFromCache</p> 
  55.           * <p>Description: 从缓存中获取access_token</p> 
  56.           * @return 
  57.           * @author zhutulang 
  58.           * @version 1.0 
  59.           */  
  60.          public  String getFromCache(){  
  61.                    returnACCESS_TOKEN;  
  62.          }  
  63.           
  64.          /** 
  65.           * <p>Title: getNew</p> 
  66.           * <p>Description: 强制更新、获取access_token</p> 
  67.           * <p>如果发现现在的时间戳和上次更新的时间戳间隔小于5分钟,那么不更新</p> 
  68.           * @return 
  69.           * @author zhutulang 
  70.           * @version 1.0 
  71.           */  
  72.          publicsynchronized  String getNew(){  
  73.                    longtimeNow = System.currentTimeMillis();  
  74.                    if(LAST_ACCESS_TOKEN_UPDATE_TIME== null){  
  75.                             get();  
  76.                    }elseif(timeNow - LAST_ACCESS_TOKEN_UPDATE_TIME < 300000){  
  77.                             //如果是5分钟以内  
  78.                             returnACCESS_TOKEN;  
  79.                    }else{  
  80.                             get();  
  81.                    }  
  82.                    returnACCESS_TOKEN;  
  83.          }  
  84.           
  85.          /** 
  86.           * <p>Title: get</p> 
  87.           * <p>Description: 调用获取access_token接口</p> 
  88.           * @author zhutulang 
  89.           * @version 1.0 
  90.           */  
  91.          synchronized  void get(){  
  92.                    Stringurl = getAccessTokenUrl.replace("APPID",appId).replace("APPSECRET", appSecret);  
  93.                    StringcontentType = "application/json";  
  94.                    byte[]bytes = HttpUtil.doHttpsGet(url, contentType);  
  95.                    try{  
  96.                             StringaccessToken = new String(bytes, "UTF-8");  
  97.                             longtimeNow = System.currentTimeMillis();  
  98.                             ACCESS_TOKEN= accessToken;  
  99.                             LAST_ACCESS_TOKEN_UPDATE_TIME= timeNow;  
  100.                             log.info("执行获取access_token任务,access_token="+ACCESS_TOKEN);  
  101.                  log.info("时间戳="+LAST_ACCESS_TOKEN_UPDATE_TIME);  
  102.                    }catch (UnsupportedEncodingException e) {  
  103.                             //TODO Auto-generated catch block  
  104.                             e.printStackTrace();  
  105.                    }  
  106.          }  
  107.    
  108.          publicString getAppId() {  
  109.                    returnappId;  
  110.          }  
  111.    
  112.          publicvoid setAppId(String appId) {  
  113.                    this.appId= appId;  
  114.          }  
  115.    
  116.          publicString getAppSecret() {  
  117.                    returnappSecret;  
  118.          }  
  119.    
  120.          publicvoid setAppSecret(String appSecret) {  
  121.                    this.appSecret= appSecret;  
  122.          }  
  123.    
  124.          publicString getGetAccessTokenUrl() {  
  125.                    returngetAccessTokenUrl;  
  126.          }  
  127.    
  128.          publicvoid setGetAccessTokenUrl(String getAccessTokenUrl) {  
  129.                    this.getAccessTokenUrl= getAccessTokenUrl;  
  130.          }  




代码下载:

http://download.csdn.net/detail/carl_jiang/9853148



原创粉丝点击