|
@ -0,0 +1,303 @@
|
|
1
|
package com.ekexiu.push.service;
|
|
2
|
|
|
3
|
import java.io.IOException;
|
|
4
|
import java.io.InputStream;
|
|
5
|
import java.io.OutputStream;
|
|
6
|
import java.lang.reflect.Type;
|
|
7
|
import java.net.HttpURLConnection;
|
|
8
|
import java.net.URL;
|
|
9
|
import java.security.MessageDigest;
|
|
10
|
import java.security.cert.CertificateException;
|
|
11
|
import java.security.cert.X509Certificate;
|
|
12
|
import java.util.HashMap;
|
|
13
|
import java.util.Map;
|
|
14
|
import java.util.concurrent.ConcurrentHashMap;
|
|
15
|
|
|
16
|
import javax.net.ssl.HostnameVerifier;
|
|
17
|
import javax.net.ssl.HttpsURLConnection;
|
|
18
|
import javax.net.ssl.SSLContext;
|
|
19
|
import javax.net.ssl.SSLSession;
|
|
20
|
import javax.net.ssl.TrustManager;
|
|
21
|
import javax.net.ssl.X509TrustManager;
|
|
22
|
|
|
23
|
import org.jfw.apt.web.annotation.Path;
|
|
24
|
import org.jfw.apt.web.annotation.operate.Post;
|
|
25
|
import org.jfw.util.ConstData;
|
|
26
|
import org.jfw.util.io.IoUtil;
|
|
27
|
import org.jfw.util.json.JsonService;
|
|
28
|
import org.jfw.util.reflect.TypeReference;
|
|
29
|
|
|
30
|
@Path("/push")
|
|
31
|
public class PushService {
|
|
32
|
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(PushService.class);
|
|
33
|
|
|
34
|
private static Type RES_TYPE = new TypeReference<Map<String, Object>>() {
|
|
35
|
}.getType();
|
|
36
|
|
|
37
|
private static Map<String, String> CONTENT_TYPE = new HashMap<String, String>();
|
|
38
|
private static Map<String,String> TOKEN_MAP = new ConcurrentHashMap<String,String>();
|
|
39
|
private static Map<String, String> ERR_MAP = new HashMap<String, String>();
|
|
40
|
|
|
41
|
final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
|
42
|
// UiIGJTfKNR8oXb8apYdGh3
|
|
43
|
private String secret = "UiIGJTfKNR8oXb8apYdGh3";
|
|
44
|
private String appKey = "FnwUFkK2nt9BLgQ0XjtOl4";
|
|
45
|
private String appId = "G3L3npt6LU92DZHkdNxuL4";
|
|
46
|
private int timeout = 0;
|
|
47
|
|
|
48
|
private String token = null;
|
|
49
|
private long lastBuildTime = 0;
|
|
50
|
|
|
51
|
public String getSecret() {
|
|
52
|
return secret;
|
|
53
|
}
|
|
54
|
|
|
55
|
public void setSecret(String secret) {
|
|
56
|
this.secret = secret;
|
|
57
|
}
|
|
58
|
|
|
59
|
public String getAppKey() {
|
|
60
|
return appKey;
|
|
61
|
}
|
|
62
|
|
|
63
|
public void setAppKey(String appKey) {
|
|
64
|
this.appKey = appKey;
|
|
65
|
}
|
|
66
|
|
|
67
|
public String getAppId() {
|
|
68
|
return appId;
|
|
69
|
}
|
|
70
|
|
|
71
|
public void setAppId(String appId) {
|
|
72
|
this.appId = appId;
|
|
73
|
}
|
|
74
|
|
|
75
|
public int getTimeout() {
|
|
76
|
return timeout;
|
|
77
|
}
|
|
78
|
|
|
79
|
public void setTimeout(int timeout) {
|
|
80
|
this.timeout = timeout;
|
|
81
|
}
|
|
82
|
|
|
83
|
private String buildSign(long flag) {
|
|
84
|
String p = this.appKey + flag + this.secret;
|
|
85
|
MessageDigest messageDigest;
|
|
86
|
try {
|
|
87
|
messageDigest = MessageDigest.getInstance("SHA-256");
|
|
88
|
messageDigest.update(p.getBytes("UTF-8"));
|
|
89
|
StringBuilder sb = new StringBuilder();
|
|
90
|
for (byte b : messageDigest.digest()) {
|
|
91
|
sb.append(digits[(b & 0xf0) >> 4]);
|
|
92
|
sb.append(digits[b & 0xf]);
|
|
93
|
}
|
|
94
|
return sb.toString();
|
|
95
|
} catch (Exception e) {
|
|
96
|
throw new RuntimeException("jdk unsupported sh256???????????", e);
|
|
97
|
}
|
|
98
|
}
|
|
99
|
|
|
100
|
private void checkResult(Map<String, Object> ret) {
|
|
101
|
Object obj = ret.get("result");
|
|
102
|
if ("ok".equals(obj))
|
|
103
|
return;
|
|
104
|
String errMsg = null;
|
|
105
|
errMsg = ERR_MAP.get(obj);
|
|
106
|
if (errMsg == null)
|
|
107
|
errMsg = "其他错误";
|
|
108
|
log.error("调用用个推restApi,返回结果错误:" + obj + ":" + errMsg);
|
|
109
|
throw new RuntimeException("调用用个推restApi,返回结果错误:" + obj + ":" + errMsg);
|
|
110
|
}
|
|
111
|
|
|
112
|
private void checkToken()
|
|
113
|
{
|
|
114
|
if(this.token==null){
|
|
115
|
log.error("token is null");
|
|
116
|
throw new RuntimeException("token is null");
|
|
117
|
}
|
|
118
|
}
|
|
119
|
|
|
120
|
private void buildToken() {
|
|
121
|
long time = System.currentTimeMillis();
|
|
122
|
String sign = this.buildSign(time);
|
|
123
|
StringBuilder sb = new StringBuilder();
|
|
124
|
sb.append("{\"sign\":\"").append(sign).append("\",\"timestamp\":\"").append(time).append("\",\"appkey\":\"").append(this.appKey).append("\"}");
|
|
125
|
try {
|
|
126
|
Map<String, Object> ret = post("https://restapi.getui.com/v1/" + this.appId + "/auth_sign", CONTENT_TYPE, sb.toString().getBytes(ConstData.UTF8));
|
|
127
|
this.checkResult(ret);
|
|
128
|
String otoken = (String) ret.get("auth_token");
|
|
129
|
if (otoken == null) {
|
|
130
|
throw new RuntimeException("返回token is null");
|
|
131
|
}
|
|
132
|
this.token = otoken;
|
|
133
|
this.lastBuildTime = System.currentTimeMillis();
|
|
134
|
TOKEN_MAP.put("authtoken", this.token);
|
|
135
|
} catch (Exception e) {
|
|
136
|
this.token = null;
|
|
137
|
log.error("build token error", e);
|
|
138
|
}
|
|
139
|
}
|
|
140
|
|
|
141
|
public void refresh(){
|
|
142
|
if((this.token!=null) && ((System.currentTimeMillis() - this.lastBuildTime) < (24*60 *60*1000-5000))){
|
|
143
|
return ;
|
|
144
|
}
|
|
145
|
this.buildToken();
|
|
146
|
}
|
|
147
|
|
|
148
|
public Map<String, Object> post(String url, Map<String, String> header, byte[] data) throws IOException {
|
|
149
|
HttpURLConnection connection = getConnection(url);
|
|
150
|
try {
|
|
151
|
connection.setRequestMethod("POST");
|
|
152
|
connection.setUseCaches(false);
|
|
153
|
for (Map.Entry<String, String> entry : header.entrySet()) {
|
|
154
|
connection.setRequestProperty(entry.getKey(), entry.getValue());
|
|
155
|
}
|
|
156
|
connection.setDoOutput(true);
|
|
157
|
connection.setDoInput(true);
|
|
158
|
if (this.timeout > 0) {
|
|
159
|
connection.setConnectTimeout(this.timeout);
|
|
160
|
connection.setReadTimeout(this.timeout);
|
|
161
|
}
|
|
162
|
connection.setFixedLengthStreamingMode(data.length);
|
|
163
|
OutputStream out = connection.getOutputStream();
|
|
164
|
try {
|
|
165
|
out.write(data);
|
|
166
|
} finally {
|
|
167
|
out.close();
|
|
168
|
}
|
|
169
|
int code = connection.getResponseCode();
|
|
170
|
|
|
171
|
if (code == 200) {
|
|
172
|
InputStream in = null;
|
|
173
|
byte[] resData = null;
|
|
174
|
try {
|
|
175
|
in = connection.getInputStream();
|
|
176
|
resData = IoUtil.readStream(in, false);
|
|
177
|
} catch (IOException e) {
|
|
178
|
log.error("Error read http response stream,url:" + url, e);
|
|
179
|
throw new IOException("Error read http response stream");
|
|
180
|
} finally {
|
|
181
|
if (null != in)
|
|
182
|
IoUtil.close(in);
|
|
183
|
}
|
|
184
|
try {
|
|
185
|
return JsonService.fromJson(new String(resData, ConstData.UTF8), RES_TYPE);
|
|
186
|
} catch (Exception e) {
|
|
187
|
log.error("invalid response data,url:" + url, e);
|
|
188
|
throw new IOException("invalid response data", e);
|
|
189
|
}
|
|
190
|
}
|
|
191
|
log.error("Error http reponse status:" + code + ",url:" + url);
|
|
192
|
throw new IOException("Error http reponse status:" + code);
|
|
193
|
} finally {
|
|
194
|
connection.disconnect();
|
|
195
|
}
|
|
196
|
}
|
|
197
|
|
|
198
|
|
|
199
|
|
|
200
|
@Path("/bindAlias")
|
|
201
|
@Post
|
|
202
|
public boolean bindAlias(String alias,String cid){
|
|
203
|
String url = "https://restapi.getui.com/v1/"+this.appId+"/bind_alias";
|
|
204
|
StringBuilder sb = new StringBuilder();
|
|
205
|
sb.append("{\"alias_list\" : [{\"cid\":\"").append(cid).append("\",\"alias\":\"").append(alias).append("\" }]}");
|
|
206
|
try {
|
|
207
|
Map<String,Object> ret = post(url, TOKEN_MAP,sb.toString().getBytes(ConstData.UTF8));
|
|
208
|
this.checkResult(ret);
|
|
209
|
return true;
|
|
210
|
} catch (IOException e) {
|
|
211
|
log.error("bind alias error[cid:"+cid+",alias:"+alias+"]",e);
|
|
212
|
return false;
|
|
213
|
}
|
|
214
|
}
|
|
215
|
|
|
216
|
|
|
217
|
|
|
218
|
public static HttpURLConnection getConnection(String urlString) throws IOException {
|
|
219
|
URL url = new URL(urlString);
|
|
220
|
HttpURLConnection conn = null;
|
|
221
|
conn = (HttpURLConnection) url.openConnection();
|
|
222
|
String protocal = url.getProtocol();
|
|
223
|
if ((protocal != null) && (protocal.equalsIgnoreCase("https"))) {
|
|
224
|
try {
|
|
225
|
HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
|
|
226
|
httpsConn.setSSLSocketFactory(getTrustAllSSLContext().getSocketFactory());
|
|
227
|
|
|
228
|
HostnameVerifier hv = new HostnameVerifier() {
|
|
229
|
public boolean verify(String arg0, SSLSession arg1) {
|
|
230
|
return true;
|
|
231
|
}
|
|
232
|
};
|
|
233
|
httpsConn.setHostnameVerifier(hv);
|
|
234
|
} catch (Exception e) {
|
|
235
|
log.warn("init httpmanager error", e);
|
|
236
|
throw new RuntimeException("init httpmanager error", e);
|
|
237
|
}
|
|
238
|
}
|
|
239
|
return conn;
|
|
240
|
}
|
|
241
|
|
|
242
|
public static SSLContext getTrustAllSSLContext() throws Exception {
|
|
243
|
TrustManager[] trustAllCerts = new TrustManager[1];
|
|
244
|
TrustManager trust = new CustomTrustManager();
|
|
245
|
trustAllCerts[0] = trust;
|
|
246
|
SSLContext sc = SSLContext.getInstance("SSL");
|
|
247
|
sc.init(null, trustAllCerts, null);
|
|
248
|
return sc;
|
|
249
|
}
|
|
250
|
|
|
251
|
static class CustomTrustManager implements TrustManager, X509TrustManager {
|
|
252
|
public X509Certificate[] getAcceptedIssuers() {
|
|
253
|
return null;
|
|
254
|
}
|
|
255
|
|
|
256
|
public boolean isServerTrusted(X509Certificate[] certs) {
|
|
257
|
return true;
|
|
258
|
}
|
|
259
|
|
|
260
|
public boolean isClientTrusted(X509Certificate[] certs) {
|
|
261
|
return true;
|
|
262
|
}
|
|
263
|
|
|
264
|
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
|
|
265
|
}
|
|
266
|
|
|
267
|
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
|
|
268
|
}
|
|
269
|
}
|
|
270
|
|
|
271
|
static {
|
|
272
|
CONTENT_TYPE.put("Content-Type", "application/json");
|
|
273
|
TOKEN_MAP.putAll(CONTENT_TYPE);
|
|
274
|
|
|
275
|
ERR_MAP.put("no_msg", "没有消息体");
|
|
276
|
ERR_MAP.put("alias_error", "找不到别名");
|
|
277
|
ERR_MAP.put("black_ip", "黑名单ip");
|
|
278
|
ERR_MAP.put("sign_error", "鉴权失败");
|
|
279
|
ERR_MAP.put("pushnum_overlimit", "推送次数超限");
|
|
280
|
ERR_MAP.put("no_appid", "找不到appid");
|
|
281
|
ERR_MAP.put("no_user", "找不到对应用户");
|
|
282
|
ERR_MAP.put("too_frequent", "推送过于频繁");
|
|
283
|
ERR_MAP.put("sensitive_word", "有敏感词出现");
|
|
284
|
ERR_MAP.put("appid_notmatch", "appid与cid或者appkey不匹配");
|
|
285
|
ERR_MAP.put("not_auth", "用户没有鉴权");
|
|
286
|
ERR_MAP.put("black_appid", "黑名单app");
|
|
287
|
ERR_MAP.put("invalid_param", "参数检验不通过");
|
|
288
|
ERR_MAP.put("alias_notbind", "别名没有绑定cid");
|
|
289
|
ERR_MAP.put("tag_over_limit", "tag个数超限");
|
|
290
|
ERR_MAP.put("successed_online", "在线下发");
|
|
291
|
ERR_MAP.put("successed_offline", "离线下发");
|
|
292
|
ERR_MAP.put("taginvalid_or_noauth", "tag无效或者没有使用权限");
|
|
293
|
ERR_MAP.put("no_valid_push", "没有有效下发");
|
|
294
|
ERR_MAP.put("successed_ignore", "忽略非活跃用户");
|
|
295
|
ERR_MAP.put("no_taskid", "找不到taskid");
|
|
296
|
}
|
|
297
|
|
|
298
|
public static void main(String[] args) throws Exception {
|
|
299
|
PushService s = new PushService();
|
|
300
|
s.buildToken();
|
|
301
|
s.checkToken();
|
|
302
|
}
|
|
303
|
}
|