SpringBoot自搭建APNS服务

描述

前段时间研究了自搭建APNS服务,在网上也找了很长一段时间,很少有Java直接调用APNS服务的方式,有的很老了也没有用起来,自己总结下SpringBoot自搭建APNS服务。

结果显示

代码展示

一、创建ApnsClient

根据P8证书或者P12证书创建ApnsClient对象

/**

* 创建客户端

*/

public ApnsClient createApnsClient() throws Exception {

String p8_path = getCerPath() + "AuthKey.p8";

String p12_dis_path = getCerPath() + "Dis.p12";

String p12_dev_path = getCerPath() + "Dev.p12";

String config_path = getCerPath() + "apns_config.json";

if (!FileUtil.isExistFile(config_path)) {

throw new Exception("apns_config配置文件不存在!");

}

if (currentProductStatus) { //生产环境

if (FileUtil.isExistFile(p8_path)) { // P8发送

String configContent = FileUtil.readJsonFile(config_path);

JSONObject json = (JSONObject) JSONObject.parse(configContent);

if (StringUtils.isEmpty(json.getString("TeamId")) || StringUtils.isEmpty(json.getString("KeyId"))) {

throw new Exception("p8配置参数不对!");

}

apnsClient = new ApnsClientBuilder()

.setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)

.setSigningKey(ApnsSigningKey.loadFromPkcs8File(new File(p8_path),

json.getString("TeamId"), json.getString("KeyId")))

.build();

} else if (FileUtil.isExistFile(p12_dis_path)) { // P12发送 生产环境

String configContent = FileUtil.readJsonFile(config_path);

JSONObject json = (JSONObject) JSONObject.parse(configContent);

if (StringUtils.isEmpty(json.getString("DisP12Pwd"))) {

throw new Exception("p12密码没有配置!");

}

apnsClient = new ApnsClientBuilder()

.setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST)

.setClientCredentials(new File(p12_dis_path), json.getString("DisP12Pwd"))

.build();

} else {

throw new Exception("apnsClient创建失败,没有找到合适证书环境创建");

}

} else { //测试环境

if (FileUtil.isExistFile(p8_path)) { // P8发送

String configContent = FileUtil.readJsonFile(config_path);

JSONObject json = (JSONObject) JSONObject.parse(configContent);

if (StringUtils.isEmpty(json.getString("TeamId")) || StringUtils.isEmpty(json.getString("KeyId"))) {

throw new Exception("p8配置参数不对!");

}

apnsClient = new ApnsClientBuilder()

.setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST)

.setSigningKey(ApnsSigningKey.loadFromPkcs8File(new File(p8_path),

json.getString("TeamId"), json.getString("KeyId")))

.build();

} else if (FileUtil.isExistFile(p12_dev_path)) { // P12发送 测试环境

String configContent = FileUtil.readJsonFile(config_path);

JSONObject json = (JSONObject) JSONObject.parse(configContent);

if (StringUtils.isEmpty(json.getString("DevP12Pwd"))) {

throw new Exception("p12密码没有配置!");

}

apnsClient = new ApnsClientBuilder()

.setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST)

.setClientCredentials(new File(p12_dev_path), json.getString("DevP12Pwd"))

.build();

} else {

throw new Exception("apnsClient创建失败,没有找到合适证书环境创建");

}

}

return apnsClient;

}

二、发送推送通知

向指定设备发送推送通知

/**

* 发送通知

*/

public JSONObject pushNotification(JSONObject params) throws Exception {

final ApnsPayloadBuilder payloadBuilder = new SimpleApnsPayloadBuilder();

HashMap notification = (HashMap) params.get("notification");

HashMap aps = (HashMap) notification.get("aps");

JSONObject backJO = new JSONObject();

if (aps != null) { // apns通知

HashMap alert = (HashMap) aps.get("alert");

String title = (String) alert.get("title");

String subtitle = (String) alert.get("subtitle");

String body = (String) alert.get("body");

String badge = (String) aps.get("badge");

String sound = (String) aps.get("sound");

if (!StringUtils.isEmpty(title)) {

payloadBuilder.setAlertTitle(title);

}

if (!StringUtils.isEmpty(subtitle)) {

payloadBuilder.setAlertSubtitle(subtitle);

}

if (!StringUtils.isEmpty(body)) {

payloadBuilder.setAlertBody(body);

}

if (!StringUtils.isEmpty(badge)) {

payloadBuilder.setBadgeNumber(Integer.parseInt(badge));

}

if (!StringUtils.isEmpty(sound)) {

payloadBuilder.setSound(sound);

}

HashMap custommap = (HashMap) notification.get("custommap");

if (custommap != null) {

for (Map.Entry entry : custommap.entrySet()) {

payloadBuilder.addCustomProperty(entry.getKey(), entry.getValue());

}

}

final String payload = payloadBuilder.build();

ArrayList device_tokens = (ArrayList) params.get("device_token");

String appId = params.getString("appId");

List responseList = new ArrayList();

for (int i = 0; i < device_tokens.size(); i++) {

String device_token = device_tokens.get(i);

final String token = TokenUtil.sanitizeTokenString(device_token);

ApnsPushNotification pushNotification = new SimpleApnsPushNotification(token, appId, payload);

boolean productStatus = params.get("product") == null ? true : params.getBoolean("product");

if (apnsClient == null || productStatus != currentProductStatus) {

currentProductStatus = productStatus;

apnsClient = null;

createApnsClient();

}

// 开始推送

final PushNotificationFuture>

sendNotificationFuture =

apnsClient.sendNotification(pushNotification);

final PushNotificationResponse pushNotificationResponse =

sendNotificationFuture.get();

JSONObject pushParam = new JSONObject();

String id = UUID.randomUUID().toString();

pushParam.put("id", id);

pushParam.put("content", notification.toString());

pushParam.put("device_token", device_token);

pushParam.put("type", "2"); //ios

pushParam.put("status", "1");

JSONObject responseObj = new JSONObject();

responseObj.put("device_token", device_token);

responseObj.put("id", id);

if (pushNotificationResponse.isAccepted()) { //成功发送

pushParam.put("push_status", "1");

pushParam.put("reason", "");

responseObj.put("push_status", "1");

} else {

pushParam.put("push_status", "2");

pushParam.put("reason", "错误码 :" + pushNotificationResponse.getStatusCode() + ";拒绝原因:" + pushNotificationResponse.getRejectionReason().toString());

responseObj.put("push_status", "2");

responseObj.put("reason", "错误码 :" + pushNotificationResponse.getStatusCode() + ";拒绝原因:" + pushNotificationResponse.getRejectionReason().toString());

System.out.println("失败发送了");

}

responseList.add(responseObj);

pushDao.addPush(pushParam);

}

backJO.put("code", "200");

backJO.put("msg", "执行完");

backJO.put("responseList", responseList);

} else { //安卓通知

throw new Exception("暂时仅支持APNS推送通知!");

}

return backJO;

}

依赖JAR包

POM 依赖的JAR包

com.eatthepath

pushy

0.15.2

io.netty

netty-tcnative-boringssl-static

2.0.59.Final

runtime