新的APNS提供程序API和PHP

时间:2016-01-08 18:53:58

标签: php ios iphone apple-push-notifications

我开始创建一些基于this的代码,用于从PHP发送推送通知。

但是现在我已经知道有一个新的API利用HTTP / 2并在响应中提供反馈,我试图弄清楚我需要做些什么来获得反馈。

我还没有能够找到任何教程或示例代码来指导我(我猜是因为它是如此新的)。

是否可以使用stream_socket_client()方法通过新的提供者API连接到APNS?我如何获得反馈?我现在从fwrite($fp, $msg, strlen($msg))回来的只是一个数字。出于所有意图和目的,您可以将我的代码视为与the SO question I based my code on

中的代码相同

谢谢!

7 个答案:

答案 0 :(得分:32)

使用新的HTTP / 2 APNS提供程序API,您可以使用curl发送推送通知。

修改

在继续之前(如@Madox所述),应安装openssl> = 1.0.2e(最好从包中)。使用命令验证

openssl version

a)您的PHP版本应该是> = 5.5.24,以便定义常量CURL_HTTP_VERSION_2_0。

b)确保使用

在系统中安装了卷曲版本7.46+
curl --version

c)Curl应该启用http / 2支持。在键入上一个命令的输出中,您应该看到如下所示的行:

Features: IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets 

如果HTTP2没有显示,您可以按照这个优秀的教程安装http / 2 for curl https://serversforhackers.com/video/curl-with-http2-support

验证curl检测到openssl> = 1.0.2e,做curl --version应输出如下内容:

curl 7.47.1 (x86_64-pc-linux-gnu) libcurl/7.47.1 OpenSSL/1.0.2f zlib/1.2.8 libidn/1.28 nghttp2/1.8.0-DEV librtmp/2.3

e)安装好所有内容后,您可以在命令行中对其进行测试:

curl -d '{"aps":{"alert":"hi","sound":"default"}}' \ 
--cert <your-certificate.pem>:<certificate-password> \ 
-H "apns-topic: <your-app-bundle-id>" \ 
--http2  \ 
https://api.development.push.apple.com/3/device/<device-token>

f)以下是我成功尝试的PHP示例代码:     

if(defined('CURL_HTTP_VERSION_2_0')){

    $device_token   = '...';
    $pem_file       = 'path to your pem file';
    $pem_secret     = 'your pem secret';
    $apns_topic     = 'your apns topic. Can be your app bundle ID';


    $sample_alert = '{"aps":{"alert":"hi","sound":"default"}}';
    $url = "https://api.development.push.apple.com/3/device/$device_token";

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $sample_alert);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("apns-topic: $apns_topic"));
    curl_setopt($ch, CURLOPT_SSLCERT, $pem_file);
    curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $pem_secret);
    $response = curl_exec($ch);
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    //On successful response you should get true in the response and a status code of 200
    //A list of responses and status codes is available at 
    //https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1

    var_dump($response);
    var_dump($httpcode);

}

答案 1 :(得分:4)

我想在tiempor3al回答中添加一些信息。

1)curl必须使用openssl版本&gt; = 1.0.2进行编译才能完全支持http / 2。当我使用CentOS stock openssl-1.0.1e编译它时,我收到“?@@?HTTP / 2客户端序言字符串丢失或损坏...”错误。

2)如果你的php模块mod_curl.so的版本在没有CURL_HTTP_VERSION_2_0的情况下编译,你可以用整数3替换它:

curl_setopt($ch, CURLOPT_HTTP_VERSION, 3);

答案 2 :(得分:4)

