When sending notifications to iOS users, for some of them I get response status code 400 (BadDeviceToken) or code 410 (Unregistered).
From Apple documentation about \"Ba
Error code 404: BadDevice token
Posssible reasons:
Note: Append .voip with your bundleid for sending voip push notification(exmple: bundleid.voip)
Here is an workable example of voip push notification :
<?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";
}
?>
Feedback is no longer immediate with 410 notifications. Apple intentionally has done this due to privacy concerns. It may take up to a week now. See https://developer.ibm.com/customer-engagement/2019/05/01/apns-feedback-service-change/
If using node-apn
. I found the answers here rather confusing as APN has moved to using tokens which work for either sandbox or production modes. I was also confused because writing a 1 off script to send a notification worked in production.
It wasn't until I started to suspect that my my service wasn't getting process.env.NODE_ENV === 'production'
. So I added that to my startup log message and low and behold my service runner forever
was not getting any environment variables. Because of this, it was trying production device ids on the sandbox url.
I was sending a "development" device token to the "production" apple push servers. I fixed it by sending requests to api.development.push.apple.com
instead of api.push.apple.com
As you've quoted from Table 8-6 in the APNS documentation, there are two possible causes for the error:
If it is the first case, make sure that the iOS app registers the device for remote notifications every single time that the app is launched because there are many reasons for the device token to change across launches, as outlined in Configuring Remote Notification Support.
If it is the second case, you need to be sure that:
Luckily, as the iOS developer, you don't need to directly change the APNS entitlements yourself. It is always in development, and is only automatically changed by Xcode to production when you generate the build and export for App Store or enterprise distribution. As for the backend, your backend developer should know how to configure the backend for development and production environments. For some frameworks, it is a matter of toggling some boolean named isProduction
. Ultimately, according to Communicating with APNs under the section APNs Connections
, push notifications are sent to different APNS endpoints depending on whether the environment is production or development.
Let's pretend that the BadDeviceToken
error is due to the second case--that the device token registered by the app does not match the backend's properly configured development environment. First, in your Xcode project, check your .entitlements
file and verify that the APS Environment
key's value is development
. It should look like this:
Next, after you generate an archive, open the Organizer (via the Window
menu > Organizer
), select the archive, and click on Export...
at the right. You should see four methods of distribution:
If you select App Store or Enterprise, you will see in the later dialogs that Xcode changes the APNS entitlements to production (see tip of red arrow):
If you select Ad Hoc or Development, the text under aps-environment will be development
, which should then match the backend's configurations.
Status code '400' : You get this error when you try to send the notification with a wrong certificate. Make sure that you use production certificate for production environment. It is bad because you are using bad configurations.
Status code '410' : Yes with this code we can understand that App has deleted. In our app when we get this status code we delete this token from db. The other scenario could be that user has reinstalled the app which could change his token. So its better you remove this token.