web-dev-qa-db-fra.com

Comment envoyer des messages APN à l'aide de la clé d'authentification APN et des outils CLI standard?

Apple a récemment ajouté une nouvelle méthode d’authentification à APNS ( Clé d’authentification de notification Apple Push (Sandbox & Production) ).

enter image description here

La clé téléchargée est un .p8 fichier avec une clé privée:

$ cat APNSAuthKey_3HHEB343FX.p8
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBH...Already.Revoked...lHEjCX1v51W
-----END PRIVATE KEY-----

J'utilise des messages APN en utilisant l'ancienne méthode - en les ajoutant au trousseau, en demandant un certificat et en utilisant OpenSSL pour envoyer des messages à gateway.production.Push.Apple.com:2195.

Comment puis-je envoyer des notifications Push à l'aide des outils CLI Linux standard (OpenSSL, Python etc.) à l'aide du nouveau format?

37
Adam Matan

Si vous avez curl avec le support HTTP/2 et openssl avec le support ECDSA installé sur votre ordinateur, vous pouvez utiliser le script suivant pour tester les notifications Push à l'aide d'une clé d'authentification APN:

#!/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

REMARQUE: J'utilise une légère variante de ce script pour tester sur macOS avec homebrew versions de curl et openssl: http://thrysoee.dk/apns/

55
Jess Thrysoee

Vous pouvez envoyer une notification push par NODE JS en utilisant Apple Clé d'authentification de la notification push (bac à sable et production). Apple a fourni un tutoriel en ce lien

Ce didacticiel présente toutes les étapes de la création de la clé Apple Authentification de la notification Push et de la configuration d’un serveur local pour l’exécution Node code JS permettant l’envoi de la notification Push. Vous pouvez exécuter cette tâche. le code sur votre ordinateur local et testez la notification Push.

J'espère que cela aidera.

12
Teena nath Paul

Voilà dans PHP à quoi ça ressemble avec curl et HTTP/2. Ce script renvoie le code de statut 200 ok avec l'identifiant de jeton généré.

// 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);
6
Nicolas Manzini

La réponse fournie par Nicolas Manzini, bien qu'utile, ne m'a pas pleinement fonctionné. Je voulais aussi utiliser curl en ligne de commande. En particulier, la lecture du fichier .p8 posait problème. Une version modifiée:

<?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;
            }
        }
    }
}

?>
2
David