apple-push-notifications - 使用 php 的 APNs 提供商 API HTTP/2,curl 导致发送的多个推送通知出现错误

标签 apple-push-notifications http2

我已经设置了一个运行 Ubuntu 15.10 x64 的 Linux 服务器。我已经设置 php/openssl/curl 一起使用 HTTP/2 发送。我正在测试的 PHP 脚本如下。基本上,我发送两条推送消息,均使用相同的curl 句柄,以便按照 Apple 的建议保持连接打开。第一条消息顺利通过并显示在我的设备上,但是当它尝试发送第二条消息时,我在“SSL”之后收到错误“连接到 api.development.push.apple.com:443 的未知 SSL 协议(protocol)错误”重新使用 session ID”。有人对可能出现的问题有什么建议吗?有人可以尝试这个脚本并让我知道他们是否遇到同样的事情吗?

以下是我的服务器的版本打印输出:

PHP

PHP 7.0.5-2+deb.sury.org~wily+1 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

OpenSSL

OpenSSL 1.0.2d 9 Jul 2015

curl

curl 7.48.0 (x86_64-pc-linux-gnu) libcurl/7.48.0 OpenSSL/1.0.2d zlib/1.2.8 libidn/1.28 nghttp2/1.10.0-DEV librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: IDN IPv6 Largefile NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets

PHP 代码:

<?php
$ch = curl_init();
$device_token   = 'TOKEN HERE';
$pem_file       = 'YOURFILE.pem';
$pem_secret     = 'PEM PASS';
$apns_topic     = 'com.YOURTOPIC';

//curl_setopt($ch, CURLOPT_SSLVERSION, 6);
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);
curl_setopt($ch, CURLOPT_VERBOSE , true);

echo "Try 1 ================================================" . PHP_EOL;

//setup and send first push message
$url = "https://api.development.push.apple.com/3/device/$device_token";
curl_setopt($ch, CURLOPT_URL, "{$url}");
$sample_alert = '{"aps":{"alert":"hi #1","sound":"default"}}';
curl_setopt($ch, CURLOPT_POSTFIELDS, $sample_alert);

$response = curl_exec($ch);
$httpcode = curl_getinfo($ch);
//var_dump($response);
//var_dump($httpcode);

echo "Try 2 ================================================" . PHP_EOL;

//setup and send second push message
$url = "https://api.development.push.apple.com/3/device/$device_token";
curl_setopt($ch, CURLOPT_URL, "{$url}");
$sample_alert = '{"aps":{"alert":"hi #2","sound":"default"}}';
curl_setopt($ch, CURLOPT_POSTFIELDS, $sample_alert);

$response = curl_exec($ch);
$httpcode = curl_getinfo($ch);
//var_dump($response);
//var_dump($httpcode);

curl_close($ch);

使用curl verbose运行上述脚本的输出(个人项目替换为XXXXX):

Try 1 ================================================
*   Trying 17.110.227.100...
* Connected to api.development.push.apple.com (17.110.227.100) 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/ssl/certs/ca-certificates.crt
  CApath: none
* SSL connection using TLSv1.2 / XXXXXXXXXXXXXXXXXXXXXXXXXXX
* 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 0x555e84417f80)
> POST /3/device/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
HTTP/1.1
Host: api.development.push.apple.com
Accept: */*
apns-topic: com.XXXXXXX.XXXXXXXXXXXXXXXXXX
Content-Length: 43
Content-Type: application/x-www-form-urlencoded

* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* We are completely uploaded and fine
< HTTP/2.0 200
< apns-id:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
<
* Connection #0 to host api.development.push.apple.com left intact
Try 2 ================================================
* Found bundle for host api.development.push.apple.com: 0x555e8442afb0 [can multiplex]
* Hostname api.development.push.apple.com was found in DNS cache
*   Trying 17.110.227.100...
* Connected to api.development.push.apple.com (17.110.227.100) port 443 (#1)
* 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/ssl/certs/ca-certificates.crt
  CApath: none
* SSL re-using session ID
* Unknown SSL protocol error in connection to api.development.push.apple.com:443
* Closing connection 1

最佳答案

我尝试了你的代码,它在我的机器上运行正常。尽管如此,我还是发现我们的详细日志之间存在一些差异。 Try 1 的日志是相同的,但是 Try 2 的日志有一些差异,这是我的:

...
Try 2 ================================================
* Found bundle for host api.development.push.apple.com: 0x7fe1b380e730 [can multiplex]
* Re-using existing connection! (#0) with host api.development.push.apple.com
* Connected to api.development.push.apple.com (17.172.238.203) port 443 (#0)
* Using Stream ID: 3 (easy handle 0x7fe1b305da00)
> POST /3/device/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX HTTP/1.1
Host: api.development.push.apple.com
Accept: */*
apns-topic: it.XXX.XXXXX
Content-Length: 43
Content-Type: application/x-www-form-urlencoded

* We are completely uploaded and fine
< HTTP/2.0 200
< apns-id:XXXXXXXXXXXXXXXXX
< 
* Connection #0 to host api.development.push.apple.com left intact

我在您的日志中没有看到“重新使用现有连接!”文本...

编辑

解决方案似乎是将curl降级到7.47.1

关于apple-push-notifications - 使用 php 的 APNs 提供商 API HTTP/2,curl 导致发送的多个推送通知出现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36611384/

相关文章:

ios - 每 X 小时重复一次推送通知

iphone - 随时禁用推送通知声音

javascript - 对在 HTTP1 和 HTTP2 中发送请求感到困惑

java - 使用 IntelliJ 将 Java lambda 转换为 Kotlin Lambda 生成语法错误

HTTP/2 推送 promise 行为

ios - 有没有办法阻止用户在从 Firebase 发送后接收推送通知?

javascript - Phonegap iOS 推送通知示例

php - 使用 PHP 向应用程序的所有 iOS 用户发送推送通知

nginx - 在 Windows 上的 Nginx 上启用 http2

php - 在apache php上实现http2推送方法