zoukankan      html  css  js  c++  java
  • IOSAPNS 消息推送实践

    首先,需要一个pem的证书,该证书需要与开发时签名用的一致。 具体生成pem证书方法如下:

    1. 登录到 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action ) 并点击 App IDs

    2. 选择对应App ID。(开发与发布不一样的。需注意)

    3. 点击App ID旁的“Configure”,然后按下按钮生产 推送通知许可证。根据“向导” 的步骤生成一个签名并上传,最后下载生成的许可证。

    4. 通过双击.cer文件将你的 aps_developer_identity.cer 引入Keychain中。

    6. 单机“Apple Development Push Services”,导出p12文件,保存为 apns-dev-cert.p12 文件。

    7. 扩展“Apple Development Push Services” 对“Private Key”做同样操作,保存为 apns-dev-key.p12 文件。

    8. 需要通过终端命令将这些文件转换为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

    9. 如果你想要移除密码,要么在导出/转换时不要设定或者执行:

    openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem

    10. 最后,你需要将键和许可文件合成为apns-dev.pem文件,此文件在连接到APNS时需要使用:

    cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

    PHP后台写法:

    <?php
        
        // 这里是我们上面得到的deviceToken,直接复制过来(记得去掉空格)
    
    //deviceToken  在测试版本和上线版本上不一样。    
    
        //lei ipod touch
        $deviceToken = '06fe0a85056f6b9f07fb11a4eed962aaab824b9522660a8bb165b369717159ab';
        
        // Put your private key's passphrase here:
        $passphrase = 'abc123456';
        
        // Put your alert message here:
        $message = 'My first push test!';
        
        ////////////////////////////////////////////////////////////////////////////////
        
        
        $message = array('msg'=>'小小说阅读器','title'=>'小小说','url'=>'http://www.apple.com.cn');
        //$message = array('msg'=>'去商品详细页面','itemtype'=>'2','id'=>'192172');
        //$message = array('msg'=>'去菜单页面','itemtype'=>'1','zktype'=>'1','order'=>'1','zksubtype'=>'1','zktitle'=>'9.9包邮');
        //$message = array('msg'=>'软件升级');
        
        
        $ctx = stream_context_create();
        
        stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck_dev.pem');
        
        stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
        
        // Open a connection to the APNS server
        
        //这个为正是的发布地址
        //$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
        
        //这个是沙盒测试地址,发布到appstore后记得修改哦
        $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
        
        
        if (!$fp)
        exit("Failed to connect: $err $errstr" . PHP_EOL);
        echo 'Connected to APNS' . PHP_EOL;
        
        // Create the payload body
            
        $body['aps'] = array(
                             'alert' => '逗你玩!哈哈。',
                             'sound' => 'beep.wav',
                             'badge' => 1
                             );
        $body['type']=2;
        $body['data']=$message;
        
        // Encode the payload as JSON
        
        $payload = json_encode($body);
        
        // Build the binary notification
        
        $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
        
        // Send it to the server
        
        $result = fwrite($fp, $msg, strlen($msg));
        
        if (!$result)
        
        echo 'Message not delivered' . PHP_EOL;
        
        else
        
        echo 'Message successfully delivered' . PHP_EOL;
        
        // Close the connection to the server
        
        fclose($fp);
        
        ?>

    客户端代码:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
        // Override point for customization after application launch.
        
        main = [[MainViewController alloc] init];
        navMain = [[UINavigationController alloc] initWithRootViewController:main];
        self.window.rootViewController = navMain;
        
        notifiDic = [[NSMutableDictionary alloc] init];
        
        [self initNotification];
        
        [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
        
        
        NSLog(@"launchOption==%@",[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]);
        if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey] != nil) {
            
            if (notifiDic.count != 0) {
                [notifiDic removeAllObjects];
            }
            [notifiDic setDictionary:(NSDictionary *)[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]];
            
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"didFinishLaunching" message:[NSString stringWithFormat:@"didFinishLaunching:\n%@",launchOptions] delegate:self cancelButtonTitle:@"Cancek" otherButtonTitles:@"OK", nil];
            [alert show];
            alert.tag = 101;
            [alert release];
            
    
        }
        
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    - (void)initNotification{
        [[UIApplication sharedApplication]registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert |UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound)];
    }
    #pragma mark -
    -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
        NSLog(@"deviceToken: %@", deviceToken);
        NSLog(@"deviceToken===%@",[deviceToken description]);
        
        NSRange _range = NSMakeRange(1,[[deviceToken description] length]-2);
        NSString *deviceTokenStr = [[deviceToken description] substringWithRange:_range];
        NSLog(@"deviceTokenStr==%@",deviceTokenStr);
        deviceTokenStr = [deviceTokenStr stringByReplacingOccurrencesOfString:@" " withString:@""];
        NSLog(@"deviceTokenStr==%@",deviceTokenStr);
        
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"product deviceToken" message:deviceTokenStr delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alertView show];
        [alertView release];
        
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
        
        NSLog(@"%s,,,,%@",__func__,userInfo);
        
        if (notifiDic.count != 0) {
            [notifiDic removeAllObjects];
        }
        [notifiDic setDictionary:userInfo];
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:[NSString stringWithFormat:@"受到的通知如下:\n%@",userInfo] delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
        [alert show];
        alert.tag = 100;
        [alert release];
        
    }
    
    - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
        NSLog(@"%s",__func__);
    }

    注意点:

    1.推送证书都弄好后,项目的开发证书要重新下载一下。

    1.反馈服务

    Apple 还提供了一个  馈服务 ,你应该定期查询。它提供了一个以前使用过但不再有效的(例如用户卸载了你的iPhone程序)设备令牌列表。你可以从你的数据库中删除这些设备令牌。

    本教程不涉及反馈服务的使用。

    2.创建载荷

    使用 PHP 很容易根据数组并  换成 JSON而创建载荷:

    $payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');

    $payload = json_encode($payload);

    显示 $payload 的内容可以看到传送到APNS  JSON字符串:

    {

         "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" }

    }

    这将使消息显示于设备上,触发提升声音并将“1”置于程序图标上。默认按钮“Close”“View”同时会显示于弹出窗口上。

    对于 Server Density iPhone程序而言,让用户按下“View”直接进入产生此提示的服务器是很重要的,所以我们增加了额外的自定义值:

    $payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');

    $payload['server'] = array('serverId' => $serverId, 'name' => $name);

    $output = json_encode($payload);

    当用户按下“View”后,自定义server值将被传递到设备中的程序。JSON 值如下:

    {

         "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" },

         "server" : { "serverId" : 1, "name" : "Server name")

    }

    256字节的限制适用于整个载荷,包括自定义字典集。

      

    原生接口

    Server Density中,一旦产生了一条提示,将建立一个载荷并插入队列中。因此有必要时我们可以同时发送多个载荷。

    Apple推荐使用这种方法,因为如果你在发送各载荷时频繁连接和断开,APNS有可能会封锁你的IP

    3.Push Notification Provider 是一个应用程序,用于通过 APNs 发送推送通知给 iPhone 应用。

    通过 APNs 发送推送通知有几个步骤:
    1.
    使用前面创建的 SSL 证书与 APNs 通讯;

    2. 构造所要发送的消息载体;

    3. 发送载体到APNs

    APNs 是一个基于流的 TCP socket,你的 provider SSL 协议与其通讯。推送通知(包括载体)是以二进制流的方式发送的。和APNs 建立连接后,你可以维持该连接并在连接中断之前发送多个通知。

    技巧:应避免每发送一次推送通知就建立、关闭一次连接。频繁的建立、关闭连接可能会被 APNs 认为是 DOS 攻击,从而拒绝发送 provider 的推送通知发送请求。

  • 相关阅读:
    为什么页面设计宽度要控制在960px
    RRDtool运用
    cacti监控jvm
    cacti安装
    rConfig v3.9.2 授权认证与未授权RCE (CVE-2019-16663) 、(CVE-2019-16662)
    Linux安全学习
    Github-Dorks与辅助工具
    警方破获超大DDoS黑产案,20万个僵尸网络运营商被抓
    SRC漏洞挖掘
    威胁情报木马病毒样本搜集
  • 原文地址:https://www.cnblogs.com/iphone520/p/3023687.html
Copyright © 2011-2022 走看看