zoukankan      html  css  js  c++  java
  • PHP苹果推送实现(APNS)

    以下资料网上收集整理得来

    1、在ios dev center制作相关证书和文件用客户端实现(不再赘述,网上很多,)
    网上教程:
    http://blog.csdn.net/lizhenning87/article/details/8259270
    官方文档:
    https://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/ProvisioningDevelopment/ProvisioningDevelopment.html#//apple_ref/doc/uid/TP40008194-CH104-SW1

    2、制作好后下载下来,双击导入。然后在钥匙串访问处找到刚导入的证书,展开可看到钥匙,选中证书,导出.p12文件,由于PHP不好处理这种格式,所以要转换成.pem文件,方法如下,在终端执行:
    openssl pkcs12 -in CertificateName.p12 -out CertificateName.pem -nodes(将文伯拖入终端可以免去自己写路径),分别制作一个production,development证书

    4、服务端,创建测试文件apns.php,并将CertificateName.pem放到同一目录,
    正式地址:gateway.push.apple.com, port 2195(使用正式证书)
    测试地址:gateway.sandbox.push.apple.com, port 2195(使用测试证书)

    //接收到设备发来的token,这里我手动填上。
    $deviceToken = "015c5a2377ac146830f8ed09059b82bb91ed7190ebf74b633809bc2245da95ee";
    //构造消息体
    $body = array("aps" => array("alert" => '测试测试测试', "badge" => 1, "sound" => 'received5.caf'));
    $ctx = stream_context_create();
    stream_context_set_option($ctx, "ssl", "local_cert", "CertificateName.pem");
    //建立socket连接
    $fp = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
    if (!$fp) { print "Failed to connect $err $errstrn"; return; }
    print "Connection OK";
    $payload = json_encode($body);
    $msg = chr(0) . pack("n",32) . pack("H*", $deviceToken) . pack("n",strlen($payload)) . $payload;
    print "sending message :" . $payload . "
    ";
    fwrite($fp, $msg);
    fclose($fp);
    

    5、服务器返馈
    当用户将我们的应用删除时,我们应该停止对这台机器推送,这个SSL地址是:
    正式机:feedback.push.apple.com, port 2196
    测试机:feedback.sandbox.push.apple.com, port 2196

    具本见

    https://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html

    php如下:

    $certFile = 'apns-dev.pem';
    while(true){
    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', $certFile);
    //stream_context_set_option($ctx, 'ssl', 'passphrase', $this->certPass);
    echo "try to open stream
    ";
    $fp = stream_socket_client('ssl://feedback.sandbox.push.apple.com:2196', $err, $errstr, 5, STREAM_CLIENT_CONNECT, $ctx);
    if (!$fp) {
    print "Failed to connect". $err . $errstr. "
    ";
    exit();
    }
    else
    {
    echo 'Connected to feedback sandbox...';
    while(($in = fread($fp, 1024)) != EOF)
    {
    echo 'read '. $in . "
    ";
    }
    socket_close($fp);
    fclose($fp);
    }
    sleep(2000);
    }
    

     注意,要将你的APP删除后,再发一个推送,才可能返回数据

    开发状态服务器地址 gateway.sandbox.push.apple.com 2195
    产品状态服务器地址 gateway.push.apple.com         2195

    Development和Production两个版本对应的apns device token是不同的,前者是develop的mobileprovision下获取的。后者是production的mobileprovision获取的。
    Development和Production两个版本可以共用一个App ID(不推荐。共用时每次调试前都要删除设备上的app,重新打包生成。而且公用appid会经常抓狂,早上行,下午就不行了。所以不推荐),但是不能共用一个mobileprovision,所以要单独生成Distribution的证书供production版本使用。
    注:Distribution的版本是无法在设备上debug调试的!
    Development和Production两个版本的code sign是不同的,前者是iPhone Developer,后者是iPhone Distribution。注意不能搞错。

    无论是Development Push SSLCertificate还是Production Push SSL Certificate 都有过期时间的。
    Development Push SSL Certificate有效期大概四个月左右,而ProductionPush SSL Certificate的有效期是一年。需要注意在过期之前生成新的证书,以免影响使用。

    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-cert.p12
    openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
    cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

    在Mac上生成 Apple推送通知SSL许可证:
        1.    登录到 iPhone Developer Connection Portal 并点击 App IDs
        2.    创建一个不使用通配符的 App ID 。通配符 ID 不能用于推送通知服务。例如,我们的iPhone程序ID像这样:  AB123346CD.com.serverdensity.iphone
        3.    点击App ID旁的“Configure”,然后按下按钮生产 推送通知许可证。根据“向导”指导的步骤生成一个签名并上传,最后下载生成的许可证。此步骤在 Apple文档中 也有谈到。
        4.    通过双击.cer文件将你的 aps_developer_identity.cer 引入Keychain中。
        5.    在Mac上启动 Keychain助手,然后在login keychain中选择 Certificates分类。你将看到一个可扩展选项“Apple Development Push Services”
        6.    扩展此选项然后右击“Apple Development Push Services” > Export “Apple Development Push Services ID123”。保存为 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
        9.    转换得到key的pem:
    openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-cert.p12
        10.    如果你想要移除密码,要么在导出/转换时不要设定或者执行:
    openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
        11.    最后,你需要将键和许可文件合成为apns-dev.pem文件,此文件在连接到APNS时需要使用:
    cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

    将此文件保存为一个易记的名字,你有可能以后会用到它。上述步骤同样适合于生成产品许可证。

    检验证书是否正确的方法:

    $ telnet gateway.sandbox.push.apple.com 2195

    Trying 17.172.232.226…

    Connected to gateway.sandbox.push-apple.com.akadns.net.

    Escape character is ‘^]’.

    它将尝试发送一个规则的,不加密的连接到APNS服务。如果你看到上面的反馈,那说明你的MAC能够到达APNS。按下Ctrl+C 关闭连接。如果得到一个错误信息,那么你需要确保你的防火墙允许2195端口。

    然后再次连接,这次用我们的SSL证书和私钥来设置一个安全的连接:

    $ openssl s_client -connect gateway.sandbox.push.apple.com:2195

    -cert PushChatCert.pem -key PushChatKey.pem

    Enter pass phrase for PushChatKey.pem:

    你会看到一个完整的输出,让你明白OpenSSL在后台做什么。如果连接是成功的,你可以键入一些字符。当你按下回车后,服务就会断开连接。如果在建立连接时有问题,OpenSSL将会给你一个错误消息,但是你不得不向上翻输出LOG,来找到它。

    当然上面要测试prodution版本是否正确的话,把gateway.sandbox.push.apple.com换成gateway.push.apple.com就好。




    客户端很好做,申请证书,复制代码,就行了。
    服务器端,如果是php的,那必须使用.pem的证书,如果是java的,那必须使用.p12的证书。(很可能还需要双击证书进行安装!)
    服务器端发出的json包是有大小限制的,最大256字节,包括自定义字典集。
    aps中的alert字符串里是可以添加" "做换行的。
    json包中除了alert,badge,sound之外,还是是可以自定值的。

    额外的自定义值:
      $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" :
                          {
                            "action-loc-key" : "显示" ,
                            "body" : "This is the alert text"
                           },
                 "badge" : 1,
                 "sound" : "default" },
      "server" : { "serverId" : 1, "name" : "Server name")
      }
      256字节的限制适用于整个payload,包括自定义字典集。


      原生接口
      在Server Density中,一旦产生了一条提示,将建立一个payload并插入队列中。因此有必要时我们可以同时发送多个payload。
      Apple推荐使用这种方法,因为如果你在发送各payload时频繁连接和断开,APNS有可能会封锁你的IP。
      如Apple 描述:
      原生接口使用原生socket,具有二进制内容,采用数据流技术,不产生回馈。

    高人的总结:
    APPLE推送通知服务教程 PART-1
    APPLE推送通知服务教程 PART-2
    APPLE推送通知服务教程 PART-3
    apns php版本:
    https://code.google.com/p/apns-php/wiki/CertificateCreation

    IOS7之前,苹果对于一个设备上的多个APP,生成相同的DeviceToken。
    IOS7以及之后,苹果对于一个设备上的多个APP,生成不同的DeviceToken。
    这种新改变导致APNS上创建了一张新老token的映射表,如果你一直用老的token,那没问题,但是,一旦服务器使用新的DeviceToken,映射表中的记录就会被删除,这意味着,老的DeviceToken就不能用了,必然发送失败。
    待验证:IOS5和IOS6,APP永远可以获取DeviceToken,除此之外的系统,如果用户拒绝了,或者关闭了推送,那么无法获取DeviceToken,走失败回调。
    原文出处:https://support.urbanairship.com/customer/portal/articles/1321513-how-ios-7-handles-push-differently
    http://stackoverflow.com/questions/6652242/does-the-device-token-ever-change-once-created

    生成证书需要注意事项:
    苹果开发者账号分好几种角色
    Agent:代理人,拥有最高权限,可以访问iTunes Connect。
    Admin:管理员,拥有管理成员、维护设备列表,维护APPID以及证书列表权限。
    Member:普通成员,只读权限。

    备注:3013.9.11经过测试,我发现前段时间苹果网站下线期间更新了证书生成机制。以前,利用钥匙串生成一个CSR文件,可以一直用。但是,现在每当你要生成证书,做generate的时候都需要提前重新生成一个CSR文件,否则你生成的证书都是无效的,假证书,尤其是PUSH的,服务端使用这种证书根本无法和APNS建立连接,这种诡异的问题超难跟踪的!希望看到这段话的人都能避免走弯路,不用谢了!

    在使用PushMeBaby中也遇到各种问题。首先,虽然工程中已经使用了.cer的公钥证书,但是本地钥匙串中必须有带私钥的证书,否则连接无法成功建立。而且需要注意的是,证书最好放在“登录”分组中,否则程序也是找不到私钥的。其次,原始的工程中在scanString的时候会死循环,需要修改为如下代码:
        NSUInteger count = 0;
        while(![scanner isAtEnd]) {
            [scanner scanHexInt:&value];
            value = htonl(value);
            [deviceTokenData appendBytes:&value length:sizeof(value)];
            if (++count >= [self.deviceToken length]-1) {
                break;
            }
        }

  • 相关阅读:
    octotree神器 For Github and GitLab 火狐插件
    实用篇如何使用github(本地、远程)满足基本需求
    PPA(Personal Package Archives)简介、兴起、使用
    Sourse Insight使用过程中的常使用功能简介
    Sourse Insight使用教程及常见的问题解决办法
    github 遇到Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts问题解决
    二叉查找树的C语言实现(一)
    初识内核链表
    container_of 和 offsetof 宏详解
    用双向链表实现一个栈
  • 原文地址:https://www.cnblogs.com/ymms/p/3865913.html
Copyright © 2011-2022 走看看