Новый API-интерфейс APNS-провайдера и PHP

Я начал создавать код на основе этого для отправки push-уведомлений с PHP.

Однако теперь, когда я понял, есть новый API, который использует HTTP/2 и обеспечивает обратную связь в ответе, я пытаюсь выяснить, что мне нужно сделать, чтобы получить эту обратную связь.

Я не смог найти какие-либо учебники или примеры кода, чтобы дать мне направление (я думаю, потому что это так новичок).

Можно ли использовать метод stream_socket_client() для подключения к APNS с новым API-интерфейсом поставщика? Как получить обратную связь? Все, что я вернусь из fwrite($fp, $msg, strlen($msg)) прямо сейчас, это число. Для всех целей и целей вы можете считать мой код таким же, как код из вопроса SO, на котором я основывал свой код на

Спасибо!

Ответы

Ответ 1

С помощью нового API-провайдера APNS HTTP/2 вы можете использовать curl для отправки push-уведомлений.

ИЗМЕНИТЬ

Прежде чем продолжить (как отмечено @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 для 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);

}

Ответ 2

Я хочу добавить некоторую информацию в ответ tiempor3al.

1) curl должен быть скомпилирован с версией openssl >= 1.0.2 для полной поддержки http/2. Я получаю сообщение об ошибке "@@? HTTP/2 preface string missing или corrupt...", когда я скомпилировал его с помощью файла CentOS openssl-1.0.1e.

2) если ваша версия php-модуля mod_curl.so скомпилирована без константы CURL_HTTP_VERSION_2_0, вы можете заменить ее целым числом 3:

curl_setopt($ch, CURLOPT_HTTP_VERSION, 3);

Ответ 3

Я мог бы успешно отправить push через HTTP2 с помощью php CURL и прочитать обратную связь непосредственно в теле ответа (здесь я написал короткий учебник о том, как это сделать: Отправка Push-уведомления с помощью HTTP2 (и PHP)). Я думаю, что вы можете проверить чтение тела ответа из сокета (я точно не помню функцию php, возможно, "fgets" ).

Ответ 4

Я использую CentOS 6, и способ решить - установить из исходных cURL и OpenSSL.

Это может показаться очень простым, но мне потребовалось 3 дня, чтобы выяснить правильную конфигурацию пакетов, поэтому я думаю, что могу помочь кому-то, разместив здесь то, что я здесь сделал.

Мне это показалось немного сложным, так как я не привык устанавливать пакеты из исходного кода, но теперь я могу подключиться к APN, используя HTTPS через HTTP/2.

Детали того, что я сделал, здесь:

  • Загрузите и распакуйте 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
    
  • Настройте OpenSSL со следующими флагами (я не уверен, что они делают, но это то, что сработало для меня):

    export CXXFLAGS="$CXXFLAGS -fPIC"
    ./config zlib enable-ssl3 enable-shared
    
  • создать и установить OpenSSL

  • Настройте cURL со следующим флагом:

    ./configure --with-ssl=/usr/local/ssl/
    
  • Сделать и установить cURL

  • установить LD_LIBRARY_PATH в /usr/local/ssl/lib/

    export LD_LIBRARY_PATH=/usr/local/ssl/lib/                  
    
  • Test

    /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 "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

Ответ 5

Следуйте этому руководству [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'

Ответ 6

Чтобы разрешить ошибки HTTP/2 client preface string missing or corrupt в PHP 5.6, я создал Apache и CLI Изображение PHP Docker, на которое вы, возможно, захотите положиться, или просто посмотрите, что я сделал в Dockerfile, чтобы создать собственный. То же самое можно применить к PHP 7.0, хотя я не пробовал.

Ответ 7

да, возможно:

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