How to send APNs push messages using APNs Auth Key and standard CLI tools?

后端 未结 4 635
北荒
北荒 2021-01-30 10:29

Apple recently added a new authentication method to APNS ( Apple Push Notification Authentication Key (Sandbox & Production)).

The downloaded key is a

相关标签:
4条回答
  • 2021-01-30 11:04

    You can send push notification by NODE JS using Apple Push Notification Authentication Key (Sandbox & Production). There is a tutorial provided by Elad Nava in this link

    This tutorial has all steps of creating the Apple Push Notification Authentication Key and setting up a local server to run Node JS code for sending push notification. You can run the code in your local machine and test the push notification.

    Hope this will help.

    0 讨论(0)
  • 2021-01-30 11:07

    The answer provided by Nicolas Manzini, while helpful, did not fully work for me. I also wanted to use command line curl. In particular, reading in the .p8 file was causing some problems. A modified version:

    <?php
    
    $teamid = 'YOURTEAMID';
    $keyid = 'A464FN6T93';     // in the name of the file downloaded from Apple Certs
    
    // since it is a universal key, I wanted this in a location accessible to several accounts
    $keyFile = '/path/to/file/AuthKey_A464FN6T93.p8';
    
    $privateKey = openssl_pkey_get_private('file://' . $keyFile);
    
    if (! $privateKey) {
        die('could not find: ' . $keyFile);
    }
    
    $header = ['alg' => 'ES256', 'kid' => $keyid];
    $header = base64_encode(json_encode($header));
    
    $claim = ['iss' => $teamid, 'iat' => time()];
    $claim = base64_encode(json_encode($claim));
    
    $tok = $header . '.' . $claim;
    
    // pass in empty $signature, 2nd line below fills it
    $signature = '';
    $result = openssl_sign($tok, $signature, $privateKey, OPENSSL_ALGO_SHA256);      //  'sha256'
    if (! $result) {
        die('unable to create signature');
    }
    
    $sign = base64_encode($signature);
    
    openssl_free_key($privateKey);
    
    $jwt = $tok . '.' . $sign;
    
    foreach($tokens as $token) {
        $cmd = '\
        /usr/local/bin/curl -v \
        -d \'{"aps":{"alert":{"title":"Notification Title","body":"You are being notified!"},"sound":"default"}}\' \
        -H "apns-topic: com.app.bundle.id" \
        -H "authorization: bearer ' . $jwt . '" \
        -H "content-type:application/json" \
        --http2 \
        https://api.push.apple.com/3/device/' . $token . ' 2>&1';    // ending w/ 2>&1, sends output to $output
    
        exec($cmd, $output, $return);
    
        if ($return != 0) {
            // be notified of error
        }
        else {
            foreach($output as $line) {
                if (strpos($line, 'apns-id')) {
                    $apns = $line;
                }
            }
        }
    }
    
    ?>
    
    0 讨论(0)
  • 2021-01-30 11:09

    If you have curl with HTTP/2 support and openssl with ECDSA support installed on your machine, you can use the following script to test push notifications using an APNs Auth Key:

    #!/bin/bash
    
    deviceToken=b27371497b85611baf9052b4ccfb9641ab7fea1d01c91732149c99cc3ed9342f
    
    authKey="./APNSAuthKey_ABC1234DEF.p8"
    authKeyId=ABC1234DEF
    teamId=TEAM123456
    bundleId=com.example.myapp
    endpoint=https://api.development.push.apple.com
    
    read -r -d '' payload <<-'EOF'
    {
       "aps": {
          "badge": 2,
          "category": "mycategory",
          "alert": {
             "title": "my title",
             "subtitle": "my subtitle",
             "body": "my body text message"
          }
       },
       "custom": {
          "mykey": "myvalue"
       }
    }
    EOF
    
    # --------------------------------------------------------------------------
    
    base64() {
       openssl base64 -e -A | tr -- '+/' '-_' | tr -d =
    }
    
    sign() {
       printf "$1" | openssl dgst -binary -sha256 -sign "$authKey" | base64
    }
    
    time=$(date +%s)
    header=$(printf '{ "alg": "ES256", "kid": "%s" }' "$authKeyId" | base64)
    claims=$(printf '{ "iss": "%s", "iat": %d }' "$teamId" "$time" | base64)
    jwt="$header.$claims.$(sign $header.$claims)"
    
    curl --verbose \
       --header "content-type: application/json" \
       --header "authorization: bearer $jwt" \
       --header "apns-topic: $bundleId" \
       --data "$payload" \
       $endpoint/3/device/$deviceToken
    

    NOTE: I use a slight variation of this script for testing on macOS with homebrew versions of curl and openssl: http://thrysoee.dk/apns/

    0 讨论(0)
  • 2021-01-30 11:24

    Voilà in PHP what it looks like with curl and HTTP/2. This script return the 200 ok status code along with the generated token id.

    // THE FINAL SCRIPT WITHOUT DEPENDENCIES!!! ...except curl with http2
    $device_token = "a0abd886etc...";
    //echo $key;
    $kid      = "YOURKEYID";
    $teamId   = "YOURTEAMID";
    $app_bundle_id = "your.app.bundle";
    $base_url = "https://api.development.push.apple.com";
    
    $header = ["alg" => "ES256", "kid" => $kid];
    $header = base64_encode(json_encode($header));
    
    $claim = ["iss" => $teamId, "iat" => time()];
    $claim = base64_encode(json_encode($claim));
    
    $token = $header.".".$claim;
    // key in same folder as the script
    $filename = "KeyFromApple.p8";
    $pkey     = openssl_pkey_get_private("file://{$filename}");
    $signature;
    openssl_sign($token, $signature, $pkey, 'sha256');
    $sign = base64_encode($signature);
    
    $jws = $token.".".$sign;
    
    $message = '{"aps":{"alert":"You are welcome.","sound":"default"}}';
    
    function sendHTTP2Push($curl, $base_url, $app_bundle_id, $message, $device_token, $jws) {
    
        $url = "{$base_url}/3/device/{$device_token}";
        // headers
        $headers = array(
            "apns-topic: {$app_bundle_id}",
            'Authorization: bearer ' . $jws
        );
        // other curl options
        curl_setopt_array($curl, array(
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
            CURLOPT_URL => $url,
            CURLOPT_PORT => 443,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POST => TRUE,
            CURLOPT_POSTFIELDS => $message,
            CURLOPT_RETURNTRANSFER => TRUE,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => FALSE,
            CURLOPT_HEADER => 1
        ));
        // go...
        $result = curl_exec($curl);
        if ($result === FALSE) {
            throw new Exception("Curl failed: " .  curl_error($curl));
        }
        print_r($result."\n");
        // get response
        $status = curl_getinfo($curl);
        return $status;
    }
    // open connection
    $curl = curl_init();
    sendHTTP2Push($curl, $base_url, $app_bundle_id, $message, $device_token, $jws);
    
    0 讨论(0)
提交回复
热议问题