|
package com.ekexiu.push.service;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.jfw.apt.web.annotation.Path;
import org.jfw.apt.web.annotation.operate.Get;
import org.jfw.apt.web.annotation.operate.Post;
import org.jfw.util.ConstData;
import org.jfw.util.io.IoUtil;
import org.jfw.util.json.JsonService;
import org.jfw.util.log.LogFactory;
import org.jfw.util.log.Logger;
import org.jfw.util.reflect.TypeReference;
import com.ekexiu.operation.push.getui.Message;
import com.ekexiu.operation.push.getui.MsgCondition;
import com.ekexiu.operation.push.getui.MsgStyle;
import com.ekexiu.operation.push.getui.NotificationMessage;
@Path("/push")
public class PushService {
private static final Logger log =LogFactory.getLog(PushService.class);
private static Type RES_TYPE = new TypeReference<Map<String, Object>>() {
}.getType();
private static final MsgCondition android=new MsgCondition("phonetype",new String[]{"ANDROID"},1);
private static final MsgCondition ios=new MsgCondition("phonetype",new String[]{"IOS"},1);
private static final MsgCondition[] onlyAndroid = new MsgCondition[]{android};
private static final MsgCondition[] onlyIos = new MsgCondition[]{ios};
private static Map<String, String> CONTENT_TYPE = new HashMap<String, String>();
private static Map<String, String> TOKEN_MAP = new ConcurrentHashMap<String, String>();
private static Map<String, String> ERR_MAP = new HashMap<String, String>();
final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
// UiIGJTfKNR8oXb8apYdGh3
private String secret = "U96j677DHoA1Pv5X0mxMU9";
private String appKey = "48nq7d7yHu8dgbzVHuisp6";
private String appId = "TUdvbnxu1c97r6Fb6cUy57";
private int timeout = 0;
private boolean enable = false;
private String token = null;
private long lastBuildTime = 0;
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getAppKey() {
return appKey;
}
public void setAppKey(String appKey) {
this.appKey = appKey;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
private String buildSign(long flag) {
String p = this.appKey + flag + this.secret;
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(p.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte b : messageDigest.digest()) {
sb.append(digits[(b & 0xf0) >> 4]);
sb.append(digits[b & 0xf]);
}
return sb.toString();
} catch (Exception e) {
throw new RuntimeException("jdk unsupported sh256???????????", e);
}
}
private void checkResult(Map<String, Object> ret) {
Object obj = ret.get("result");
if ("ok".equals(obj))
return;
String errMsg = null;
errMsg = ERR_MAP.get(obj);
if (errMsg == null)
errMsg = "其他错误";
log.error("调用用个推restApi,返回结果错误:" + obj + ":" + errMsg);
throw new RuntimeException("调用用个推restApi,返回结果错误:" + obj + ":" + errMsg);
}
// private void checkToken() {
// if (this.token == null) {
// log.error("token is null");
// throw new RuntimeException("token is null");
// }
// }
public String allocateRequesstId() {
UUID uuid = UUID.randomUUID();
return "A" + Long.toString(uuid.getLeastSignificantBits(), 36) + "_" + Long.toString(uuid.getMostSignificantBits(), 36);
}
private void buildToken() {
long time = System.currentTimeMillis();
String sign = this.buildSign(time);
StringBuilder sb = new StringBuilder();
sb.append("{\"sign\":\"").append(sign).append("\",\"timestamp\":\"").append(time).append("\",\"appkey\":\"").append(this.appKey).append("\"}");
try {
Map<String, Object> ret = post("https://restapi.getui.com/v1/" + this.appId + "/auth_sign", CONTENT_TYPE, sb.toString().getBytes(ConstData.UTF8));
this.checkResult(ret);
String otoken = (String) ret.get("auth_token");
if (otoken == null) {
throw new RuntimeException("返回token is null");
}
this.token = otoken;
this.lastBuildTime = System.currentTimeMillis();
TOKEN_MAP.put("authtoken", this.token);
} catch (Exception e) {
this.token = null;
log.error("build token error", e);
}
}
public void refresh() {
if ((this.token != null) && ((System.currentTimeMillis() - this.lastBuildTime) < (24 * 60 * 60 * 1000 - 5000))) {
return;
}
if(enable) this.buildToken();
}
public Map<String, Object> post(String url, Map<String, String> header, byte[] data) throws IOException {
HttpURLConnection connection = getConnection(url);
try {
connection.setRequestMethod("POST");
connection.setUseCaches(false);
for (Map.Entry<String, String> entry : header.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
connection.setDoOutput(true);
connection.setDoInput(true);
if (this.timeout > 0) {
connection.setConnectTimeout(this.timeout);
connection.setReadTimeout(this.timeout);
}
connection.setFixedLengthStreamingMode(data.length);
OutputStream out = connection.getOutputStream();
try {
out.write(data);
} finally {
out.close();
}
int code = connection.getResponseCode();
if (code == 200) {
InputStream in = null;
byte[] resData = null;
try {
in = connection.getInputStream();
resData = IoUtil.readStream(in, false);
} catch (IOException e) {
log.error("Error read http response stream,url:" + url, e);
throw new IOException("Error read http response stream");
} finally {
if (null != in)
IoUtil.close(in);
}
try {
return JsonService.fromJson(new String(resData, ConstData.UTF8), RES_TYPE);
} catch (Exception e) {
log.error("invalid response data,url:" + url, e);
throw new IOException("invalid response data", e);
}
}
log.error("Error http reponse status:" + code + ",url:" + url);
throw new IOException("Error http reponse status:" + code);
} finally {
connection.disconnect();
}
}
@Path("/bindAlias")
@Post
public boolean bindAlias(String alias, String cid) {
String url = "https://restapi.getui.com/v1/" + this.appId + "/bind_alias";
StringBuilder sb = new StringBuilder();
sb.append("{\"alias_list\" : [{\"cid\":\"").append(cid).append("\",\"alias\":\"").append(alias).append("\" }]}");
try {
Map<String, Object> ret = post(url, TOKEN_MAP, sb.toString().getBytes(ConstData.UTF8));
this.checkResult(ret);
return true;
} catch (IOException e) {
log.error("bind alias error[cid:" + cid + ",alias:" + alias + "]", e);
return false;
}
}
@Get
@Path("/token")
public String getToken(){
String ret = this.token;
if(ret!=null){
int len = ret.length();
Random random = new Random();
int idx = random.nextInt(len-1);
if(idx<1 || idx >=len){
return ret;
}
return ret.substring(idx)+ret.substring(0,idx)+"_"+idx;
}
return null;
}
@Path("/bindTags")
@Post
public boolean bindTags(String[] tags, String cid) {
String url = "https://restapi.getui.com/v1/" + this.appId + "/set_tags";
Map<String,Object> msg = new HashMap<String,Object>();
msg.put("cid",cid);
msg.put("tag_list",tags);
try {
Map<String, Object> ret = post(url, TOKEN_MAP, JsonService.toJson(msg).getBytes(ConstData.UTF8));
this.checkResult(ret);
return true;
} catch (IOException e) {
log.error("bind tags error:"+JsonService.toJson(msg), e);
return false;
}
}
@Path("/applyBadge")
@Get
public void applyBadge(int badge,String cid,String devtoken){
String url = "https://restapi.getui.com/v1/" + this.appId + "/set_badge";
StringBuilder sb = new StringBuilder();
sb.append("{\"badge\":").append(badge).append(",\"cid_list\":[\"").append(cid).append("\"],\"devicetoken_list\":[\"").append(devtoken).append("\"]}");
System.out.println(sb.toString());
try {
Map<String, Object> ret = post(url, TOKEN_MAP, sb.toString().getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (IOException e) {
log.error("apply badge error[cid:" + cid + ",devtoken:" + devtoken + "]", e);
}
}
private Map<String,Object > createIosMessage(String title,String content,String payload){
Map<String,Object> ret = new HashMap<String,Object>();
Map<String,Object> message= new HashMap<String,Object>();
ret.put("message", message);
message.put("appkey",this.appKey);
message.put("is_offline",true);
message.put("msgtype", "transmission");
Map<String,Object> transmission = new HashMap<String,Object>();
ret.put("transmission", transmission);
transmission.put("transmission_type", false);
transmission.put("transmission_content", payload);
Map<String,Object> pushInfo = new HashMap<String,Object>();
ret.put("push_info", pushInfo);
Map<String,Object> aps = new HashMap<String,Object>();
pushInfo.put("aps",aps);
Map<String,Object> alert = new HashMap<String,Object>();
aps.put("alert", alert);
alert.put("title", title);
alert.put("body",content);
aps.put("autoBadge","+1");
aps.put("content-available",1);
aps.put("sound","default");
pushInfo.put("payload",payload);
ret.put("condition", onlyIos);
return ret;
}
private Map<String,Object > createAndriodMessage(String title,String content,String payload){
Map<String,Object> ret = new HashMap<String,Object>();
Message message = new Message();
ret.put("message", message);
message.setAppKey(this.appKey);
message.setMsgtype("notification");
message.setOffline(true);
message.setOfflineExpireTime(2*60*1000);
message.setPushNetworkType(0);
NotificationMessage notification = new NotificationMessage();
ret.put("notification", notification);
notification.setTransmissionType(true);
notification.setTransmissionContent(payload);
MsgStyle style = new MsgStyle();
notification.setStyle(style);
style.setType(0);
style.setClearable(true);
style.setRing(true);
style.setText(content);
style.setTitle(title);
style.setVibrate(true);
ret.put("condition", onlyAndroid);
return ret;
}
public void toApp(String title,String content,Object payload){
String url = "https://restapi.getui.com/v1/"+this.appId+"/push_app";
String pl_str = JsonService.toJson(payload);
Map<String,Object> andriodMessage = this.createAndriodMessage(title, content, pl_str);
Map<String,Object> iosMessage = this.createIosMessage(title, content, pl_str);
andriodMessage.put("requestid",this.allocateRequesstId());
iosMessage.put("requestid",this.allocateRequesstId());
// System.out.println(JsonService.toJson(andriodMessage));
// System.out.println(JsonService.toJson(iosMessage));
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(andriodMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(iosMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
}
private MsgCondition createTagCondition(String[] tags){
return new MsgCondition("tag", tags, 0);
}
private void addTag(Map<String,Object> msg,MsgCondition tagCondition){
MsgCondition[] mcs = (MsgCondition[]) msg.get("condition");
MsgCondition[] mcsn = new MsgCondition[mcs.length+1];
System.arraycopy(mcs,0,mcsn, 0,mcs.length);
mcsn[mcs.length] = tagCondition;
msg.put("condition", mcsn);
}
public void pushWithTag(String title,String content,Object payload,String[] tags){
String url = "https://restapi.getui.com/v1/"+this.appId+"/push_app";
String pl_str = JsonService.toJson(payload);
Map<String,Object> andriodMessage = this.createAndriodMessage(title, content, pl_str);
Map<String,Object> iosMessage = this.createIosMessage(title, content, pl_str);
andriodMessage.put("requestid",this.allocateRequesstId());
iosMessage.put("requestid",this.allocateRequesstId());
MsgCondition tagC = this.createTagCondition(tags);
addTag(andriodMessage, tagC);
addTag(iosMessage, tagC);
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(andriodMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(iosMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
}
public void pushWithCid(String title,String content,Object payload,String cid){
String url = "https://restapi.getui.com/v1/"+this.appId+"/push_single";
String pl_str = JsonService.toJson(payload);
Map<String,Object> androidMessage = this.createAndriodMessage(title, content, pl_str);
Map<String,Object> iosMessage = this.createIosMessage(title, content, pl_str);
androidMessage.put("requestid",this.allocateRequesstId());
androidMessage.put("cid",cid);
iosMessage.put("requestid",this.allocateRequesstId());
iosMessage.put("cid",cid);
// System.out.println(JsonService.toJson(androidMessage));
// System.out.println(JsonService.toJson(iosMessage));
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(androidMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(iosMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
}
public void pushWithAlias(String title,String content,Object payload,String alias){
String url = "https://restapi.getui.com/v1/"+this.appId+"/push_single";
String pl_str = JsonService.toJson(payload);
Map<String,Object> androidMessage = this.createAndriodMessage(title, content, pl_str);
Map<String,Object> iosMessage = this.createIosMessage(title, content, pl_str);
androidMessage.put("requestid",this.allocateRequesstId());
androidMessage.put("alias","A_"+alias);
iosMessage.put("requestid",this.allocateRequesstId());
iosMessage.put("alias","I_"+alias);
// System.out.println(JsonService.toJson(androidMessage));
// System.out.println(JsonService.toJson(iosMessage));
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(androidMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
try {
Map<String,Object> ret = post(url, TOKEN_MAP,JsonService.toJson(iosMessage).getBytes(ConstData.UTF8));
this.checkResult(ret);
} catch (Exception e) {
log.error("send app message error",e);
}
}
public static HttpURLConnection getConnection(String urlString) throws IOException {
URL url = new URL(urlString);
HttpURLConnection conn = null;
conn = (HttpURLConnection) url.openConnection();
String protocal = url.getProtocol();
if ((protocal != null) && (protocal.equalsIgnoreCase("https"))) {
try {
HttpsURLConnection httpsConn = (HttpsURLConnection) conn;
httpsConn.setSSLSocketFactory(getTrustAllSSLContext().getSocketFactory());
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
};
httpsConn.setHostnameVerifier(hv);
} catch (Exception e) {
log.warn("init httpmanager error", e);
throw new RuntimeException("init httpmanager error", e);
}
}
return conn;
}
public static SSLContext getTrustAllSSLContext() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager trust = new CustomTrustManager();
trustAllCerts[0] = trust;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
return sc;
}
static class CustomTrustManager implements TrustManager, X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
}
}
static {
CONTENT_TYPE.put("Content-Type", "application/json");
TOKEN_MAP.putAll(CONTENT_TYPE);
TOKEN_MAP.put("authtoken", "ef60d2aa2bc3193fc99a99ef43906cee70658156dfb41156acc35f7e7b7fb3dd");
ERR_MAP.put("no_msg", "没有消息体");
ERR_MAP.put("alias_error", "找不到别名");
ERR_MAP.put("black_ip", "黑名单ip");
ERR_MAP.put("sign_error", "鉴权失败");
ERR_MAP.put("pushnum_overlimit", "推送次数超限");
ERR_MAP.put("no_appid", "找不到appid");
ERR_MAP.put("no_user", "找不到对应用户");
ERR_MAP.put("too_frequent", "推送过于频繁");
ERR_MAP.put("sensitive_word", "有敏感词出现");
ERR_MAP.put("appid_notmatch", "appid与cid或者appkey不匹配");
ERR_MAP.put("not_auth", "用户没有鉴权");
ERR_MAP.put("black_appid", "黑名单app");
ERR_MAP.put("invalid_param", "参数检验不通过");
ERR_MAP.put("alias_notbind", "别名没有绑定cid");
ERR_MAP.put("tag_over_limit", "tag个数超限");
ERR_MAP.put("successed_online", "在线下发");
ERR_MAP.put("successed_offline", "离线下发");
ERR_MAP.put("taginvalid_or_noauth", "tag无效或者没有使用权限");
ERR_MAP.put("no_valid_push", "没有有效下发");
ERR_MAP.put("successed_ignore", "忽略非活跃用户");
ERR_MAP.put("no_taskid", "找不到taskid");
}
public static void main(String[] args) throws Exception {
PushService s = new PushService();
// s.buildToken();
// s.checkToken();
TOKEN_MAP.put("authtoken", "c3bbeb7aac006871f228d48e5da846933bfd2109e1d20fac3c8c0a3f3ccebd7d");
long l = System.currentTimeMillis();
//s.toApp("title_" + l, "content_" + l, "payload_" + l);
s.pushWithAlias("title_" + l, "content_" + l, "payload_" + l,"A21F6D7BD4C549A1A2ABC415DE7701BD");
System.out.println(l);
// s.applyBadge(1, "f293af1f1cc043185ee9d921b63c4807", "D380AD6865B61F4D179DBB208EE3C7268A672AB9821385050596608A186F6023");
// for(int i = 0 ;i < 100;++i){
// UUID uuid= UUID.randomUUID();
// System.out.println( "A"+Long.toString(
// uuid.getLeastSignificantBits(),36)+"_"+Long.toString(uuid.getMostSignificantBits(),
// 36));
// }
}
}
|