簡體   English   中英

使用 .p8 和 PHP 發送推送

[英]Send Push with .p8 and PHP

我需要使用 .p8 文件通過 PHP 腳本發送推送通知,並在此處提出的類似問題中找到以下代碼。

<?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 在測試階段,我使用同一文件夾中的腳本和文件來避免任何路徑問題。

哪里出錯了?

如果還沒有閱讀,請參考下一個 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);
}

以下可能是一個問題。

  1. 小路

以下路徑樣式應該有效。

$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:沒有那個文件或目錄”

  1. 網絡環境

    檢查您的 Web 根目錄和 Web 用戶對文件夾和密鑰文件的訪問權限。

    為了減少問題,請在 php 內置 Web 服務器環境而不是 WAMP 環境中測試它。

>php -S localhost:80
  1. 損壞的密鑰文件

保存為包含空格的特定類型。 這可能會發生如下錯誤。

“錯誤: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);
}

此腳本可用於使用 .p8 證書向 IOS 發送推送。 確保證書位置正確


<?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)), '+/', '-_'), '=');
      }

    ?>```

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM