web-dev-qa-db-ja.com

APNs応答BadDeviceTokenまたはUnregisteredを取得する可能性のある理由は何ですか?

IOSユーザーに通知を送信すると、一部のユーザーに対して応答ステータスコード400(BadDeviceToken)またはコード410(未登録)が返されます。

From Apple「BadDeviceToken」に関するドキュメント:

指定されたデバイストークンが不良でした。要求に有効なトークンが含まれていること、およびトークンが環境と一致することを確認してください。

「悪い」とはどういう意味ですか?私は、デバイストークンが以前に有効だったことを知っています。ユーザーは、デバイストークンを無効にするために何をしますか?

「未登録」に関するドキュメントから:

デバイストークンは、指定されたトピックに対して非アクティブです。

これは、アプリが削除されたことを意味しますか?または、この応答には他の理由があります。

17
Shai Givati

APNSドキュメントの 表8-6 から引用したように、エラーには2つの原因が考えられます。

  1. デバイストークンが無効であること
  2. デバイストークンが環境と一致しないこと

最初の場合は、多くの理由があるため、iOSアプリがアプリを起動するたびにデバイスをリモート通知に登録するようにしますリモート通知サポートの設定 で説明されているように、起動時にデバイストークンが変更されます。

2番目の場合、次のことを確認する必要があります。

  • アプリビルドがdevelopmentAPNSで署名されている場合、バックエンドはdevelopment構成を使用します資格、および
  • アプリビルドがproductionAPNSで署名されている場合、バックエンドはproduction構成を使用します資格。

幸いなことに、iOS開発者は、APNSの資格を直接変更する必要はありません。これは常に開発段階にあり、App Storeまたはエンタープライズ配布用のビルドとエクスポートを生成したときにのみ、Xcodeによって本番環境に自動的に変更されます。バックエンドに関しては、バックエンド開発者は、開発環境および実稼働環境向けにバックエンドを構成する方法を知っている必要があります。一部のフレームワークでは、isProductionという名前のブール値を切り替える必要があります。最終的には、 APNとの通信 セクションAPNs Connections、プッシュ通知は、環境が本番か開発かによって、異なるAPNSエンドポイントに送信されます。

BadDeviceTokenエラーは2番目のケースが原因であると想定しましょう。アプリによって登録されたデバイストークンが、バックエンドの適切に構成された開発環境と一致しないということです。まず、Xcodeプロジェクトで、.entitlementsファイルを作成し、APS Environmentキーの値はdevelopmentです。次のようになります。

enter image description here

次に、アーカイブを生成した後、オーガナイザーを開き(Windowメニュー> Organizerを使用)、アーカイブを選択して、[Export...右側。 4つの配布方法が表示されます。

enter image description here

App StoreまたはEnterpriseを選択すると、後のダイアログでXcodeがAPNSエンタイトルメントを本番に変更することがわかります(赤い矢印の先端を参照)。

enter image description here

Ad HocまたはDevelopmentを選択した場合、aps-environmentの下のテキストはdevelopmentになり、バックエンドの設定と一致するはずです。

27
Matthew Quiros

ステータスコード '400':間違った証明書で通知を送信しようとすると、このエラーが発生します。実稼働環境には実稼働証明書を使用してください。あなたが悪い構成を使用しているので、それは悪いです。

ステータスコード '410':はい、このコードでアプリが削除されたことを理解できます。このステータスコードを取得したアプリでは、dbからこのトークンを削除します。他のシナリオは、ユーザーがトークンを変更する可能性のあるアプリを再インストールしたことです。したがって、このトークンを削除することをお勧めします。

6
Suhaib Affan

エラーコード404:BadDeviceトークン

考えられる理由:

  1. .pem証明書が間違っている可能性があります。
  2. BundleIdが間違っている可能性があります。
  3. デバイスIDが間違っている可能性があります。

注:voipプッシュ通知を送信するために、バンドルIDに.voipを追加します(例:bundleid.voip)

Voipプッシュ通知の実行可能な例は次のとおりです。

<?php
$token = $_REQUEST['tok'];
if (!defined('CURL_HTTP_VERSION_2_0')) {
  define('CURL_HTTP_VERSION_2_0', 3);
}
// open connection 
$http2ch = curl_init();
curl_setopt($http2ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
// send Push
$Apple_cert = 'certificate_name.pem';
$message = '{"aps":{"action":"message","title":"your_title","body":"your_message_body"}}';
$http2_server = 'https://api.development.Push.Apple.com'; // or 'api.Push.Apple.com' if production
$app_bundle_id = 'your bundle id';
$status = sendHTTP2Push($http2ch, $http2_server, $Apple_cert, $app_bundle_id, $message, $token);
echo $status;
// close connection
curl_close($http2ch);
function sendHTTP2Push($http2ch, $http2_server, $Apple_cert, $app_bundle_id, $message, $token) 
{
    // url (endpoint)
    $url = "{$http2_server}/3/device/{$token}";
    $cert = realpath($Apple_cert);
    // headers
    $headers = array(
        "apns-topic: {$app_bundle_id}",
        "User-Agent: My Sender"
    );
    curl_setopt_array($http2ch, array(
        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_SSLCERT => $cert,
        CURLOPT_HEADER => 1
    ));
    $result = curl_exec($http2ch);
    if ($result === FALSE) {
      throw new Exception("Curl failed: " .  curl_error($http2ch));
    }
    // get response
    $status = curl_getinfo($http2ch, CURLINFO_HTTP_CODE);
    if($status=="200")
    echo "SENT|NA";
    else
    echo "FAILED|$status";
}
?> 
1

node-apnを使用している場合。 APNはサンドボックスモードまたは本番モードのいずれかで動作するトークンを使用するようになったため、ここでの答えはかなりわかりにくいものでした。また、通知を送信するための1回限りのスクリプトを作成することが本番環境で機能したため、私も混乱していました。

私のサービスがprocess.env.NODE_ENV === 'production'を取得していないのではないかと疑い始めるようになりました。そこで、それをスタートアップログメッセージに追加し、サービスランナーforeverが環境変数を取得していないことを確認しました。このため、サンドボックスURLで本番デバイスIDを試行していました。

0
Kyle Parisi