Memo

メモ > 技術 > サービス: AmazonSNS > iOS: アプリにPHPからPushを送信(HTTP/2版)

■iOS: アプリにPHPからPushを送信(HTTP/2版)
※「旧式のバイナリインターフェイス」が使える間は、この手順は省略できる が、早い段階で検証しておくことを推奨 APNs Provider API(HTTP/2)をPHPで試してみる - Qiita https://qiita.com/itosho/items/2402df4de85b360d5bd9 ■pemファイルの作成 「iOS: アプリにPHPからPushを送信」と同じ手順で作成する ■環境の構築 PHP curlでHTTP/2リクエストを実行するための設定 on CentOS 7 | 稲葉サーバーデザイン https://inaba-serverdesign.jp/blog/20171011/php_curl_http2_centos7.html PHP+curlでHTTP/2リクエストを送信できる環境が必要 上記ページが参考になりそうだが、Amazon Linux 2 なら特別な更新作業なしにPHP+curlでHTTP/2リクエストを送信できた 以下は2020年1月7日時点に構築した Amazon Linux 2。PHPはExtrasリポジトリからインストールした # cat /etc/system-release Amazon Linux release 2 (Karoo) # openssl version OpenSSL 1.0.2k-fips 26 Jan 2017 # php --version PHP 7.3.11 (cli) (built: Oct 31 2019 19:16:47) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies # curl --version curl 7.61.1 (x86_64-koji-linux-gnu) libcurl/7.61.1 OpenSSL/1.0.2k zlib/1.2.7 libidn2/2.3.0 libssh2/1.4.3 nghttp2/1.39.2 Release-Date: 2018-09-05 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy Metalink # php -r 'phpinfo();' | grep SSL SSL => Yes MULTI_SSL => No SSL Version => OpenSSL/1.0.2k core SSL => supported extended SSL => supported OpenSSL support => enabled OpenSSL Library Version => OpenSSL 1.0.2k-fips 26 Jan 2017 OpenSSL Header Version => OpenSSL 1.0.2k 26 Jan 2017 Native OpenSSL support => enabled # curl -vso /dev/null --http2 https://www.google.co.jp/ * Trying 216.58.197.131... * TCP_NODELAY set * Connected to www.google.co.jp (216.58.197.131) 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): } [5 bytes data] * TLSv1.2 (OUT), TLS handshake, Client hello (1): } [512 bytes data] * TLSv1.2 (IN), TLS handshake, Server hello (2): { [96 bytes data] * TLSv1.2 (IN), TLS handshake, Certificate (11): { [3491 bytes data] * TLSv1.2 (IN), TLS handshake, Server key exchange (12): { [148 bytes data] * TLSv1.2 (IN), TLS handshake, Server finished (14): { [4 bytes data] * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): } [70 bytes data] * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): } [1 bytes data] * TLSv1.2 (OUT), TLS handshake, Finished (20): } [16 bytes data] * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): { [1 bytes data] * TLSv1.2 (IN), TLS handshake, Finished (20): { [16 bytes data] * SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256 * ALPN, server accepted to use h2 * Server certificate: * subject: C=US; ST=California; L=Mountain View; O=Google LLC; CN=*.google.com * start date: Dec 3 14:48:49 2019 GMT * expire date: Feb 25 14:48:49 2020 GMT * subjectAltName: host "www.google.co.jp" matched cert's "*.google.co.jp" * issuer: C=US; O=Google Trust Services; CN=GTS CA 1O1 * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 } [5 bytes data] * Using Stream ID: 1 (easy handle 0x6fdb70) } [5 bytes data] > GET / HTTP/2 > Host: www.google.co.jp > User-Agent: curl/7.61.1 > Accept: */* > { [5 bytes data] * Connection state changed (MAX_CONCURRENT_STREAMS == 100)! } [5 bytes data] < HTTP/2 200 < date: Tue, 07 Jan 2020 02:42:04 GMT < expires: -1 < cache-control: private, max-age=0 < content-type: text/html; charset=Shift_JIS < p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info." < server: gws < x-xss-protection: 0 < x-frame-options: SAMEORIGIN < set-cookie: 1P_JAR=2020-01-07-02; expires=Thu, 06-Feb-2020 02:42:04 GMT; path=/; domain=.google.co.jp; Secure < set-cookie: NID=195=J90uYLvbutUBMyCjx5B-cfvCaSQbmbTbItStMl_8Md-t_k6qRCq18qweObs-AYSOHrUVkw0u3xS-4y6DC_1kC4eOgd5JC94rgpdM9qm-62BiEZecOeYCMXqqZbdvZgdIEUpvAMBKM_gWQK2X_p5YFwtyCoHVl0M9B-wegtle3hc; expires=Wed, 08-Jul-2020 02:42:04 GMT; path=/; domain=.google.co.jp; HttpOnly < alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000 < accept-ranges: none < vary: Accept-Encoding < { [5 bytes data] * Connection #0 to host www.google.co.jp left intact ■テスト用PHPプログラム ※ファイルの文字コードは UTF-8N にする $ vi curl_test.php
<?php if (!defined('CURL_HTTP_VERSION_2_0')) { define('CURL_HTTP_VERSION_2_0', CURL_HTTP_VERSION_1_1 + 1); } $url = 'https://www.google.co.jp/'; $opts = [ CURLOPT_VERBOSE => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_SSL_VERIFYPEER => false ]; $ch = curl_init($url); curl_setopt_array($ch, $opts); curl_exec($ch); curl_close($ch);
以下で実行できる Googleのページデータを取得できれば成功 # php curl_test.php * Trying 172.217.25.227... * TCP_NODELAY set * Connected to www.google.co.jp (172.217.25.227) 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 * SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256 * ALPN, server accepted to use h2 * Server certificate: * subject: C=US; ST=California; L=Mountain View; O=Google LLC; CN=*.google.com * start date: Dec 10 08:42:43 2019 GMT * expire date: Mar 3 08:42:43 2020 GMT * issuer: C=US; O=Google Trust Services; CN=GTS CA 1O1 * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x55866798eba0) > GET / HTTP/2 Host: www.google.co.jp Accept: */* * Connection state changed (MAX_CONCURRENT_STREAMS == 100)! < HTTP/2 200 < date: Tue, 07 Jan 2020 02:54:02 GMT < expires: -1 < cache-control: private, max-age=0 < content-type: text/html; charset=Shift_JIS < p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info." < server: gws < x-xss-protection: 0 < x-frame-options: SAMEORIGIN < set-cookie: 1P_JAR=2020-01-07-02; expires=Thu, 06-Feb-2020 02:54:02 GMT; path=/; domain=.google.co.jp; Secure < set-cookie: NID=195=F6rGPJWX6DSZJFKvW036m6NKEqLkasi-SLWmkjF6rwGRm9Ks9S2Ix3xVj1Kplj1_C1Bg0gc8LOsjuFJcR64Orm-tR7h0pIBuncfPxFEZsqP-pysrYrU_ah2C24Tty8ng2cyDMIBiPbOBBlluAPryLSYiJbOTMX8DoCgjwpRMUzU; expires=Wed, 08-Jul-2020 02:54:02 GMT; path=/; domain=.google.co.jp; HttpOnly < alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000 < accept-ranges: none < vary: Accept-Encoding < <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head> 〜〜中略 </body></html>* Connection #0 to host www.google.co.jp left intact ■curlでプッシュを送信 以下のコマンドでプッシュを送信できる(curlで送信するならPHPは関係ない) $ curl -v -d '{"aps":{"alert":"[送信メッセージ]"}}' -H "[アプリのID]" --http2 --cert [pemファイル] https://api.development.push.apple.com/3/device/[デバイストークン] 具体的には以下のようになる (server_certificates_bundle_sandbox.pem は同じ階層に配置してあるものとする p12 ファイルではなく pem ファイルが必要なので注意) $ curl -v -d '{"aps":{"alert":"Hello!"}}' -H "net.refirio.pushtest1" --http2 --cert server_certificates_bundle_sandbox.pem https://api.development.push.apple.com/3/device/f7b8b8ade018f18e8b0dd9e34cfd1764575941243e21d9b47a6d... * Trying 17.188.165.219... * TCP_NODELAY set * Connected to api.development.push.apple.com (17.188.165.219) 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, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (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: Apr 17 17:37:51 2019 GMT * expire date: May 16 17:37:51 2021 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) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x2046b70) > POST /3/device/f7b8b8ade018f18e8b0dd9e34cfd1764575941243e21d9b47a6d3a3ad62d277b HTTP/2 > Host: api.development.push.apple.com > User-Agent: curl/7.61.1 > Accept: */* > Content-Length: 26 > Content-Type: application/x-www-form-urlencoded > * Connection state changed (MAX_CONCURRENT_STREAMS == 1000)! * We are completely uploaded and fine < HTTP/2 200 < apns-id: DE5A62A4-C4FE-E576-8245-03404F50A790 < * Connection #0 to host api.development.push.apple.com left intact ■PHPでプッシュを送信 ※ファイルの文字コードは UTF-8N にする apns_test.php
<?php if (defined('CURL_HTTP_VERSION_2_0')) { $ch = curl_init('https://api.development.push.apple.com/3/device/f7b8b8ade018f18e8b0dd9e34cfd1764575941243e21d9b47a6d3a3ad62d277b'); curl_setopt($ch, CURLOPT_POSTFIELDS, '{"aps":{"alert":"Hello!"}}'); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); curl_setopt($ch, CURLOPT_HTTPHEADER, ['apns-topic: net.refirio.pushtest1']); curl_setopt($ch, CURLOPT_SSLCERT, 'server_certificates_bundle_sandbox.pem'); //curl_setopt($ch, CURLOPT_SSLCERTPASSWD, 'your pem secret'); // pemファイルにパスワードを設定している場合は必要 $response = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); var_dump($response); var_dump($httpcode); }
以下で実行できる (server_certificates_bundle_sandbox.pem は同じ階層に配置してあるものとする) $ php apns_test.php bool(true) int(200) 送信内容に問題があると、JSON形式でエラー内容を返してくれる 以下はデバイストークンを間違えた場合の例 $ php apns_test.php {"reason":"BadDeviceToken"}bool(true) int(400)

Advertisement