IOSユーザーに通知を送信すると、一部のユーザーに対して応答ステータスコード400(BadDeviceToken)またはコード410(未登録)が返されます。
From Apple「BadDeviceToken」に関するドキュメント:
指定されたデバイストークンが不良でした。要求に有効なトークンが含まれていること、およびトークンが環境と一致することを確認してください。
「悪い」とはどういう意味ですか?私は、デバイストークンが以前に有効だったことを知っています。ユーザーは、デバイストークンを無効にするために何をしますか?
「未登録」に関するドキュメントから:
デバイストークンは、指定されたトピックに対して非アクティブです。
これは、アプリが削除されたことを意味しますか?または、この応答には他の理由があります。
APNSドキュメントの 表8-6 から引用したように、エラーには2つの原因が考えられます。
最初の場合は、多くの理由があるため、iOSアプリがアプリを起動するたびにデバイスをリモート通知に登録するようにしますリモート通知サポートの設定 で説明されているように、起動時にデバイストークンが変更されます。
2番目の場合、次のことを確認する必要があります。
幸いなことに、iOS開発者は、APNSの資格を直接変更する必要はありません。これは常に開発段階にあり、App Storeまたはエンタープライズ配布用のビルドとエクスポートを生成したときにのみ、Xcodeによって本番環境に自動的に変更されます。バックエンドに関しては、バックエンド開発者は、開発環境および実稼働環境向けにバックエンドを構成する方法を知っている必要があります。一部のフレームワークでは、isProduction
という名前のブール値を切り替える必要があります。最終的には、 APNとの通信 セクションAPNs Connections
、プッシュ通知は、環境が本番か開発かによって、異なるAPNSエンドポイントに送信されます。
BadDeviceToken
エラーは2番目のケースが原因であると想定しましょう。アプリによって登録されたデバイストークンが、バックエンドの適切に構成された開発環境と一致しないということです。まず、Xcodeプロジェクトで、.entitlements
ファイルを作成し、APS Environment
キーの値はdevelopment
です。次のようになります。
次に、アーカイブを生成した後、オーガナイザーを開き(Window
メニュー> Organizer
を使用)、アーカイブを選択して、[Export...
右側。 4つの配布方法が表示されます。
App StoreまたはEnterpriseを選択すると、後のダイアログでXcodeがAPNSエンタイトルメントを本番に変更することがわかります(赤い矢印の先端を参照)。
Ad HocまたはDevelopmentを選択した場合、aps-environmentの下のテキストはdevelopment
になり、バックエンドの設定と一致するはずです。
ステータスコード '400':間違った証明書で通知を送信しようとすると、このエラーが発生します。実稼働環境には実稼働証明書を使用してください。あなたが悪い構成を使用しているので、それは悪いです。
ステータスコード '410':はい、このコードでアプリが削除されたことを理解できます。このステータスコードを取得したアプリでは、dbからこのトークンを削除します。他のシナリオは、ユーザーがトークンを変更する可能性のあるアプリを再インストールしたことです。したがって、このトークンを削除することをお勧めします。
エラーコード404:BadDeviceトークン
考えられる理由:
注: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";
}
?>
node-apn
を使用している場合。 APNはサンドボックスモードまたは本番モードのいずれかで動作するトークンを使用するようになったため、ここでの答えはかなりわかりにくいものでした。また、通知を送信するための1回限りのスクリプトを作成することが本番環境で機能したため、私も混乱していました。
私のサービスがprocess.env.NODE_ENV === 'production'
を取得していないのではないかと疑い始めるようになりました。そこで、それをスタートアップログメッセージに追加し、サービスランナーforever
が環境変数を取得していないことを確認しました。このため、サンドボックスURLで本番デバイスIDを試行していました。