获取APNs响应BadDeviceToken或Unregistered的可能原因是什么?

问题描述 投票:11回答:3

向iOS用户发送通知时,对于其中一些用户,我会收到响应状态码400(BadDeviceToken)或代码410(未注册)。

从Apple关于“BadDeviceToken”的文档:

指定的设备令牌很糟糕。验证请求是否包含有效令牌以及令牌是否与环境匹配。

“坏”是什么意思?我知道设备令牌在某些时候是有效的。用户如何使其设备令牌变坏?

从关于“未注册”的文档:

设备令牌对于指定的主题处于非活动状态。

这是否意味着应用程序已被删除?或者这种反应可能还有其他原因。

ios http-headers apple-push-notifications http-status-code-400 http-status-code-410
3个回答
21
投票

正如您在APNS文档中引用Table 8-6一样,错误有两种可能的原因:

  1. 设备令牌无效
  2. 设备令牌与环境不匹配

如果是第一种情况,请确保iOS应用程序每次启动应用程序时都会注册设备以进行远程通知,因为有很多原因导致设备令牌在启动时发生变化,如Configuring Remote Notification Support中所述。

如果是第二种情况,您需要确保:

  • 如果您的应用程序版本使用开发APNS权利进行签名,则后端将使用开发配置
  • 如果您的应用程序版本使用生产APNS权利签名,则后端将使用生产配置。

幸运的是,作为iOS开发人员,您不需要自己直接更改APNS权利。它始终处于开发阶段,只有在为App Store或企业分发生成构建和导出时,Xcode才会自动将其更改为生产。至于后端,您的后端开发人员应该知道如何为开发和生产环境配置后端。对于某些框架,这是一个切换一些名为isProduction的布尔值的问题。最终,根据Communicating with APNsAPNs Connections部分,推送通知将发送到不同的APNS端点,具体取决于环境是生产还是开发。

让我们假装BadDeviceToken错误是由第二种情况引起的 - 应用程序注册的设备令牌与后端正确配置的开发环境不匹配。首先,在您的Xcode项目中,检查您的.entitlements文件并验证APS Environment密钥的值是development。它应该如下所示:

enter image description here

接下来,在生成存档后,打开管理器(通过Window菜单> Organizer),选择存档,然后单击右侧的Export...。您应该看到四种分发方法:

enter image description here

如果您选择App Store或Enterprise,您将在后面的对话框中看到Xcode将APNS权利更改为生产(请参阅红色箭头的提示):

enter image description here

如果选择Ad Hoc或Development,则aps-environment下的文本将为development,然后应与后端的配置匹配。


5
投票

状态代码“400”:当您尝试使用错误的证书发送通知时,会出现此错误。确保将生产证书用于生产环境。这很糟糕,因为您使用了错误的配置。

状态代码'410':是的,使用此代码我们可以理解应用已删除。在我们的app中获取此状态代码时,我们会从db中删除此令牌。另一种情况可能是用户重新安装了可能会更改其令牌的应用程序。所以你删除这个令牌会更好。


1
投票

错误代码404:BadDevice令牌

可能的原因:

  1. 您的.pem证书可能有误。
  2. 你的BundleId可能是错的。
  3. 您的设备ID可能有误。

注意:使用您的bundleid附加.voip以发送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";
}
?> 
© www.soinside.com 2019 - 2024. All rights reserved.