commit push server

This commit is contained in:
heavyrain.lee
2019-01-18 21:41:21 +08:00
parent 903b9b947f
commit cc513446b9
63 changed files with 5896 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
package cn.wildfirechat.push;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PushApplication {
public static void main(String[] args) {
SpringApplication.run(PushApplication.class, args);
}
}

View File

@@ -0,0 +1,28 @@
package cn.wildfirechat.push;
import cn.wildfirechat.push.android.AndroidPushService;
import cn.wildfirechat.push.ios.IOSPushService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PushController {
@Autowired
private AndroidPushService mAndroidPushService;
@Autowired
private IOSPushService mIOSPushService;
@PostMapping(value = "/android/push", produces = "application/json;charset=UTF-8" )
public Object androidPush(@RequestBody PushMessage pushMessage) {
return mAndroidPushService.push(pushMessage);
}
@PostMapping(value = "/ios/push", produces = "application/json;charset=UTF-8" )
public Object iOSPush(@RequestBody PushMessage pushMessage) {
return mIOSPushService.push(pushMessage);
}
}

View File

@@ -0,0 +1,161 @@
package cn.wildfirechat.push;
public class PushMessage {
public String sender;
public String senderName;
public int convType;
public String target;
public String targetName;
public int line;
public int cntType;
public long serverTime;
//消息的类型普通消息通知栏voip要透传。
public int pushMessageType;
//推送类型android推送分为小米/华为/魅族等。ios分别为开发和发布。
public int pushType;
public String pushContent;
public int unReceivedMsg;
public int mentionedType;
public String packageName;
public String deviceToken;
public String voipDeviceToken;
public String language;
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getSenderName() {
return senderName;
}
public void setSenderName(String senderName) {
this.senderName = senderName;
}
public int getConvType() {
return convType;
}
public void setConvType(int convType) {
this.convType = convType;
}
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public String getTargetName() {
return targetName;
}
public void setTargetName(String targetName) {
this.targetName = targetName;
}
public int getLine() {
return line;
}
public void setLine(int line) {
this.line = line;
}
public int getCntType() {
return cntType;
}
public void setCntType(int cntType) {
this.cntType = cntType;
}
public long getServerTime() {
return serverTime;
}
public void setServerTime(long serverTime) {
this.serverTime = serverTime;
}
public int getPushMessageType() {
return pushMessageType;
}
public void setPushMessageType(int pushMessageType) {
this.pushMessageType = pushMessageType;
}
public int getPushType() {
return pushType;
}
public void setPushType(int pushType) {
this.pushType = pushType;
}
public String getPushContent() {
return pushContent;
}
public void setPushContent(String pushContent) {
this.pushContent = pushContent;
}
public int getUnReceivedMsg() {
return unReceivedMsg;
}
public void setUnReceivedMsg(int unReceivedMsg) {
this.unReceivedMsg = unReceivedMsg;
}
public int getMentionedType() {
return mentionedType;
}
public void setMentionedType(int mentionedType) {
this.mentionedType = mentionedType;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getDeviceToken() {
return deviceToken;
}
public void setDeviceToken(String deviceToken) {
this.deviceToken = deviceToken;
}
public String getVoipDeviceToken() {
return voipDeviceToken;
}
public void setVoipDeviceToken(String voipDeviceToken) {
this.voipDeviceToken = voipDeviceToken;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
}

View File

@@ -0,0 +1,7 @@
package cn.wildfirechat.push;
public interface PushMessageType {
int PUSH_MESSAGE_TYPE_NORMAL = 0;
int PUSH_MESSAGE_TYPE_VOIP_INVITE = 1;
int PUSH_MESSAGE_TYPE_VOIP_BYE = 2;
}

View File

@@ -0,0 +1,7 @@
package cn.wildfirechat.push.android;
import cn.wildfirechat.push.PushMessage;
public interface AndroidPushService {
Object push(PushMessage pushMessage);
}

View File

@@ -0,0 +1,45 @@
package cn.wildfirechat.push.android;
import cn.wildfirechat.push.PushMessage;
import cn.wildfirechat.push.android.hms.HMSPush;
import cn.wildfirechat.push.android.meizu.MeiZuPush;
import cn.wildfirechat.push.android.xiaomi.XiaomiPush;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AndroidPushServiceImpl implements AndroidPushService {
private static final Logger LOG = LoggerFactory.getLogger(AndroidPushServiceImpl.class);
@Autowired
private HMSPush hmsPush;
@Autowired
private MeiZuPush meiZuPush;
@Autowired
private XiaomiPush xiaomiPush;
@Override
public Object push(PushMessage pushMessage) {
LOG.info("Android push {}", new Gson().toJson(pushMessage));
switch (pushMessage.getPushType()) {
case AndroidPushType.ANDROID_PUSH_TYPE_XIAOMI:
xiaomiPush.push(pushMessage);
break;
case AndroidPushType.ANDROID_PUSH_TYPE_HUAWEI:
hmsPush.push(pushMessage);
break;
case AndroidPushType.ANDROID_PUSH_TYPE_MEIZU:
meiZuPush.push(pushMessage);
break;
default:
LOG.info("unknown push type");
break;
}
return "ok";
}
}

View File

@@ -0,0 +1,7 @@
package cn.wildfirechat.push.android;
public interface AndroidPushType {
int ANDROID_PUSH_TYPE_XIAOMI = 1;
int ANDROID_PUSH_TYPE_HUAWEI = 2;
int ANDROID_PUSH_TYPE_MEIZU = 3;
}

View File

@@ -0,0 +1,29 @@
package cn.wildfirechat.push.android.hms;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ConfigurationProperties(prefix="hms")
@PropertySource(value = "classpath:hms.properties")
public class HMSConfig {
private String appSecret;
private String appId;
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
}

View File

@@ -0,0 +1,136 @@
package cn.wildfirechat.push.android.hms;
import cn.wildfirechat.push.PushMessage;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.List;
@Component
public class HMSPush {
private static final Logger LOG = LoggerFactory.getLogger(HMSPush.class);
private static final String tokenUrl = "https://login.vmall.com/oauth2/token"; //获取认证Token的URL
private static final String apiUrl = "https://api.push.hicloud.com/pushsend.do"; //应用级消息下发API
private String accessToken;//下发通知消息的认证Token
private long tokenExpiredTime; //accessToken的过期时间
@Autowired
private HMSConfig mConfig;
//获取下发通知消息的认证Token
private void refreshToken() throws IOException {
LOG.info("hms refresh token");
String msgBody = MessageFormat.format(
"grant_type=client_credentials&client_secret={0}&client_id={1}",
URLEncoder.encode(mConfig.getAppSecret(), "UTF-8"), mConfig.getAppId());
String response = httpPost(tokenUrl, msgBody, 5000, 5000);
JSONObject obj = JSONObject.parseObject(response);
accessToken = obj.getString("access_token");
tokenExpiredTime = System.currentTimeMillis() + obj.getLong("expires_in") - 5*60*1000;
LOG.info("hms refresh token with result {}", response);
}
//发送Push消息
public void push(PushMessage pushMessage) {
if (tokenExpiredTime <= System.currentTimeMillis()) {
try {
refreshToken();
} catch (IOException e) {
e.printStackTrace();
}
}
/*PushManager.requestToken为客户端申请token的方法可以调用多次以防止申请token失败*/
/*PushToken不支持手动编写需使用客户端的onToken方法获取*/
JSONArray deviceTokens = new JSONArray();//目标设备Token
deviceTokens.add(pushMessage.getDeviceToken());
JSONObject msg = new JSONObject();
msg.put("type", 1);//3: 通知栏消息,异步透传消息请根据接口文档设置
msg.put("body", new Gson().toJson(pushMessage));//通知栏消息body内容
JSONObject hps = new JSONObject();//华为PUSH消息总结构体
hps.put("msg", msg);
JSONObject payload = new JSONObject();
payload.put("hps", hps);
LOG.info("send push to HMS {}", payload);
try {
String postBody = MessageFormat.format(
"access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
URLEncoder.encode(accessToken,"UTF-8"),
URLEncoder.encode("openpush.message.api.send","UTF-8"),
URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000),"UTF-8"),
URLEncoder.encode(deviceTokens.toString(),"UTF-8"),
URLEncoder.encode(payload.toString(),"UTF-8"));
String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + mConfig.getAppId() + "\"}", "UTF-8");
String response = httpPost(postUrl, postBody, 5000, 5000);
LOG.info("Push to {} response {}", pushMessage.getDeviceToken(), response);
} catch (IOException e) {
e.printStackTrace();
LOG.info("Push to {} with exception", pushMessage.getDeviceToken(), e);
}
}
public String httpPost(String httpUrl, String data, int connectTimeout, int readTimeout) throws IOException {
OutputStream outPut = null;
HttpURLConnection urlConnection = null;
InputStream in = null;
try {
URL url = new URL(httpUrl);
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
urlConnection.setConnectTimeout(connectTimeout);
urlConnection.setReadTimeout(readTimeout);
urlConnection.connect();
// POST data
outPut = urlConnection.getOutputStream();
outPut.write(data.getBytes("UTF-8"));
outPut.flush();
// read response
if (urlConnection.getResponseCode() < 400) {
in = urlConnection.getInputStream();
} else {
in = urlConnection.getErrorStream();
}
List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
StringBuffer strBuf = new StringBuffer();
for (String line : lines) {
strBuf.append(line);
}
LOG.info(strBuf.toString());
return strBuf.toString();
}
finally {
IOUtils.closeQuietly(outPut);
IOUtils.closeQuietly(in);
if (urlConnection != null) {
urlConnection.disconnect();
}
}
}
}

