it-swarm.com.ru

Новый API провайдера APNS и PHP

Я начал создавать некоторый код, основанный на this для отправки Push-уведомлений из PHP.

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

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

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

Спасибо!

17
Ben Holness

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

ПРАВКА

Прежде чем продолжить (как отмечает @Madox), openssl> = 1.0.2e должен быть установлен (из пакета желательно). Подтвердите с помощью команды 

openssl version

a) Ваша версия PHP должна быть> = 5.5.24, чтобы была определена константа CURL_HTTP_VERSION_2_0.

б) Убедитесь, что в вашей системе установлена ​​версия curl 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

д) После того, как вы все установили, вы можете проверить это в командной строке:

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

}
31
tiempor3al

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

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

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

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

  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
    

Результат:

*   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
Samo

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

1) curl должен быть скомпилирован с версией openssl> = 1.0.2 для полной поддержки http/2. Я получаю сообщение об ошибке «? @@? HTTP/2 клиентская строка отсутствует или повреждена ...» при компиляции с помощью CentOS stock openssl-1.0.1e.

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

curl_setopt($ch, CURLOPT_HTTP_VERSION, 3);

4
Madox

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

4
valfer

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

1
Norbert

Следуйте этому руководству [ http://cloudfields.net/blog/ios-Push-notifications-encryption/][1] , чтобы создать и объединить ваш сертификат и закрытый ключ .... 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'
1
KeranMarinov