IOS菜鸟初学第九篇:实现远程推送通知(证书创建,证书使用,ios代码,php后台发送推送)

    xiaoxiao2022-07-12  147

    首先说一点,我这里只是简单实现整个推送过程,还暂未对推送后的通知做处理,比如3Dtouch触发的快捷操作,如果你需要看这方面的资料,这里推荐几个参考

    1.https://www.jianshu.com/p/81c6bd16c7ac

    2.http://www.cocoachina.com/ios/20180719/24235.html

     

    好了,整个实现流程就不多说了,简单总结一下

    1.苹果开发者后台创建推送证书(建议开发环境和正式环境的证书都创建好)

    2.创建好证书后,到xcode中配置,并在AppDelegate中注册设备token,发送给后台,以及处理通知

    3.php使用证书,跟Apns建立连接,发送推送消息

     

    就上面的3步操作,但是有繁琐的步骤,还有一些细节要注意。

    由于步骤过于繁琐,某些步骤就不一一贴上来了,这里安利一下我参考的这几位大佬的教程,亲测是能成功的,只是可能会遇到些坑,我会总结一下,供大家参考。

    1.证书创建和xcode配置:https://www.jianshu.com/p/adfce0921c09

    2..p12证书合成.pem证书,以及php后台代码:https://www.jianshu.com/p/38d9fed94ee0

    3. AppDelegate完整代码:https://www.jianshu.com/p/c58f8322a278

     

    总结:

    1.证书必须创建正确。自己写后台的发送程序,需要用到.pem文件。而第三方的推送服务器需要的是p12文件

    2.xcode要在打开相应的开关

    3.你测试获取的deviceToken是需要你自己写代码发给你后台的。当然自己测试的话,只需要直接复制就好了。

    4.当你原生app已经能够获取deviceToken,你已经成功一半了,只需要在后端测试能否收到推送通知就好了。我用的是PHP,网上大部分是16年的教程,但是还是管用,下面附上我的PHP后段代码,亲测能成功,注意要在命令终端运行php并不可以直接运行,也可以写一个方法另一php调用这个方法,此时能够在浏览器中成功运行。

    <?php $fp =create_apns_link(); $message = array("title" =>"劲爆活动来袭" , "body" =>'邀请好友,即可获得邀请大奖。累计奖金第一名还可获得额外实物奖励,速来吧'); //app右上角显示的数字 $badge = 1; //推送消息到手机时的提示音 $sound = 'default'; //建设的通知有效载荷(即通知包含的一些信息) $body = array(); $body['aps'] = array('alert' => $message,'badge'=>$badge,'sound'=>$sound); //自定义参数 $body['userInfo'] = array('type' => '2'); //把数组数据转换为json数据 $payload = json_encode($notification); echo strlen($payload); //这里可批量发送deviceToken,将多个deviceToken放在数组中循环即可 $devicetoken =['8e2ac24b85b32f14bd5af82ebb80edebd0671195abb876b00044ad08ad3391c4']; $i = 1; //推送开始 foreach ($devicetoken as $v){ print_r('开始推送' .'<br/>'); $msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $v)) . pack("n",strlen($payload)) . $payload; if( !fwrite($fp, $msg) || checkAppleErrorResponse($fp) ){ //如果失败,则进行重发,连续3次还是失败,则重新建立连接,并对下一个devicetoken进行推送 $times = 1; while($times <= 3){ if(!fwrite($fp, $msg) || checkAppleErrorResponse($fp)){ $times ++ ; }else{ $fp = create_apns_link(); break; } } } print_r('已推送' . $v .'的通知<br/>'); //每隔100次重新和APNS服务器建立连接. if( $i0 == 0 ){ $fp = create_apns_link(); } $i++; } usleep(500000); if(checkAppleErrorResponse($fp)){ print_r('推送失败<br/>'); }else{ print_r('推送完成<br/>'); } fclose($fp); function create_apns_link(){ $passphrase = '123456'; //这是合成的.pem证书,跟php文件放在同一个文件夹 $filename = dirname(__FILE__) .'/'.'apns_production.pem'; //测试环境下的apns服务器,用tls连接方式 $link = 'tls://gateway.push.apple.com:2195'; //正式环境下的apns服务器 //$link = 'tls://gateway.sandbox.push.apple.com:2195'; $scc = stream_context_create(); //这里并不需要改为tls,保持ssl就好了 stream_context_set_option($scc, 'ssl', 'local_cert', $filename); stream_context_set_option($scc, 'ssl', 'passphrase', $passphrase); $fp = stream_socket_client($link, $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $scc); $i = 0; while (gettype($fp) != 'resource'){ print_r('重连Apns'.'<br/>'); if($i < 3){ usleep(500000); $fp = stream_socket_client($link, $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $scc); }else{ break; } } stream_set_blocking ($fp, 0); if($fp){ echo '成功连接到Apns,等待推送' . '<br/>'; } return $fp; } function checkAppleErrorResponse($fp) { //byte1=always 8, byte2=StatusCode, bytes3,4,5,6=identifier(rowID). // Should return nothing if OK. //NOTE: Make sure you set stream_set_blocking($fp, 0) or else fread will pause your script and wait // forever when there is no response to be sent. $apple_error_response = fread($fp, 6); if ($apple_error_response) { // unpack the error response (first byte 'command" should always be 8) $error_response = unpack('Ccommand/Cstatus_code/Nidentifier', $apple_error_response); if ($error_response['status_code'] == '0') { $error_response['status_code'] = '0-没遇到任何错误'; } else if ($error_response['status_code'] == '1') { $error_response['status_code'] = '1-处理错误'; } else if ($error_response['status_code'] == '2') { $error_response['status_code'] = '2-缺少设备token'; } else if ($error_response['status_code'] == '3') { $error_response['status_code'] = '3-缺少主题'; } else if ($error_response['status_code'] == '4') { $error_response['status_code'] = '4-缺少荷载'; } else if ($error_response['status_code'] == '5') { $error_response['status_code'] = '5-无效的设备token'; } else if ($error_response['status_code'] == '6') { $error_response['status_code'] = '6-无效的主题size'; } else if ($error_response['status_code'] == '7') { $error_response['status_code'] = '7-无效的荷载size'; } else if ($error_response['status_code'] == '8') { $error_response['status_code'] = '8-无效的token'; } else if ($error_response['status_code'] == '255') { $error_response['status_code'] = '255-未知错误'; } else { $error_response['status_code'] = $error_response['status_code'].'-错误不在错误列表内'; } echo '<br><b>+ + + + + + 错误</b> 返回命令:<b>' . $error_response['command'] . '</b> 识别码:<b>' . $error_response['identifier'] . '</b> 状态码:<b>' . $error_response['status_code'] . '</b><br>'; echo '标识符是导致问题的数据库中的rowID(索引),Apple将断开您与服务器的连接。 要继续发送推送通知,只需从此标识符后面的下一个rowID开始。<br>'; return true; } return false; } ?>

    5.测试正式环境的推送

    首先将php的测试发送通知的apns服务器和证书换成正式环境的。

    然后最重要的是获取正式环境下的deviceToken。这里有两个解决方案,第一种就是代码里写好将获取到的deviceToken发送到服务器的数据库,存起来。然后在appstore上线了,在进行测试。这个时间成本太高了。第二种就是生成ipa文件,直接安装在手机上,将deviceToken存在本地文件,然后去找这个文件,读取deviceToken信息。

    我这里详细说一下第二种方案:参考教程:https://www.jianshu.com/p/76e23be72b3b

    1.首先修改代码,在获取deviceToken的地方把deviceToken存在本地文件。代码如下:

    打个广告:我写的另一篇文章,收集了一些ios常用开发技巧:传送门

    NSArray *pathArr=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *strPath=[pathArr lastObject]; NSString *strFinalPath=[NSString stringWithFormat:@"%@/myfile.txt",strPath]; [deviceToken writeToFile:strFinalPath atomically:YES encoding:NSUTF8StringEncoding error:nil];

     

    2.打包生成ipa文件,首先要在apple的developer后台创建这个应用的ad hoc证书,可参考上面的教程

    生成之后,打包生成ipa操作如下:

    xcode->product->archive,打开窗口后distribute app,选择ad hoc

        然后next->next->

    这里要注意hoc是我在apple的developer中创建的那个ad hoc证书。这里要用的。然后next->

    export导出,就会在导出的地方有个文件夹,里面就有.ipa文件,如下:

     

    3.真机安装ipa文件。xcode要链接好手机,然后打开设备窗口,操作如下:xcode->windows->devices and simulators,这样就会打开如下窗口:

    点击+号,选择刚刚导出的ipa文件,就会自动安装好了,如下图

    安装好之后,你就正常的使用你的app,你一打开app,他应该就会存下deviceToken了,然后你就会到上图这个窗口,选中这个app,+号旁边的设置icon就会亮起,点击选择download选项:

    download之后就会在你download到的那个文件夹中出现一个app data文件:

    右键->显示包内容。就能打开里面的文件目录,在document文件夹下应该有个txt文件,打开里面就是正式环境下的deviceToken,如下图:

    5. 这时候你就可以拿着这个deviceToken去php后台发送测试了。之前我分享的那个教程中的smartpush那个测试插件挺好用的,也能用来测试,xcode打开就能跑起来,非常方便。

     

    最新回复(0)