【IM-02】apns服務(wù)的實(shí)現(xiàn)

前沿

市面上的推送有很多:極光推送卧波,個(gè)推,這是我用過(guò)的兩款產(chǎn)品淆游,在推送領(lǐng)域都有特點(diǎn),現(xiàn)在自己開(kāi)發(fā)了一款推送產(chǎn)品MagotanPush隔盛,服務(wù)端用Node.js語(yǔ)言犹菱,移動(dòng)端用OC,目前是一個(gè)初品吮炕,也可以商用哈腊脱。

第一篇:即時(shí)通信解決方案
第二篇:推送解決方案
第三篇:Web端匿名聊天
第四篇:iOS集成單聊&群聊

1.推送實(shí)現(xiàn)流程

推送實(shí)現(xiàn)流程.png
說(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文件成功

證書(shū)有效.png

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:
服務(wù)端操作.png
client:
客戶端效果.jpeg

不管大佬們關(guān)不關(guān)注公眾號(hào),我都會(huì)放上本章的Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锦亦,一起剝皮案震驚了整個(gè)濱河市舶替,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杠园,老刑警劉巖顾瞪,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抛蚁,居然都是意外死亡陈醒,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門瞧甩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钉跷,“玉大人,你說(shuō)我怎么就攤上這事肚逸∫蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵朦促,是天一觀的道長(zhǎng)膝晾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)思灰,這世上最難降的妖魔是什么玷犹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上歹颓,老公的妹妹穿的比我還像新娘坯屿。我一直安慰自己,他們只是感情好巍扛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布领跛。 她就那樣靜靜地躺著,像睡著了一般撤奸。 火紅的嫁衣襯著肌膚如雪吠昭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天胧瓜,我揣著相機(jī)與錄音矢棚,去河邊找鬼。 笑死府喳,一個(gè)胖子當(dāng)著我的面吹牛蒲肋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钝满,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼兜粘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了弯蚜?” 一聲冷哼從身側(cè)響起孔轴,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碎捺,沒(méi)想到半個(gè)月后路鹰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡牵寺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年悍引,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帽氓。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趣斤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出黎休,到底是詐尸還是另有隱情浓领,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布势腮,位于F島的核電站联贩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捎拯。R本人自食惡果不足惜泪幌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧祸泪,春花似錦吗浩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至右蒲,卻和暖如春阀湿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瑰妄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工陷嘴, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翰撑。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓罩旋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親眶诈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容