Отправить Push с.p8 и PHP
Мне нужно отправить Push-уведомления через PHP-скрипт, используя файл.p8, и я нашел следующий код в аналогичном вопросе, заданном здесь.
<?php
$keyfile = 'AuthKey_AABBCC1234.p8'; # <- Your AuthKey file
$keyid = 'AABBCC1234'; # <- Your Key ID
$teamid = 'AB12CD34EF'; # <- Your Team ID (see Developer Portal)
$bundleid = 'com.company.YourApp'; # <- Your Bundle ID
$url = 'https://api.development.push.apple.com'; # <- development url, or use http://api.push.apple.com for production environment
$token = 'e2c48ed32ef9b018........'; # <- Device Token
$message = '{"aps":{"alert":"Hi there!","sound":"default"}}';
$key = openssl_pkey_get_private('file://'.$keyfile);
$header = ['alg'=>'ES256','kid'=>$keyid];
$claims = ['iss'=>$teamid,'iat'=>time()];
$header_encoded = base64($header);
$claims_encoded = base64($claims);
$signature = '';
openssl_sign($header_encoded . '.' . $claims_encoded, $signature, $key, 'sha256');
$jwt = $header_encoded . '.' . $claims_encoded . '.' . base64_encode($signature);
// only needed for PHP prior to 5.5.24
if (!defined('CURL_HTTP_VERSION_2_0')) {
define('CURL_HTTP_VERSION_2_0', 3);
}
$http2ch = curl_init();
curl_setopt_array($http2ch, array(
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_URL => "$url/3/device/$token",
CURLOPT_PORT => 443,
CURLOPT_HTTPHEADER => array(
"apns-topic: {$bundleid}",
"authorization: bearer $jwt"
),
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $message,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_TIMEOUT => 30,
CURLOPT_HEADER => 1
));
$result = curl_exec($http2ch);
if ($result === FALSE) {
throw new Exception("Curl failed: ".curl_error($http2ch));
}
$status = curl_getinfo($http2ch, CURLINFO_HTTP_CODE);
echo $status;
function base64($data) {
return rtrim(strtr(base64_encode(json_encode($data)), '+/', '-_'), '=');
}
?>
Тем не менее, я обнаружил, что openssl_pkey_get_private
не читает файл ключа и выдает следующую ошибку при отладке.
$key = openssl_pkey_get_private('file://'.$keyfile);
if ($key === false) {
var_dump(openssl_error_string());
}
ошибка:
'error:02001002:system library:fopen:No such file or directory'
Обратите внимание, что нет проблем с curl
как HTTP2
был включен для curl
и я использую PHP7
, На этапе тестирования я использую скрипт и файл в одной папке, чтобы избежать проблем с путями.
Любая подсказка, где это пошло не так?
2 ответа
Пожалуйста, обратитесь к следующему URL, если еще не читал.
https://www.php.net/manual/en/function.openssl-pkey-get-private.php
Чтобы сузить проблему, используйте тот же каталог для вашего файла php и файла ключей и попробуйте этот рабочий код.
Рабочий код
$keyfile="file://".__DIR__.DIRECTORY_SEPARATOR."key.p8"; //absolute path
$key = openssl_pkey_get_private($keyfile);
if ($key === false) {
var_dump(openssl_error_string());
}else{
var_dump($key);
}
Следующее может быть проблемой.
- Дорожка
Следующие стили пути должны работать.
$keyfile="file:///home/john/php/key.p8"; // unix absoulute path
$keyfile="file://C:\\users\\john\\php\\key.p8"; // windows absoulute path
$keyfile="file://".__DIR__.DIRECTORY_SEPARATOR."key.p8"; //absoulute path for unix, windows
$keyfile="file://key.p8"; // relative path, unix, windows, (php,key files in same directory)
$key = openssl_pkey_get_private($keyfile);
Если путь не существует, ошибка будет
"ошибка:02001002: системная библиотека:fopen: нет такого файла или каталога"
Веб-среда
Проверьте свой веб-root и права доступа пользователя к папке и файлу ключа.
Чтобы уменьшить количество проблем, протестируйте его на встроенном веб-сервере php, а не на WAMP.
>php -S localhost:80
- Поврежденный ключевой файл
сохраняются как определенный тип, который включает пробелы. Это может произойти ошибка, как в следующем.
"ошибка:0906D06C: процедуры PEM:PEM_read_bio: нет начальной строки"
in my case, key file was saved as UTF-8 with BOM(whitespaces)
Ключевой файл отладки 1 - ЧИТАТЬ ИЗ ПЕРЕМЕННЫХ
Этот код должен работать. Я получил ключевой файл от http://micmap.org/php-by-example/en/function/openssl_pkey_get_private
Пожалуйста, замените $str на ваш.
$str = <<<EOF
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA0llCeBjy18RylTdBih9GMUSZIC3GzeN0vQ9W8E3nwy2jdeUn
H3GBXWpMo3F43V68zM2Qz5epRNmlLSkY/PJUfJIC8Yc1VEokT52q87hH/XJ5eS8h
eZnjuSlPAGi8oZ3ImVbruzV7XmlD+QsCSxJW7tBv0dqJ71e1gAAisCXK2m7iyf/u
l6rT0Zz0ptYH4IZfwc/hQ9JcMg69uM+3bb4oBFsixMmEQwxKZsXk3YmO/YRjRbay
+6+79bSV/frW+lWhknyGSIJp2CJArYcOdbK1bXx1dRWpbNSExo7dWwuPC0Y7a5AE
eoZofieQPPBhXlp1hPgLYGat71pDqBjKLvF5GwIDAQABAoIBACPItYsSy3UzYT7L
OKYTrfBBuD8GKpTqBfkHvAWDa1MD15P92Mr7l0NaCxGfAy29qSa6LdFy/oPM9tGY
9TxKyV6rxD5sfwEI3+Z/bw6pIe4W5F1eTDaQnHHqehsatkRUQET9yXp+na8w/zRF
0C0PQKS95tfvcpm59RGCdGQ8+aZw+cIy/xez75W8IS/hagMxe7xYPjpkOkSCCEJU
zmbVq6AyWodASV0p4H9p8I+c0vO2hJ/ELJ167w6T+2/GlZg979rlyHoTW8jK2BbG
IRGaPo+c2GANXa686tdpbkPd6oJliXwBSNolxmXShvlveBbPFAJJACzCmbXNj9kH
6/K+SWkCgYEA7FNudcTkRPV8TzKhJ1AzDjw3VcnraYhY8IlNxbk7RVHLdkoUtwk/
mImeBlEfCoz9V+S/gRgeQ+1Vb/BCbS24+bN/+IGoNRFMRcOieFt6lQUpj7a9NeSo
IEclGgUiU7QR3xH73SB4GC3rgSPeHJhJZC5EJq5TzYjXTPGPpBD3zicCgYEA49wz
zfMDYIH8h4L65r/eJYIbLwpvgktgaYvhijO3qfZSWW+Y19jCBn55f65YOhPGQBHA
my0f+tVxFNZ/OupbrAIIzogxlCIYHNBawDhoHN/sB3/lSBAjifySNLyRlA62oA0w
wXvXVLVWMa3aXim3c9AlnLF1fHwcvwpOKSfdye0CgYBb1mBKq+T5V1yjek1d9bCh
i40FbZ5qOG43q2Ppvn3mBk9G/KroJlPsdy5NziB9/SRGj8JL7I92Xjihc4Cc5PPJ
NZQ5gklXtg0p30i39PTCDGuGScFlvCIJyRwF7JDWblezlE2INSH2Y4HtgX7DJfr/
T2t0jLJMYS0p3YWwgFeMaQKBgHUIe/8y6zAdc5QynSX5tGL1gXrW1FFK39k2RICU
cag1YTSYkhuDNJzbRxJifORPlcsAkzngooVWLb+zMCQVjUI6xUU3RKe+Hz5lccc6
8ZarGHL9qMkrqOVNudamZ+tw5zIrtDgcoIvcm8nmbrtgl94/MaJar2ph4O3qoByZ
Ylw9AoGAIdS79s0VKkj4VVXqK47ZcI7jGL4V4C8ujU8YcMNV88xwCoDg9ZIFprWA
P5p/cnvj6aHnqL58XiH0+bE0Lt3J+U6N6JelQQevgBHooMFh4FpDXcVda7xB3rK3
woqbi8fNhr827H2maxIZPtVG95/mvR4k5z1Jrdnr34ZUmtC6U5Q=
-----END RSA PRIVATE KEY-----
EOF;
$key = openssl_pkey_get_private($str);
if ($key === false) {
var_dump(openssl_error_string());
}else{
var_dump($key);
}
ВЫХОД
ресурс (4) типа (ключ OpenSSL)
Файл ключа отладки 2 - ЧИТАТЬ ИЗ ФАЙЛА
скопируйте строки ключей ($str) в файл ключей, например, "key.p8".
$str = <<<EOF
-----BEGIN RSA PRIVATE KEY-----
...YOUR KEY STINGS HERE...
-----END RSA PRIVATE KEY-----
EOF;
$str2 = file_get_contents("key.p8");
$len1 = strlen ($str);
$len2 = strlen ($str2);
if($len1 !== $len2) echo "File has been corrupted.";
$key = openssl_pkey_get_private($str2);
if ($key === false) {
var_dump(openssl_error_string());
}else{
var_dump($key);
}
Этот сценарий можно использовать для отправки push-уведомлений в IOS с использованием сертификата.p8. Убедитесь, что местоположение сертификата правильное
<?php
$keyfile = 'AuthKey_AABBCC1234.p8'; // Your p8 Key file
$keyid = 'AABBCC1234'; // Your Key ID
$teamid = 'AB12CD34EF'; // Your Team ID (see Developer Portal)
$bundleid = 'com.company.YourApp'; // Your Bundle ID
$url = 'https://api.development.push.apple.com'; // development url, or use http://api.push.apple.com for production environment
$token = 'e2c48ed32ef9b018........'; // Device Token
$message = '{"aps":{"alert":"Hi there!","sound":"default"}}';
$key = openssl_pkey_get_private('file://'.$keyfile);
$header = ['alg'=>'ES256','kid'=>$keyid];
$claims = ['iss'=>$teamid,'iat'=>time()];
$header_encoded = base64($header);
$claims_encoded = base64($claims);
$signature = '';
openssl_sign($header_encoded . '.' . $claims_encoded, $signature, $key, 'sha256');
$jwt = $header_encoded . '.' . $claims_encoded . '.' . base64_encode($signature);
// only needed for PHP prior to 5.5.24
if (!defined('CURL_HTTP_VERSION_2_0')) {
define('CURL_HTTP_VERSION_2_0', 3);
}
$http2ch = curl_init();
curl_setopt_array($http2ch, array(
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_URL => "$url/3/device/$token",
CURLOPT_PORT => 443,
CURLOPT_HTTPHEADER => array(
"apns-topic: {$bundleid}",
"authorization: bearer $jwt"
),
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $message,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_TIMEOUT => 30,
CURLOPT_HEADER => 1
));
$result = curl_exec($http2ch);
if ($result === FALSE) {
throw new Exception("Curl failed: ".curl_error($http2ch));
}
$status = curl_getinfo($http2ch, CURLINFO_HTTP_CODE);
echo $status;
function base64($data) {
return rtrim(strtr(base64_encode(json_encode($data)), '+/', '-_'), '=');
}
?>```