前沿
市面上的推送有很多:極光推送卧波,個(gè)推,這是我用過(guò)的兩款產(chǎn)品淆游,在推送領(lǐng)域都有特點(diǎn),現(xiàn)在自己開(kāi)發(fā)了一款推送產(chǎn)品MagotanPush隔盛,服務(wù)端用Node.js語(yǔ)言犹菱,移動(dòng)端用OC,目前是一個(gè)初品吮炕,也可以商用哈腊脱。
1.推送實(shí)現(xiàn)流程
說(shuō)明:
第一步:App注冊(cè)通知,獲得DeviceToken龙亲,上報(bào)apns服務(wù)
第二步:App注冊(cè)通知陕凹,獲取到DeviceToken,上報(bào)自己服務(wù)器鳄炉,作為用戶標(biāo)識(shí)
第三步:配置證書(shū)和推送文本杜耙,根據(jù)DeviceToken進(jìn)行推送
第四步:APNS服務(wù)收到消息,完成特定用戶的推送
2.證書(shū)配置
2.1.證書(shū)配置
網(wǎng)上一大堆拂盯,這個(gè)我不提供佑女,我相信各位大佬的水平
2.2.pem文件生成
1.打開(kāi)鑰匙串,選擇需要生成的推送證書(shū);
2.分別將certificate和private key導(dǎo)出得到對(duì)應(yīng)的.p12文件团驱,證書(shū)->apns-dev-cert.p12摸吠,秘鑰->apns-dev-key.p12;
3.將apns-dev-cert.p12和apns-dev-key.p12文件對(duì)應(yīng)轉(zhuǎn)化為apns-dev-cer.pem和apns-dev-key.pem文件;
openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
4.將apns-dev-cert.pem和apns-dev-key.pem文件合成為apns-dev.pem文件
cat apns-dev-cert.pem apns-dev-key.pem > apns-dev.pem
5.測(cè)試證書(shū)有效性
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert apns-dev-cert.pem -key apns-dev-key.pem
6.終端最后顯示以下內(nèi)容嚎花,表示配置pem文件成功
3 iOS端配置
3.1.項(xiàng)目代碼編寫(xiě)
#import <UserNotifications/UserNotifications.h>
3.1.1.注冊(cè)推送/獲取deviceToken
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//注冊(cè)推送
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 必須寫(xiě)代理寸痢,不然無(wú)法監(jiān)聽(tīng)通知的接收與點(diǎn)擊
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 點(diǎn)擊允許
NSLog(@"注冊(cè)成功");
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"%@", settings);
}];
} else {
// 點(diǎn)擊不允許
NSLog(@"注冊(cè)失敗");
}
}];
//獲取deviceToken
[application registerForRemoteNotifications];
return YES;
}
3.1.2. iOS 10收到通知
// iOS 10收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSDictionary * userInfo = notification.request.content.userInfo;
UNNotificationRequest *request = notification.request; // 收到推送的請(qǐng)求
UNNotificationContent *content = request.content; // 收到推送的消息內(nèi)容
NSNumber *badge = content.badge; // 推送消息的角標(biāo)
NSString *body = content.body; // 推送消息體
UNNotificationSound *sound = content.sound; // 推送消息的聲音
NSString *subtitle = content.subtitle; // 推送消息的副標(biāo)題
NSString *title = content.title; // 推送消息的標(biāo)題
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 前臺(tái)收到遠(yuǎn)程通知:%@", userInfo);
}else {
// 判斷為本地通知
NSLog(@"iOS10 前臺(tái)收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@贩幻,\\\\nsound:%@轿腺,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
}
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要執(zhí)行這個(gè)方法两嘴,選擇是否提醒用戶丛楚,有Badge、Sound憔辫、Alert三種類型可以設(shè)置趣些,Alert可以設(shè)定前臺(tái)展示通知欄。
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler{
//處理推送過(guò)來(lái)的數(shù)據(jù)
NSLog(@"%@",response.notification.request.content.userInfo);
completionHandler();
}
3.1.3.將得到的deviceToken傳給SDK
// 將得到的deviceToken傳給SDK
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSString *deviceTokenStr = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<" withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"deviceTokenStr:\n%@",deviceTokenStr);
[[NSUserDefaults standardUserDefaults] setValue:deviceTokenStr forKey:@"DEVICETOKEN"];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(nonnull NSError *)error{
NSLog(@"注冊(cè)推送失敗Error:%@",error.localizedDescription);
}
4.服務(wù)端集成
"use strict";
const apn = require("apn");
// deviceToken 數(shù)組
let tokens = ["7f56110923c266397a3aa434ce15d3172b5666b98f49543cd78fc45e682f55b4"];
let service = new apn.Provider({
cert: "apns-dev-cert.pem",
key: "apns-dev-key.pem",
gateway: "gateway.sandbox.push.apple.com",
// gateway: "gateway.push.apple.com"; //線上地址
// port: 2195, //端口
passphrase: "關(guān)注公眾號(hào)贰您,找我要密碼坏平,hahah" //pem證書(shū)密碼
});
let note = new apn.Notification();
note.payload = {
from : "MagotanPush_APNS",
source : "ios",
module : "home"
};
note.body = "Hello MagotanPush!";
// 主題 一般取應(yīng)用標(biāo)識(shí)符(bundle identifier)
note.topic = "geekschen.APNsTest"
console.log(`Sending: ${note.compile()} to ${tokens}`);
service.send(note, tokens).then( result => {
console.log("sent:", result.sent.length);
console.log("failed:", result.failed.length);
console.log(result.failed);
});
service.shutdown();
5.效果展示
server:
client:
不管大佬們關(guān)不關(guān)注公眾號(hào),我都會(huì)放上本章的Demo