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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42511476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:57:10  来源:igfitidea点击:

What are the possible reasons to get APNs responses BadDeviceToken or Unregistered?

ioshttp-headersapple-push-notificationshttp-status-code-400http-status-code-410

提问by Shai Givati

When sending notifications to iOS users, for some of them I get response status code 400 (BadDeviceToken) or code 410 (Unregistered).

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

From Apple documentation about "BadDeviceToken":

来自关于“BadDeviceToken”的 Apple 文档:

The specified device token was bad. Verify that the request contains a valid token and that the token matches the environment.

指定的设备令牌错误。验证请求是否包含有效令牌并且令牌与环境匹配。

What is the meaning of "bad"? I know for a fact that the device token was valid at some earlier time. What does a user do to make its device token bad?

“坏”是什么意思?我知道设备令牌在更早的时间是有效的。用户如何做才能使其设备令牌变坏?

From documentation about "Unregistered":

来自关于“未注册”的文档:

The device token is inactive for the specified topic.

设备令牌对于指定主题无效。

Does this necceserally mean that the app has been deleted? Or there can be some other reasons for this response.

这是否意味着该应用程序已被删除?或者,此响应可能有其他一些原因。

回答by Matthew Quiros

As you've quoted from Table 8-6in the APNS documentation, there are two possible causes for the error:

正如您从APNS 文档中的表 8-6中引用的那样,错误有两个可能的原因:

  1. That the device token is invalid
  2. That the device token does not match the environment
  1. 设备令牌无效
  2. 设备令牌与环境不匹配

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 launchedbecause there are many reasons for the device token to change across launches, as outlined in Configuring Remote Notification Support.

如果是第一种情况,请确保 iOS 应用程序在每次启动应用程序时都为远程通知注册设备,因为设备令牌在启动时发生变化的原因有很多,如配置远程通知支持中所述

If it is the second case, you need to be sure that:

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

  • The backend uses developmentconfigurations if your app build was signed with developmentAPNS entitlements, and
  • The backend uses productionconfigurations if your app build was signed with productionAPNS entitlements.
  • 如果您的应用构建已使用开发APNS 权利进行签名,则后端使用开发配置,并且
  • 如果您的应用程序构建使用生产APNS 权利签名,则后端使用生产配置。

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 APNsunder the section APNs Connections, push notifications are sent to different APNS endpoints depending on whether the environment is production or development.

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

Let's pretend that the BadDeviceTokenerror 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 .entitlementsfile and verify that the APS Environmentkey's value is development. It should look like this:

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

enter image description here

在此处输入图片说明

Next, after you generate an archive, open the Organizer (via the Windowmenu > Organizer), select the archive, and click on Export...at the right. You should see four methods of distribution:

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

enter image description here

在此处输入图片说明

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):

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

enter image description here

在此处输入图片说明

If you select Ad Hoc or Development, the text under aps-environmentwill be development, which should then match the backend's configurations.

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

回答by Suhaib Affan

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.

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

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.

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

回答by Saiful Islam Sajib

Error code 404: BadDevice token

错误代码 404:BadDevice 令牌

Posssible reasons:

可能的原因:

  1. Your .pem certificate may be wrong.
  2. Your BundleId may be wrong.
  3. Your Device id may be wrong.
  1. 您的 .pem 证书可能有误。
  2. 您的 BundleId 可能有误。
  3. 您的设备 ID 可能有误。

Note: Append .voip with your bundleid for sending voip push notification(exmple: bundleid.voip)

注意:在 .voip 后附加您的 bundleid 以发送 voip 推送通知(例如:bundleid.voip)

Here is an workable example of voip push notification :

这是一个可行的 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";
}
?> 

回答by Kyle Parisi

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.

如果使用node-apn. 我发现这里的答案相当令人困惑,因为 APN 已转向使用适用于沙盒或生产模式的令牌。我也很困惑,因为编写 1 off 脚本来发送通知在生产中起作用。

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 foreverwas not getting any environment variables. Because of this, it was trying production device ids on the sandbox url.

直到我开始怀疑我的服务没有得到process.env.NODE_ENV === 'production'. 所以我将它添加到我的启动日志消息中,然后发现我的服务运行器forever没有获得任何环境变量。因此,它正在沙箱 url 上尝试生产设备 ID。

回答by Rik

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/

410 通知不再立即反馈。出于隐私考虑,Apple 故意这样做。现在最多可能需要一周时间。请参阅https://developer.ibm.com/customer-engagement/2019/05/01/apns-feedback-service-change/

回答by raphaelrk

I was sending a "development" device token to the "production" apple push servers. I fixed it by sending requests to api.development.push.apple.cominstead of api.push.apple.com

我正在向“生产”苹果推送服务器发送一个“开发”设备令牌。我通过向api.development.push.apple.com而不是发送请求来修复它api.push.apple.com