慢吞云雾缓吐愁 发表于 前天 00:07

PHP对接IOS原生推送APNS通知

此方法利用的是JWT令牌模式,2024-05-08亲测可用
要求:服务器必须支持http2或者发送请求的插件支持(不支持或者不懂自行百度即可)
自行更换keyId和teamId
本代码示例用到了redis(APNS的jwt有效期规定不能凌驾1小时,需要及时更新),如不需要或者利用别的缓存请自行删除更换
ios推送文档地点(英文):文档地点
注意事项:一定要保存好.p8文件(苹果那边只让下载一次,丢了就要重新天生)
注意事项:一定要保存好.p8文件(苹果那边只让下载一次,丢了就要重新天生)
注意事项:一定要保存好.p8文件(苹果那边只让下载一次,丢了就要重新天生)
PS:其他语音可自行复制代码,让AI转换然后调试即可
不废话直接上代码:
<?php
/**
* @desc
* @datatime 2024/5/6 11:16
*/

namespace app\wtx_app\controller\app_push;

use redis\RedisDb;
use think\Controller;

class TestPush extends Controller
{
    protected static $cacheKey= 'jwt-cache-key';
    protected static $cacheTime = 1800;
    protected static $keyId= '10位数的keyId';//keyId
    protected static $teamId = '团队ID';//团队ID
    public function testPush(){
      $deviceToken = '';//推送给谁给
      //方式1
      $payload = [
            'aps'=>[
                'alert'=>[
                  'title'    =>'消息提醒标题',
                  'subtitle' =>'字幕',
                  'body'   =>'具体话术',
                ],
                'badge'=>1//角标展示数量
            ],
            'ziDingYi1'=>112,//自定义参数1
            'ziDingYi2'=>['type'=>'ce'],//自定义参数2
      ];
      //方式2
      $payload = [
            'aps'=>[
                'alert'=>'具体话术',
                'badge'=>1,
            ],
            'ziDingYi1'=>112,//自定义参数1
            'ziDingYi2'=>['type'=>'ce'],//自定义参数2
      ];
      $payloadJson = json_encode($payload);

      //推送地址【沙箱环境:https://api.sandbox.push.apple.com:443正式环境:https://api.push.apple.com:443】
      $url = \think\facade\Env::get('ios_push_token_url','https://api.push.apple.com:443')."/3/device/".$deviceToken;

      //通知类型或者内容一致的话可以设置此值为固定(可以不传,IOS会随机)
      $collapseId = md5('push-ios');
      $headers = array(
            'Authorization: bearer '.$this->getJwt(),//jwt的token令牌
            'Content-Type: application/json',
            'apns-push-type: alert',//推送类型
            'apns-topic: app.xcxapp',//推送给那个app(包名)
            'apns-priority: 10',//通知重要程度(1-10,值越高越重要)
            'apns-expiration: 0',
            'apns-collapse-id: '.$collapseId,
      );
      $ch = curl_init($url);
      curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);//这里很关键,以http2发送请求
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取响应内容
      curl_setopt($ch, CURLOPT_POST, true); // 表示这是一个POST请求
      curl_setopt($ch, CURLOPT_POSTFIELDS, $payloadJson);
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($ch, CURLOPT_HEADER, true);//获取HEADERS响应头否则就获取不到apns的响应信息(apns-id和apns-unique-id)
      $response= curl_exec($ch);
      $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
      curl_close($ch);
      echo "<pre>";
      // Check the response
      if ($http_code == 200) {
            // 分割响应头字符串为行
            $headerLines = explode("\n", $response);
            // 初始化变量来存储apns-id和apns-unique-id
            $apnsId       = '';
            $apnsUniqueId = '';

            // 遍历每行
            foreach ($headerLines as $line) {
                // 检查行是否包含apns-id或apns-unique-id
                if (strpos($line, 'apns-id:') !== false) {
                  // 提取apns-id
                  $apnsId = trim(str_replace('apns-id:', '', $line));
                }
                //apns-unique-id仅开发环境会返回
                if (strpos($line, 'apns-unique-id:') !== false) {
                  // 提取apns-unique-id
                  $apnsUniqueId = trim(str_replace('apns-unique-id:', '', $line));
                }
            }

            // 输出结果
            echo "apns-id: " . $apnsId . "\napns-unique-id: " . $apnsUniqueId;
            echo "<br>";
            echo 'SUCCESS';
      } else {
            echo 'ERROR_CODE: ' . $http_code;
      }
    }
    private function getJwt(){
      $redis    = RedisDb::getRedis();
      if($redis->exists(self::$cacheKey)){
            return $redis->get(self::$cacheKey);
      }
      //p8文件地址
      $pkeyFile = '.p8'; //p8证书文件,我在这里填的绝对地址

      // token过期时间
      $expires = time() + self::$cacheTime;

      // Generate the JWT header
      $header = array(
            'alg' => 'ES256',
            'kid' => self::$keyId
      );
      $jwtHeader = base64_encode(json_encode($header));

      // Generate the JWT payload
      $payload = array(
            'iss' => self::$teamId,
            'iat' => time(),
            'exp' => $expires,
            'aud' => 'https://appleid.apple.com',
      );
      $jwtPayload = base64_encode(json_encode($payload));

      //载入证书文件
      $pkeyContents = file_get_contents($pkeyFile);
      $pkey = openssl_get_privatekey($pkeyContents);

      //JWT 签名
      $signature = '';
      openssl_sign($jwtHeader . '.' . $jwtPayload, $signature, $pkey, 'sha256');
      $jwtSignature = base64_encode($signature);

      // Generate the final JWT
      $jwt = $jwtHeader . '.' . $jwtPayload . '.' . $jwtSignature;

      // Print the JWT
      $redis->set(self::$cacheKey, $jwt, self::$cacheTime);
      return $jwt;
    }
}

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: PHP对接IOS原生推送APNS通知