我可以使用php CURL成功通过HTTP2发送推送,并直接在响应正文中阅读反馈(这里我写了一篇关于如何执行此操作的简短教程:Sending Push Notification with HTTP2 (and PHP))。 我认为你可以检查从套接字读取的响应体(我不记得确切的PHP功能,也许&#34; fgets&#34;)。

答案 3 :(得分:4)

我使用的是CentOS 6,解决方法是从源cURL和OpenSSL安装。

它可能看起来很简单,但我花了3天的时间来确定包装的正确配置,所以我想我可以通过发布我在这里做的事来帮助别人。

这对我来说有点棘手,因为我不习惯从源代码安装软件包,但我现在可以使用HTTP / 2上的HTTPS连接到APN。

我所做的详情如下:

  1. 下载并解压缩cURL和OpenSSL:

    wget https://curl.haxx.se/download/curl-7.47.1.tar.gz
    wget https://www.openssl.org/source/openssl-1.0.2h.tar.gz
    
  2. 使用以下标志配置OpenSSL(我不知道他们做了什么,但对我有用):

    export CXXFLAGS="$CXXFLAGS -fPIC"
    ./config zlib enable-ssl3 enable-shared
    
  3. 制作并安装OpenSSL

  4. 使用以下标志配置cURL:

    ./configure --with-ssl=/usr/local/ssl/
    
  5. 制作并安装cURL

  6. 将LD_LIBRARY_PATH设置为/ usr / local / ssl / lib /

    export LD_LIBRARY_PATH=/usr/local/ssl/lib/                  
    
  7. 测试

    /usr/local/bin/curl -v -d '{"aps":{"alert":"hi","sound":"default"}}' --cert cert.crt --key cert.key -H "apns-topic: topics" --http2 https://api.development.push.apple.com:443/3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
    
  8. 结果:

    *   Trying 17.172.238.203...
    * Connected to api.development.push.apple.com (17.172.238.203) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
    * successfully set certificate verify locations:
    *   CAfile: /etc/pki/tls/certs/ca-bundle.crt
      CApath: none
    * TLSv1.2 (OUT), TLS header, Certificate Status (22):
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Request CERT (13):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Certificate (11):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS handshake, CERT verify (15):
    * TLSv1.2 (OUT), TLS change cipher, Client hello (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: CN=api.development.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US
    *  start date: Jun 19 01:49:43 2015 GMT
    *  expire date: Jul 18 01:49:43 2017 GMT
    *  subjectAltName: host "api.development.push.apple.com" matched cert's "api.development.push.apple.com"
    *  issuer: CN=Apple IST CA 2 - G1; OU=Certification Authority; O=Apple Inc.; C=US
    *  SSL certificate verify ok.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * TCP_NODELAY set
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x1091110)
    > POST /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0 HTTP/1.1
    > Host: api.development.push.apple.com
    > User-Agent: curl/7.48.0
    > Accept: */*
    > apns-topic: topics
    > Content-Length: 40
    > Content-Type: application/x-www-form-urlencoded
    >
    * Connection state changed (MAX_CONCURRENT_STREAMS updated)!
    * We are completely uploaded and fine
    < HTTP/2.0 400
    <
    * Connection #0 to host api.development.push.apple.com left intact
    {"reason":"BadDeviceToken"}
    

    正如你所看到的,我摆脱了丑陋的

    ▒@@▒HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 504f5354202f332f6465766963652f746573742048545450
    

答案 4 :(得分:1)

按照本指南[http://cloudfields.net/blog/ios-push-notifications-encryption/][1]生成并合并您的证书和私钥。 一旦你使用相同的文件名合并你的sslcert和pkey,只需尝试下面的curl命令。

curl -X POST -H 'apns-topic: com.mycompany.ios.BadassApp' -d '{"aps":{"content-available":1,"alert":"hi","sound":"default"}}' --cert apns_cert.pem:yourCertPassword --http2 'https://api.development.push.apple.com:443/3/device/b8de1sf067effefc398d792205146fc67dn0e96b0ff21ds81cabe384bbe71353'

答案 5 :(得分:1)

要解决PHP 5.6中的HTTP/2 client preface string missing or corrupt错误,我创建了一个您可能想依赖的ApacheCLI PHP Docker镜像,或者只是查看我在Dockerfile中所做的事情来构建你自己。同样可能适用于PHP 7.0,虽然我没有尝试过。

答案 6 :(得分:-1)

是的,有可能:

$errno=0;$errstr="";
$sock = stream_socket_client(
  "api.push.apple.com:443",
  $errno,
  $errstr,
  4,
  STREAM_CLIENT_CONNECT,
  stream_context_create(["ssl" => ["local_cert" => "/path/to/cert.pem","verify_peer"=>false,"verify_peer_name"=>false]])
);
stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);