新的APNS提供者API和PHP

我开始创build一些基于此的代码来发送来自PHP的推送通知。

但是现在我已经知道有一个新的API使用HTTP / 2并且在响应中提供了反馈,所以我想弄清楚我需要做什么才能得到这个反馈。

我一直没有find任何教程或示例代码给我指示(我猜是因为它是如此新)。

是否有可能使用连接到APNS的stream_socket_client()方法与新的提供者API? 我如何获得反馈? 我现在从fwrite($fp, $msg, strlen($msg))得到的所有数据都是一个数字。 对于所有的意图和目的,你可以认为我的代码与我的代码所依据的SO问题的代码相同

谢谢!

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

编辑

在继续之前(正如@Madox所指出的那样),应该安装openssl> = 1.0.2e。 validation与命令

 openssl version 

a)您的PHP版本应大于5.5.24,以便定义常量CURL_HTTP_VERSION_2_0。

b)确保你的系统中安装了curl版本7.46+

 curl --version 

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

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

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

validationcurl检测到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)一旦你安装了所有东西,你可以在命令行中testing它:

 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); } 

我想添加一些信息到tiempor3al的答案。

1)curl必须用openssl version> = 1.0.2来编译才能完全支持http / 2。 当我使用CentOS股票openssl-1.0.1e编译它时,收到“?@@?HTTP / 2客户端前言string丢失或损坏…”错误。

2)如果你的php模块mod_curl.so版本没有CURL_HTTP_VERSION_2_0编译常量,你可以用整数3replace它:

curl_setopt($ch, CURLOPT_HTTP_VERSION, 3);

我可以使用PHP CURL成功地通过HTTP2发送推送,并直接在响应主体中读取反馈(在这里我写了一个关于如何执行此操作的简短教程: 使用HTTP2(和PHP)发送推送通知 )。 我认为你可以检查从套接字响应身体阅读(我不记得确切的PHPfunction,也许“fgets”)。

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

它可能看起来很简单,但花了我3天的时间才弄清楚软件包的正确configuration,所以我想我可以通过发布我在这里发布的内容来帮助某人。

这对我来说有点棘手,因为我不习惯从源代码安装软件包,但现在我可以使用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. 用下面的标志configurationOpenSSL(我不知道他们做了什么,但是对我有用):

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

  4. 用以下标志configurationcURL:

     ./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. testing

     /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 

结果:

 * 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 

遵循本指南[ http://cloudfields.net/blog/ios-push-notifications-encryption/%5D%5B1%5D生成并合并您的证书和私钥&#x3002; 一旦你合并了你的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' 

为了在PHP5.6中解决HTTP/2 client preface string missing or corrupt错误,我创build了一个你可能想要依赖的Apache和CLI PHP Docker镜像,或者只是查看我在Dockerfile中构build自己的镜像。 同样可能适用于PHP 7.0,虽然我还没有尝试过。

是的,这是可能的:

 $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);