简体   繁体   English

这个 php 脚本是否仍可用于使用 APNs 发送测试推送通知? [基于证书的连接]

[英]Can this php script still be used to send test push notifications using APNs? [Certificate Based Connection]

This script used to send test push notifications to test devices before Apple made the switch to the new APNs Provider API , which I'm surprised more people aren't talking about.在 Apple 切换到新的 APNs 提供程序 API之前,此脚本用于向测试设备发送测试推送通知,令我惊讶的是,更多人没有谈论它。

Now when I run the script from the terminal typing and entering php simplepush.php , the output says现在,当我从终端键入并输入php simplepush.php运行脚本时, output 说

在此处输入图像描述

Though no message is received.虽然没有收到任何消息。

//simplepush.php

<?php

// Put your device token here (without spaces):
$deviceToken = 'EXAMPLETOKEN';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'Hello!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://api.sandbox.push.apple.com:443', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n',     strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);

Since Apple made the switch last March, I have:自从 Apple 去年 3 月做出改变以来,我有:

  1. Created a new Certificate Signing Request创建了一个新的证书签名请求
  2. Registered a new App ID注册了一个新的 App ID
  3. Established a Certificate-Based Connection to APNs 与 APNs 建立基于证书的连接
  4. Obtained a new Provider Certificate from Apple 从 Apple 获得新的提供商证书
  5. Installed the Certificate and Private Key 安装证书和私钥
  6. Established Trust with APNs 与 APN 建立信任
  7. Sent Push Notifications Using Command-Line Tools 使用命令行工具发送推送通知

And I am able to get a test notification when I follow Sending Push Notifications Using Command-Line Tools .当我遵循Sending Push Notifications Using Command-Line Tools时,我能够获得测试通知。

curl -v --header 'apns-topic: com.your.site' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Test"}}' --http2 https://api.sandbox.push.apple.com/3/device/DEVICETOKEN

在此处输入图像描述

Is it possible to still use this php script to send test push notifications since apple made the change to the new APNs Provider API?由于苹果对新的 APNs 提供程序 API 进行了更改,是否仍然可以使用此 php 脚本发送测试推送通知? I know that the Apple developer documentation mentions required header request fields but I honestly can't tell if those are to be implemented from the terminal or from directly within the script.我知道 Apple 开发人员文档中提到了必需的 header 请求字段,但老实说,我不知道这些是从终端实现还是直接在脚本中实现。

在此处输入图像描述

If your curl call works, why not convert it to PHP如果您的 curl 调用有效,为什么不将其转换为 PHP

Example:例子:

$url = "https://api.sandbox.push.apple.com/3/device/DEVICETOKEN";
$ch = curl_init($url);

$data = json_encode(["aps" => ["alert" => "Test"]]);

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // can be URL encoded string

$headers = array();
$headers[] = 'Apns-Topic: com.your.site';
$headers[] = 'Apns-Push-Type: ';
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

If you need to know how to use cert with CURL in PHP check this answer如果您需要知道如何在 PHP 中将证书与 CURL 一起使用,请查看此答案

I've just written a some code for new version APNS.我刚刚为新版本的 APNS 编写了一些代码。 For comunication we need "The 10-character Key ID you obtained from your developer account", "Team ID" and token refreshing... : "...once every 20 minutes and no less than once every 60 minutes..."对于通信,我们需要“您从开发者帐户获得的 10 字符密钥 ID”、“团队 ID”和令牌刷新...:“...每 20 分钟一次且不少于每 60 分钟一次...”

More: Apple Documentation更多: 苹果文档

When I send noticication first time, I save token to cache file to use it again..当我第一次发送通知时,我将令牌保存到缓存文件以再次使用它..

