刚刚做了一个微信的分享。因为微信现在是很普及的APP,几乎是每个人都会有微信号,用户量何其大!!!!所以我写了一个简单的连接微信的工具类,其中包含获取token,ticket,等等。。。
1、微信通用的工具类
text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
package com.solian.web.util;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
import com.solian.web.bean.Token;
import com.solian.web.bean.WinXinEntity;
import net.sf.json.JSONObject;
/**
* 微信通用工具类
*
* @author wukaikai
*
*/
public class WeiXinUtils {
// 获取access_token的接口地址(GET) 限2000(次/天)
public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
// 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
// 缓存添加的时间
public static String cacheAddTime = null;
// token,ticket缓存
public static Map<String, Token> TOKEN_TICKET_CACHE = new HashMap<String, Token>();
// token对应的key
private static final String TOKEN = "token";
// ticket对应的key
private static final String TICKET = "ticket";
public static WinXinEntity getWinXinEntity(String url) {
WinXinEntity wx = new WinXinEntity();
String access_token = getToken("APPID", "AppSecret");
String ticket = getTicket(access_token);
Map<String, String> ret = Sign.sign(ticket, url);
System.out.println(ret.toString());
wx.setTicket(ret.get("jsapi_ticket"));
wx.setSignature(ret.get("signature"));
wx.setNoncestr(ret.get("nonceStr"));
wx.setTimestamp(ret.get("timestamp"));
wx.setStr(ret.get("url"));
return wx;
}
/**
* 获得Token
*
* @return
*/
public static String getToken(String appId, String secret) {
Token accessTocken = getToken(appId, secret, System.currentTimeMillis() / 1000);
return accessTocken.getToken();
}
/**
* 获得ticket
*
* @return
*/
public static String getTicket(String token) {
Token accessTocken = getTicket(token, System.currentTimeMillis() / 1000);
return accessTocken.getTicket();
}
/**
* 获取access_token
*
* @param appid
* @param appsecret
* @param currentTime
* @return
*/
public static Token getToken(String appid, String appsecret, long currentTime) {
Token tokenTicketCache = getTokenTicket(TOKEN);
Token token = null;
if (tokenTicketCache != null && (currentTime - tokenTicketCache.getAddTime() <= tokenTicketCache.getExpiresTime())) {
System.out.println("==========缓存中token已获取时长为:" + (currentTime - tokenTicketCache.getAddTime()) + "毫秒,可以重新使用");
return tokenTicketCache;
}
System.out.println("==========缓存中token不存在或已过期===============正在重新请求===========");
String token_url = access_token_url.replaceAll("APPID", appid).replaceFirst("APPSECRET", appsecret);
JSONObject jsonObject = httpRequest(token_url, "GET", null);
if (null != jsonObject) {
token = new Token();
token.setToken(jsonObject.getString("access_token"));
token.setExpiresTime(jsonObject.getLong(("expires_in"))/2);// 正常过期时间是7200秒,此处设置3600秒读取一次
System.out.println("==========tocket缓存过期时间为:" + token.getExpiresTime() + "毫秒");
token.setAddTime(currentTime);
updateToken(TOKEN, token);
}
return token;
}
/**
* 获取ticket
*
* @param token
* @return
*/
private static Token getTicket(String token, long currentTime) {
Token tockenTicketCache = getTokenTicket(TICKET);
Token Token = null;
if (tockenTicketCache != null && (currentTime - tockenTicketCache.getAddTime() <= tockenTicketCache.getExpiresTime())) {// 缓存中有ticket
System.out.println("==========缓存中ticket已获取时长为:" + (currentTime - tockenTicketCache.getAddTime()) + "毫秒,可以重新使用");
return tockenTicketCache;
}
System.out.println("==========缓存中ticket不存在或已过期===============");
String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
// 如果请求成功
if (null != jsonObject) {
Token = new Token();
Token.setTicket(jsonObject.getString("ticket"));
Token.setExpiresTime(jsonObject.getLong("expires_in") / 2);// 正常过期时间是7200秒,此处设置3600秒读取一次
System.out.println("==========ticket缓存过期时间为:" + Token.getExpiresTime() + "毫秒");
Token.setAddTime(currentTime);
updateToken(TICKET, Token);
}
return Token;
}
/**
* 从缓存中读取token或者ticket
*
* @return
*/
private static Token getTokenTicket(String key) {
if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
System.out.println("==========从缓存中获取到了" + key + "成功===============");
return TOKEN_TICKET_CACHE.get(key);
}
return null;
}
/**
* 更新缓存中token或者ticket
*
* @return
*/
private static void updateToken(String key, Token accessTocken) {
if (TOKEN_TICKET_CACHE != null && TOKEN_TICKET_CACHE.get(key) != null) {
TOKEN_TICKET_CACHE.remove(key);
System.out.println("==========从缓存中删除" + key + "成功===============");
}
TOKEN_TICKET_CACHE.put(key, accessTocken);
cacheAddTime = String.valueOf(accessTocken.getAddTime());// 更新缓存修改的时间
System.out.println("==========更新缓存中" + key + "成功===============");
}
/**
* 发起https请求并获取结果
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
private static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
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();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
System.out.println("Weixin server connection timed out.");
} catch (Exception e) {
System.out.println("https request error:{}" + e.getMessage());
}
return jsonObject;
}
}
2、验证,进行签名的工具类。这个是官方提供。(不建议自己写)
text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.solian.web.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
class Sign {
public static Map<String, String> sign(String jsapi_ticket, String url) {
Map<String, String> ret = new HashMap<String, String>();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + jsapi_ticket +
"&noncestr=" + nonce_str +
"×tamp=" + timestamp +
"&url=" + url;
System.out.println(string1);
try
{
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
ret.put("url", url);
ret.put("jsapi_ticket", jsapi_ticket);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", timestamp);
ret.put("signature", signature);
return ret;
}
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
3.Token类。主要是做存储。因为官方微信有一个次数的限制,和有效期限制。。。所以这里用到了一个存储类。做缓存使用
text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.solian.web.bean;
/**
* @author wukaikai
* 微信通用(限制为每日只可以调取2000次)
* token(有效期2个小时7200秒)获取和ticket缓存
* 为了减少频繁的刷微信,导致微信那边限制。给项目带来不必要的损失
*
*/
public class Token {
/**
* token
*/
private String token;
/**
* 生成的ticket
*/
private String ticket;
/**
* 过期时间,自己定义为了不影响项目的正常运行,我这里定位3600秒
*/
private Long expiresTime;
/**
* 增加时间
*/
private Long addTime;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public Long getExpiresTime() {
return expiresTime;
}
public void setExpiresTime(Long expiresTime) {
this.expiresTime = expiresTime;
}
public Long getAddTime() {
return addTime;
}
public void setAddTime(Long addTime) {
this.addTime = addTime;
}
}





评论
登录后即可评论
分享你的想法,与作者互动
暂无评论