iOS客户端如何测试推送
????當(dāng)我們?cè)诳蛻舳藢?shí)現(xiàn)推送跳轉(zhuǎn)需求后,但是服務(wù)器還沒有做好后臺(tái)的配置,此時(shí)需要測試收到推送消息之后能否按照預(yù)期,執(zhí)行我們的代碼。但在這個(gè)情況下如何去做呢。這里可以提供給大家兩個(gè)選擇。
?????1. 封裝好處理邏輯的接口,在程序啟動(dòng)或者某個(gè)時(shí)刻模擬數(shù)據(jù),直接調(diào)用處理邏輯的接口,查看是否符合預(yù)期。該情況只適用于測試跳轉(zhuǎn)邏輯,不能測試數(shù)據(jù)解析的正確性(例如字段名是否正確、字段的類型是否正確等)。
????例如,我們處理推送消息的函數(shù)都寫在了Appdelegate.m中的- (void)dealWithNotification:(NSDictionary*)userInfo函數(shù)里
????那么我們就需要來構(gòu)造數(shù)據(jù)進(jìn)行模擬推送,比如這樣:
????????//? 用于模擬器測試推送 方便快速測試推送問題 使用這個(gè)函數(shù)測試完,請(qǐng)務(wù)必在真實(shí)推送情況下測試
????????- (void)sendNotificationSelf:(RemoteNotificationType)type
????????{
? ? ????????NSDictionary * dictionary = nil;
? ? ????????if (type == kRemoteNotificationExpression)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(3), @"flag", @(1033), @"secondClassifyId", nil];
? ? ????????else if (type == kRemoteNotificationDwaft)
? ? ? ????? ????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(5), @"flag", @"寶貝計(jì)劃", @"templateName", @(126), @"templateId", nil];
? ????????? else if (type == kRemoteNotificationCharacter)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(6), @"flag", nil];
? ? ????????else if (type == kRemoteNotificationSoundExpressionCategory)
? ? ? ????????? dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(8), @"flag", @(176), @"classifyId",? @"", @"classifyName", nil];
? ????????? else if (type == kRemoteNotificationSoundExpressionSubjectDetail)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(9), @"flag", @(18), @"subjectId", @"動(dòng)物成精了", @"subjectName", nil];
? ? ????????else if (type == kRemoteNotificationMessageCenter)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(10), @"flag", nil];
? ? ????????else if (type == kRemoteNotificationFansList)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(11), @"flag", nil];
? ? ????????else if (type == kRemoteNotificationStatusDetail)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(12), @"flag", @"" , @"sid", nil];
? ????????? else if (type == kRemoteNotificationUserHomePage)
? ? ? ? ????????dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@(13), @"flag", [UserInfo getSelf].uid, @"uid", nil];
? ? ????????[self dealWithNotification:dictionary];
????????}
??? ????這段代碼的作用非常簡單,其實(shí)就是根據(jù)預(yù)設(shè)好的推送類型,來模擬不同的推送數(shù)據(jù),進(jìn)而調(diào)用推送函數(shù)的統(tǒng)一處理方法。
????????我們可以在應(yīng)用啟動(dòng)的時(shí)候調(diào)用來模擬應(yīng)用未開啟時(shí)點(diǎn)擊推送的效果,在點(diǎn)擊某個(gè)按鈕時(shí)調(diào)用來模擬應(yīng)用在前臺(tái)收到推送 ? ? ? ? 的效果,寫一個(gè)延時(shí)來調(diào)用然后點(diǎn)擊home鍵,來模擬應(yīng)用在后臺(tái)收到推送的效果了。
????????怎么樣,看起來還不錯(cuò)吧,基本上可以解決問題,那還有沒有更好的方案了,請(qǐng)繼續(xù)看。
????2. 既然服務(wù)器還沒有做好相關(guān)的配置,那么為什么我們自己做一個(gè)閹割版的服務(wù)器,只做推送測試呢?OK,那就了解一下,iOS推送通知的基本原理。
iOS推送通知的基本原理
????蘋果的推送服務(wù)是由自己專門的推送服務(wù)器APNs(Apple Push Notification service)來完成的,過程是APNs收到我們自己的應(yīng)用服務(wù)器發(fā)出的被推送的消息,將這條消息推送到制定的iOS設(shè)備上,然后再由iOS設(shè)備通知到我們的應(yīng)用程序,我們將會(huì)以通知或者聲音的形式收到推送回來的消息。iOS遠(yuǎn)程推送的前提是,裝有我們應(yīng)用程序的iOS設(shè)備,要向APNs服務(wù)器注冊(cè),注冊(cè)成功后,APNs服務(wù)器將會(huì)給我們返回一個(gè)deviceToken,我們獲取到這個(gè)token后,將它發(fā)送給我們自己的應(yīng)用服務(wù)器。當(dāng)我們需要推送消息時(shí),我們的應(yīng)用服務(wù)器將消息按照指定的格式進(jìn)行打包,然后結(jié)合iOS設(shè)備的deviceToken一起發(fā)給APNs服務(wù)器。iOS設(shè)備會(huì)和APNs服務(wù)器維持一個(gè)基于TCP的長連接,APNs服務(wù)器將新消息推送到iOS設(shè)備上,然后在設(shè)備屏幕上進(jìn)行顯示。
????其實(shí)總結(jié)下來過程如下:
????1.????客戶端向APNs申請(qǐng)注冊(cè)消息推送服務(wù)。
????2.????APNs服務(wù)器接受到請(qǐng)求后,并將deviceToken返回給設(shè)備上的客戶端
????3.????客戶端將deviceToken發(fā)送給自己的后臺(tái)服務(wù)器,后臺(tái)接受后并儲(chǔ)存。
????4.????后臺(tái)服務(wù)器向APNs服務(wù)器發(fā)送推送消息
????5.????APNs服務(wù)器接受后,將消息發(fā)送給deviceToken對(duì)應(yīng)的設(shè)備
????我們來看上面的過程中服務(wù)器要做的就是接受并儲(chǔ)存客戶端發(fā)送的deviceToken,以便之后再要發(fā)送推送時(shí),與APNs發(fā)送推送消息。所以如果要哦讓我們自己做一個(gè)閹割版的服務(wù)端也很簡單,首先deviceToken,只要我們不卸載應(yīng)用,那么他是不會(huì)變化的。所以我們只要在XCode中輸出deviceToken并且記錄下來就可以解決存儲(chǔ)的問題,那么后臺(tái)服務(wù)器怎么與APNs服務(wù)器交互的呢,其實(shí)只需要跟APNs進(jìn)行SSL連接,把我們APNs預(yù)期的格式的數(shù)據(jù)傳遞過去就可以了?;贛ac平臺(tái),我們可以選擇PHP來實(shí)現(xiàn),畢竟Mac自帶了PHP環(huán)境,使用起來很方便(況且PHP是世界上最好的語言J)。
????使用PHP進(jìn)行通信的話,就需要使用.pem文件。
.PEM文件是什么?
????如果把SSL系統(tǒng)比喻成工商局系統(tǒng)。
????首先有SSL就有CA,certificateauthority。證書局,同于制作、認(rèn)證證書的第三方機(jī)構(gòu),我們假設(shè)應(yīng)用執(zhí)照非常難制作,就像身份證一樣,需要有制作公司來提供,并且提供技術(shù)幫助工商局驗(yàn)證執(zhí)照的真?zhèn)巍?/p>
????然后CA是可以有很多的,也就是可以有多個(gè)制證公司,但是工商局只有一個(gè),它來說哪個(gè)制證公司是可信的,哪些是假的,需要打擊。在SSL的世界中,微軟、谷歌和Mozilla扮演了一部分的這個(gè)角色。也就是說,IE、Chrome、Firefox中內(nèi)置有一些CA,經(jīng)過這些CA頒發(fā),驗(yàn)證過的證書都是可信的,否則就會(huì)提示你不安全。
????要開店的老板去申請(qǐng)營業(yè)執(zhí)照的時(shí)候是需要提交他的身份證的,然后搬出來的營業(yè)執(zhí)照有他的照片和名字。身份證相當(dāng)于私鑰,營業(yè)執(zhí)照就是證書,Ceritificate,.cer文件。
????然后私鑰和公鑰他們?cè)跀?shù)據(jù)加密層面,數(shù)據(jù)的流向是這樣的。
消息-->[公鑰]-->加密后的信息-->[私鑰]-->消息
????公鑰是可以隨便扔給別人的,他把消息加了密傳遞給我??梢赃@樣理解,我有一個(gè)箱子,一把鎖和一把鑰匙,我把箱子和開著的鎖給別人,他寫信放到箱子里面,鎖上,然后傳遞回我受傷的途中誰都是打不開箱子的,只有我可以用原來的鑰匙打開,這就是SSL,公鑰、私鑰傳遞加密消息的方式。這里的密鑰就是.key文件。
????PEM,它是由RFC1421至1424定義的一種數(shù)據(jù)格式。其實(shí)里面的.cert和.key文件都是PEM格式的,只不過在有些系統(tǒng)(比如Windows)里面會(huì)根據(jù)擴(kuò)展名的不同而做不同的事情。所以當(dāng)看到.pem文件時(shí),它里面的內(nèi)容可能是certificate也可能是key,也可能兩個(gè)都有,要看具體情況,可以通過OpenSSL查看。而在與APNs的通訊中,我們需要傳遞的是同時(shí)包含.cert和.key的文件。蘋果通過這個(gè)來確定你是否是開發(fā)者本人。
如何得到.pem文件
???1. 如果在Mac上鑰匙串訪問中能找到Apple Development iOS Push Server證書的話,可以在證書上面右鍵導(dǎo)出生成apns_dev_cert.p12。如果沒有的話,可以在蘋果開發(fā)者中心生成aps_development.cer文件,然后下載,雙擊導(dǎo)入鑰匙串。
????2. 然后在鑰匙串訪問中找到Apple DevelopmentiOS Push Server密鑰,右鍵生成apns_dev_key.p12。
????3. 打開終端,進(jìn)入p12證書所在的目錄,輸入openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12 生成apns-dev-cert.pem
????4. 輸入openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12 生成apns-dev-key.pem,要輸入密碼,記住這個(gè)密碼
????5. 把兩個(gè).pem文件合并?cat apns-dev-cert.pem apns-dev-key.pem > apns-dev.pem
????這樣就得到了開發(fā)環(huán)境的pem文件了,如果是生產(chǎn)環(huán)境,那么需要選擇生環(huán)境的證書并做相同的操作,得到apns-dis-cert.pem即可。
? ?可以通過?openssl s_client -connect?gateway.sandbox.push.apple.com:2195?-cert apns-dev-cert.pem -key apns-dev-key.pem?測試證書是否正常。執(zhí)行完畢后,直接輸入任意字符,回車,出現(xiàn)closed,表示可用。否則打印錯(cuò)誤信息。
? ?如果出現(xiàn)上面的錯(cuò)誤信息,那么可能是OpenSSL的cert.pem文件問題,可以在終端中輸入命令php -r "print_r(openssl_get_cert_locations());"來查看default_cert_file的路徑,并且替換掉,可用版本的cert.pem在這里(鏈接:https://pan.baidu.com/s/1IlOqpWK-ugenEEjaWqNf9A? 密碼:7qmc),替換前打印下原文件的權(quán)限,替換后修改為同樣的權(quán)限即可。
編寫PHP
????.pem有了,那么我們需要做的就是編寫PHP了。直接送上源碼,需要注意的是修改pass變量為剛才生成.pem的密碼,替換deviceToken為測試設(shè)備的token。如果是在開發(fā)環(huán)境,那么選擇ssl://gateway.sandbox.push.apple.com:2195,如果是生產(chǎn)環(huán)境,那么選擇ssl://gateway.push.apple.com:2195。代碼如下:
<?php
$deviceToken= 'f020999681cc383f6a5e3efb8e3321912808ade966d20a3ec9696fbd5fa24e4c'; //沒有空格
$type = 1; // 1 配圖 2 逗圖工坊 3 文字表情
$body = 0;
if ($type == 1)
{
$body = array( "aps" =>array("alert" => '配圖推送測試',"badge" => 1,"sound"=>'default'),?
"flag" => "2",?
"imageListName" => "我快瘋了!",?
"imageListId" => 2589);? //推送方式,包含內(nèi)容和聲音
}
elseif ($type == 2)
{
$body = array( "aps" => array("alert" => '逗圖工坊推送測試',"badge" => 1,"sound"=>'default'),?
"flag" => "5",?
"templateName" => "二次元",?
"templateId" => 477);? //推送方式,包含內(nèi)容和聲音
}
elseif ($type == 3) {
$body = array( "aps" =>array("alert" => '文字表情推送測試',"badge" => 1,"sound"=>'default'),?
"flag" => "6");? //推送方式,包含內(nèi)容和聲音
}
elseif ($type == 4)
{
$body = array( "aps" =>array("alert" => '表情推送測試',"badge" => 1,"sound"=>'default'),?
"flag" => "3",?
"secondClassifyName" => "斗圖應(yīng)答",?
"secondClassifyId" => 1033);? //推送方式,包含內(nèi)容和聲音
}
$ctx = stream_context_create();
//如果在Windows的服務(wù)器上,尋找pem路徑會(huì)有問題,路徑修改成這樣的方法:
//$pem = dirname(__FILE__) . '/' . 'apns-dev.pem';
//linux 的服務(wù)器直接寫pem的路徑即可
stream_context_set_option($ctx,"ssl","local_cert","apns-dev.pem");
$pass = "123456";
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
//此處有兩個(gè)服務(wù)器需要選擇,如果是開發(fā)測試用,選擇第二名sandbox的服務(wù)器并使用Dev的pem證書,如果是正是發(fā)布,使用Product的pem并選用正式的服務(wù)器
$fp = stream_socket_client("ssl://gateway.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
// $fp = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp) {
echo "Failed to connect $err $errstrn";
return;
}
print "Connection OK\n";
$payload = json_encode($body);
$msg = chr(0) . pack("n",32) . pack("H*", str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
echo "sending message :" . $payload ."\n";
fwrite($fp, $msg);
fclose($fp);
?>
執(zhí)行測試
最后把push.php和apns-dev.pem放到同一目錄下,進(jìn)入命令行輸入php push.php即可。
參考文獻(xiàn):
1.https://www.zhihu.com/question/29620953
2.http://blog.sina.com.cn/s/blog_6f9a9718010128hi.html
3.https://www.cnblogs.com/cocoajin/p/3470704.html
總結(jié)
以上是生活随笔為你收集整理的iOS客户端如何测试推送的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: systemd 服务使用
- 下一篇: 智能灯丝灯方案为复古设计注入“ 科技基因