View File

@@ -0,0 +1,29 @@
package cn.wildfirechat.push.android.meizu;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ConfigurationProperties(prefix="meizu")
@PropertySource(value = "classpath:meizu.properties")
public class MeiZuConfig {
private String appSecret;
private long appId;
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
}

View File

@@ -0,0 +1,68 @@
package cn.wildfirechat.push.android.meizu;
import cn.wildfirechat.push.PushMessage;
import com.meizu.push.sdk.server.IFlymePush;
import com.meizu.push.sdk.server.constant.ResultPack;
import com.meizu.push.sdk.server.model.push.PushResult;
import com.meizu.push.sdk.server.model.push.VarnishedMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class MeiZuPush {
private static final Logger LOG = LoggerFactory.getLogger(MeiZuPush.class);
private IFlymePush flymePush;
@PostConstruct
public void init() {
this.flymePush = new IFlymePush(mConfig.getAppSecret());
}
@Autowired
private MeiZuConfig mConfig;
public void push(PushMessage pushMessage) {
//组装透传消息
VarnishedMessage message = new VarnishedMessage.Builder()
.appId(mConfig.getAppId())
.title("WildfireChat")
.content(pushMessage.pushContent)
.validTime(1)
.build();
//目标用户
List<String> pushIds = new ArrayList<String>();
pushIds.add(pushMessage.getDeviceToken());
try {
// 1 调用推送服务
ResultPack<PushResult> result = flymePush.pushMessage(message, pushIds);
if (result.isSucceed()) {
// 2 调用推送服务成功 其中map为设备的具体推送结果一般业务针对超速的code类型做处理
PushResult pushResult = result.value();
String msgId = pushResult.getMsgId();//推送消息ID用于推送流程明细排查
Map<String, List<String>> targetResultMap = pushResult.getRespTarget();//推送结果全部推送成功则map为empty
LOG.info("push result:" + pushResult);
if (targetResultMap != null && !targetResultMap.isEmpty()) {
System.err.println("push fail token:" + targetResultMap);
}
} else {
// 调用推送接口服务异常 eg: appId、appKey非法、推送消息非法.....
// result.code(); //服务异常码
// result.comment();//服务异常描述
LOG.info(String.format("pushMessage error code:%s comment:%s", result.code(), result.comment()));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,20 @@
package cn.wildfirechat.push.android.xiaomi;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ConfigurationProperties(prefix="xiaomi")
@PropertySource(value = "classpath:xiaomi.properties")
public class XiaomiConfig {
private String appSecret;
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
}

View File

@@ -0,0 +1,71 @@
package cn.wildfirechat.push.android.xiaomi;
import cn.wildfirechat.push.PushMessage;
import cn.wildfirechat.push.PushMessageType;
import com.google.gson.Gson;
import com.xiaomi.xmpush.server.Constants;
import com.xiaomi.xmpush.server.Message;
import com.xiaomi.xmpush.server.Result;
import com.xiaomi.xmpush.server.Sender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.json.simple.parser.ParseException;
import java.io.IOException;
import static com.xiaomi.xmpush.server.Message.NOTIFY_TYPE_ALL;
@Component
public class XiaomiPush {
private static final Logger LOG = LoggerFactory.getLogger(XiaomiPush.class);
@Autowired
private XiaomiConfig mConfig;
public void push(PushMessage pushMessage) {
Constants.useOfficial();
Sender sender = new Sender(mConfig.getAppSecret());
Message message;
if(pushMessage.pushMessageType != PushMessageType.PUSH_MESSAGE_TYPE_NORMAL) {
//voip
long timeToLive = 60 * 1000; // 1 min
message = new Message.Builder()
.payload(new Gson().toJson(pushMessage))
.restrictedPackageName(pushMessage.getPackageName())
.passThrough(1) //透传
.timeToLive(timeToLive)
.enableFlowControl(false)
.build();
} else {
long timeToLive = 600 * 1000;//10 min
message = new Message.Builder()
.payload(new Gson().toJson(pushMessage))
.title("新消息提醒")
.description(pushMessage.pushContent)
.notifyType(NOTIFY_TYPE_ALL)
.restrictedPackageName(pushMessage.getPackageName())
.passThrough(0)
.timeToLive(timeToLive)
.enableFlowControl(true)
.build();
}
Result result = null;
try {
result = sender.send(message, pushMessage.getDeviceToken(), 3);
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
LOG.info("Server response: MessageId: " + result.getMessageId()
+ " ErrorCode: " + result.getErrorCode().toString()
+ " Reason: " + result.getReason());
}
}

View File

@@ -0,0 +1,86 @@
package cn.wildfirechat.push.ios;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ConfigurationProperties(prefix="apns")
@PropertySource(value = "classpath:apns.properties")
public class ApnsConfig {
String productCerPath;
String productCerPwd;
String developCerPath;
String developCerPwd;
String voipCerPath;
String voipCerPwd;
String alert;
String voipAlert;
public String getProductCerPath() {
return productCerPath;
}
public void setProductCerPath(String productCerPath) {
this.productCerPath = productCerPath;
}
public String getProductCerPwd() {
return productCerPwd;
}
public void setProductCerPwd(String productCerPwd) {
this.productCerPwd = productCerPwd;
}
public String getDevelopCerPath() {
return developCerPath;
}
public void setDevelopCerPath(String developCerPath) {
this.developCerPath = developCerPath;
}
public String getDevelopCerPwd() {
return developCerPwd;
}
public void setDevelopCerPwd(String developCerPwd) {
this.developCerPwd = developCerPwd;
}
public String getVoipCerPath() {
return voipCerPath;
}
public void setVoipCerPath(String voipCerPath) {
this.voipCerPath = voipCerPath;
}
public String getVoipCerPwd() {
return voipCerPwd;
}
public void setVoipCerPwd(String voipCerPwd) {
this.voipCerPwd = voipCerPwd;
}
public String getAlert() {
return alert;
}
public void setAlert(String alert) {
this.alert = alert;
}
public String getVoipAlert() {
return voipAlert;
}
public void setVoipAlert(String voipAlert) {
this.voipAlert = voipAlert;
}
}

View File

@@ -0,0 +1,187 @@
package cn.wildfirechat.push.ios;
import cn.wildfirechat.push.PushMessage;
import cn.wildfirechat.push.PushMessageType;
import com.notnoop.apns.*;
import com.notnoop.exceptions.ApnsDeliveryErrorException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.Map;
import static com.notnoop.apns.DeliveryError.INVALID_TOKEN;
@Component
public class ApnsServer implements ApnsDelegate {
private static final Logger LOG = LoggerFactory.getLogger(ApnsServer.class);
@Override
public void messageSent(ApnsNotification message, boolean resent) {
LOG.info("APNS push sent:{}", message.getDeviceToken());
}
@Override
public void messageSendFailed(ApnsNotification message, Throwable e) {
LOG.info("APNS push failure:{}", e.getMessage());
if(e instanceof ApnsDeliveryErrorException) {
ApnsDeliveryErrorException apnsDeliveryErrorException = (ApnsDeliveryErrorException)e;
LOG.info("APNS error code:{}", apnsDeliveryErrorException.getDeliveryError());
if (apnsDeliveryErrorException.getDeliveryError() == INVALID_TOKEN) {
if (message.getDeviceId() != null) {
LOG.error("Invalide token!!!");
} else {
LOG.error("APNS ERROR without deviceId:{}", message);
}
}
}
}
@Override
public void connectionClosed(DeliveryError e, int messageIdentifier) {
LOG.info("111");
}
@Override
public void cacheLengthExceeded(int newCacheLength) {
LOG.info("111");
}
@Override
public void notificationsResent(int resendCount) {
LOG.info("111");
}
ApnsService productSvc;
ApnsService developSvc;
ApnsService voipSvc;
@Autowired
private ApnsConfig mConfig;
@PostConstruct
private void init() {
if (StringUtils.isEmpty(mConfig.alert)) {
mConfig.alert = "default";
}
if (StringUtils.isEmpty(mConfig.voipAlert)) {
mConfig.alert = "default";
}
productSvc = APNS.newService()
.asBatched(3, 10)
.withAppleDestination(true)
.withCert(mConfig.productCerPath, mConfig.productCerPwd)
.withDelegate(this)
.build();
developSvc = APNS.newService()
.asBatched(3, 10)
.withAppleDestination(false)
.withCert(mConfig.developCerPath, mConfig.developCerPwd)
.withDelegate(this)
.build();
voipSvc = APNS.newService()
.withAppleDestination(true)
.withCert(mConfig.voipCerPath, mConfig.voipCerPwd)
.withDelegate(this)
.build();
productSvc.start();
developSvc.start();
voipSvc.start();
}
public void pushMessage(PushMessage pushMessage) {
ApnsService service = developSvc;
if (pushMessage.getPushType() == IOSPushType.IOS_PUSH_TYPE_DISTRIBUTION) {
if (pushMessage.pushMessageType == PushMessageType.PUSH_MESSAGE_TYPE_NORMAL || StringUtils.isEmpty(pushMessage.getVoipDeviceToken())) {
service = productSvc;
} else {
service = voipSvc;
}
}
if (service == null) {
LOG.error("Service not exist!!!!");
return;
}
String sound = mConfig.alert;
String pushContent = pushMessage.getPushContent();
if (pushMessage.pushMessageType == PushMessageType.PUSH_MESSAGE_TYPE_VOIP_INVITE) {
pushContent = "通话邀请";
sound = mConfig.voipAlert;
} else if(pushMessage.pushMessageType == PushMessageType.PUSH_MESSAGE_TYPE_VOIP_BYE) {
pushContent = "通话结束";
sound = null;
}
int badge = pushMessage.getUnReceivedMsg();
if (badge <= 0) {
badge = 1;
}
String title;
String body;
//todo 这里需要加上语言的处理客户端会上报自己的语言在DeviceInfo那个类中
// if (pushMessage.language == "zh_CN") {
//
// } else if(pushMessage.language == "US_EN") {
//
// }
if (pushMessage.convType == 1) {
title = pushMessage.targetName;
if (StringUtils.isEmpty(title)) {
title = "群聊";
}
if (StringUtils.isEmpty(pushMessage.senderName)) {
body = pushContent;
} else {
body = pushMessage.senderName + ":" + pushContent;
}
if (pushMessage.mentionedType == 1) {
if (StringUtils.isEmpty(pushMessage.senderName)) {
body = "有人在群里@了你";
} else {
body = pushMessage.senderName + "在群里@了你";
}
} else if(pushMessage.mentionedType == 2) {
if (StringUtils.isEmpty(pushMessage.senderName)) {
body = "有人在群里@了大家";
} else {
body = pushMessage.senderName + "在群里@了大家";
}
}
} else {
if (StringUtils.isEmpty(pushMessage.senderName)) {
title = "消息";
} else {
title = pushMessage.senderName;
}
body = pushContent;
}
final String payload = APNS.newPayload().alertBody(body).badge(badge).alertTitle(title).sound(sound).build();
final ApnsNotification goodMsg = service.push(service == voipSvc ? pushMessage.getVoipDeviceToken() : pushMessage.getDeviceToken(), payload, null);
LOG.info("Message id: " + goodMsg.getIdentifier());
//检查key到期日期
final Map<String, Date> inactiveDevices = service.getInactiveDevices();
for (final Map.Entry<String, Date> ent : inactiveDevices.entrySet()) {
LOG.info("Inactive " + ent.getKey() + " at date " + ent.getValue());
}
}
}

View File

@@ -0,0 +1,7 @@
package cn.wildfirechat.push.ios;
import cn.wildfirechat.push.PushMessage;
public interface IOSPushService {
Object push(PushMessage pushMessage);
}

View File

@@ -0,0 +1,22 @@
package cn.wildfirechat.push.ios;
import cn.wildfirechat.push.PushMessage;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class IOSPushServiceImpl implements IOSPushService {
private static final Logger LOG = LoggerFactory.getLogger(IOSPushServiceImpl.class);
@Autowired
public ApnsServer apnsServer;
@Override
public Object push(PushMessage pushMessage) {
LOG.info("iOS push {}", new Gson().toJson(pushMessage));
apnsServer.pushMessage(pushMessage);
return "OK";
}
}

View File

@@ -0,0 +1,6 @@
package cn.wildfirechat.push.ios;
public interface IOSPushType {
int IOS_PUSH_TYPE_DISTRIBUTION = 0;
int IOS_PUSH_TYPE_DEVELOPEMENT = 1;
}