class PushNotifications {
    
                
    public function iOS($data, $devicetoken) {

              
                $tokenTMP = 'files/cert/token_apn';  //TOKEN CACHE
                $domain   = 'pl.domain.*****';
           
                
                $def = 'alert';
                
                $url = 'https://api.push.apple.com:443';
                
                if($devicetoken =='e9886c41112d766eb3513ffbcc12ed92cbcb68ecf1e42413319b115d3c3a1ebec') //My test token
                {
                   $url = 'https://api.sandbox.push.apple.com:443'; //sandbox
                   $def = 'alert';
                }
           
                

                //----------------
                //For security, APNs requires you to refresh your token regularly. Refresh your token no more than once every 20 minutes and no less than once every 60 minutes.
                
                $token = '';
                
                if(file_exists($tokenTMP))
                {
                    $fileTime = filemtime($tokenTMP);
                    $maxT     = time() - 1800; //max 30 min.
                    $min     = time() - 3600; //max 30 min.
                    
                    if(  $fileTime > $min && $fileTime < $maxT )
                    {
                        $token = file_get_contents($tokenTMP);
                       // echo 'I get last generated token..';
                    }                                       
                }                
                
                //----------------
                
                if($token == '') //Let's generate new token...
                {
                   // echo 'Generate new token...';
                    
                    //https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns
                    $assocToken        = array();
                    $assocToken['alg'] = 'ES256';       //The encryption algorithm you used to encrypt the token. APNs supports only the ES256 algorithm, so set the value of this key to ES256.
                    $assocToken['kid'] = '*******';  //The 10-character Key ID you obtained from your developer account
                    $assocToken['iss'] = '*******';  //The issuer key, the value for which is the 10-character Team ID you use for developing your company’s apps. Obtain this value from your developer account.
                    $assocToken['iat'] = time();  //The “issued at” time, whose value indicates the time at which this JSON token was generated. Specify the value as the number of seconds since Epoch, in UTC. The value must be no more than one hour from the current time.


                    $header = '{'
                            . ' "alg" : "'.$assocToken['alg'].'",'
                            . ' "kid" : "'.$assocToken['kid'].'"'
                            . '}';


                    $payload = '{'
                            . ' "iss" : "'.$assocToken['iss'].'",'
                            . ' "iat" : "'.$assocToken['iat'].'"'
                            . '}';                

                    $headerB64URL  = $this->base64url_encode($header);
                    $payloadB64URL = $this->base64url_encode($payload);               
                    $secret        = file_get_contents('files/cert/AuthKey_********.p8');

                    $signature = '';
                    openssl_sign($headerB64URL.'.'.$payloadB64URL, $signature, $secret, \OPENSSL_ALGO_SHA256);

                    $token = $headerB64URL.'.'.$payloadB64URL.'.'.$this->base64url_encode($signature);
                    
                    //save to use next time..                    
                    $fp = fopen($tokenTMP, 'w');
                    fwrite($fp, $token); 
                    fclose($fp);
                }
                               
        
                
                $apns_id = '8-4-4-5-12';
                
                
                // Create the payload body
                $encode= json_decode( $data['mdesc'],true) ;
                $message = $encode['message'];
                
        $body['aps'] = array(                        
            'sound' => 'default',   
            'alert' => array
                           (
                'title' => $data['mtitle'],
                            'body' => $message,
                            'mdesc' =>  $data['mdesc'] ?? array() 
                ),      
                        'mutable-content' => '1',
        );

        // Encode the payload as JSON
        $payloadData = json_encode($body);
                
                
                $curl = curl_init();
                curl_setopt_array($curl, array(
                CURLOPT_URL => $url . '/3/device/'.$devicetoken,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => "",
                CURLOPT_MAXREDIRS => 1,
                CURLOPT_TIMEOUT => 10,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, 
                CURLOPT_HTTPHEADER => array(
                "authorization: bearer ".$token,
              //  "apns-id: ".$apns_id, //
                "apns-push-type: $def",
                "apns-expiration: ". strtotime('+1 days ' .date('Y-m-d')),//ponawiaj przez 1 dzień..
                "apns-priority: 10",  //wyślij natychmiast..
                "apns-topic: ".$domain,
                  ),
                 CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,   
                 CURLOPT_POST => '1',   
                 CURLOPT_POSTFIELDS => $payloadData   
                 ));
                
        

                $response = curl_exec($curl);
                
                if(curl_errno($curl) == 0)
                {
                    return 'ret: '.$response;
                }else
                {
                    return 'err: '.curl_error($curl);
                }                                                                                                                   
    }
    
      
    
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM