57

我正在使用亚马逊 SNS。通知运行良好,但有时我会收到此错误:

{
    "message": "Endpoint is disabled",
    "code": "EndpointDisabled",
    "name": "EndpointDisabled",
    "statusCode": 400,
    "retryable": false
}

也许你知道为什么。

4

9 回答 9

74

您可以创建一个新的 SNS 主题push-notification-failures,然后将您的 APNS/APNS_SANDBOX 应用程序的“交付失败”事件与其关联。通过电子邮件订阅事件(并确认),您将获得有关失败的有用调试信息。这一切都可以通过 SNS 控制台完成,并且不需要执行 API 调用。

订阅此 SNS 主题的 HTTP 端点并记录所有交付失败可能是值得的,这样您就可以处理历史数据并调试生产问题。

例如FailureMessage,“与端点关联的平台令牌无效”的传递意味着您正在从 APNS_SANDBOX 向 APNS 注册设备发送消息,反之亦然。这可能意味着您的构建系统有错误的 APNS 设置。(我们有一个令人沮丧的问题,即开发人员使用 APNS_SANDBOX 构建二进制文件,而 TestFlight 使用 APNS 构建二进制文件进行本地测试和 QA,这正是导致我走上这条道路的原因。)

于 2014-12-29T17:10:55.933 回答
40

到目前为止,我发现了 3 个原因:

  • 有时我们会混合来自沙盒应用程序的令牌。
  • 用户在手机设置中关闭通知。
  • 用户卸载了该应用程序。

这些是关于 Iphons/Ipads 的。

于 2013-12-18T16:09:58.663 回答
32

可以禁用端点的原因很少。我没有在任何地方看到它的记录(可能错过了它),这是我从支持中得到的:

  • 您推送到端点,但令牌无效/过期。令牌在以下情况下无效:

  • 它属于设备上不再安装的应用程序。

  • 如果设备已从备份中恢复。这会使令牌无效,您的应用应请求新令牌并相应地更新 SNS 端点令牌。

  • 应用程序已重新安装在同一设备上。在 Android 的情况下,应用程序被分配了一个新的令牌。APN 也会发生这种情况,但 Android 更常见。

  • 对于 APN,在 xCode 中选择了错误的配置文件。在这种情况下,通知会失败,并且稍后会在 APNs 反馈后禁用设备。

  • 如果错误地将 IOS 开发代币用于 IOS 生产应用程序,反之亦然。

  • 如果 Apple 出于任何原因使您的 IOS 推送证书无效或有人从 iTunes 连接门户撤销推送证书。这需要几个小时才能禁用设备。

  • 如果您从 Google 开发人员控制台更新 API 密钥而不更新 SNS 中的平台应用程序凭据,则与 GCM 相同。

  • 您推送到 APNs 设备端点,但由于推送证书过期,应用程序已被禁用。

  • 您推送到 GCM 设备端点,但 API 密钥已在 Google 开发人员控制台中更新,但 SNS 平台应用程序凭据未相应更新。

有关详细信息,我推荐这篇解决我问题的优秀文章

于 2017-02-16T10:44:56.687 回答
17

根据http://docs.aws.amazon.com/sns/latest/APIReference/API_Publish.html这意味着端点被禁用。

来自http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sns/model/SetEndpointAttributesRequest.html

已启用——启用/禁用向端点传递的标志。当通知服务向 SNS 指示端点无效时,消息处理器会将其设置为 false。用户可以将其设置回 true,通常在更新 Token 之后。

在这种情况下,“通知服务”指的是谷歌的 GCM、苹果的 APNS 或亚马逊的 ADM。

于 2013-10-21T22:50:02.463 回答
6

我遇到过同样的问题。这就是我所做的:

  1. 将完整证书从 Keychain Access 导出到 .p12 文件
  2. 将私钥从 Keychange Access 导出到 *private.p12 文件

  3. 将 openssl 与下载的 .cer 文件(来自 iOS Developer MemberCenter)一起使用以创建公共 .pem 证书

  4. 将 openssl 与生成的 *private.p12 文件一起使用以创建私有 .pem 密钥文件

  5. 在 AWS SNS 中创建一个新应用程序。给它一个名字。选择苹果开发。
  6. 从带有 .p12 扩展名的 Keychain Access 中选择 FULL CERTIFICATE,然后输入您在从 Keychain Access 导出时选择的密码 将公共 CERTIFICATE .pem 文件的内容复制到标有“Certificate”的文本区域,包括开始行和结束行:

    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    
  7. 仅将私钥 .pem 文件中以下列行开头和结尾的部分复制到标记为“Private Key”的文本区域:

    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----
    

我将 Cordova 与 phonegap-plugin-push 1.4.4 一起使用,但我的问题与 phonecap 无关。除了对上面的一些困惑之外,最终对我有用的是,在 XCode 中打开我的项目,找到我的项目的目标,然后启用推送通知。这会自动将“推送通知”权利添加到应用程序 ID。下次在您的设备上安装应用程序时,推送通知应该可以工作。至少它对我有用。

我希望这可以为遇到与我相同问题的人节省 1/2 天的工作时间!:)

于 2015-12-02T22:26:18.603 回答
5

采取严厉措施之前的快速清单:

  1. 使用Keychain App生成证书签名请求 (CSR) 。
  2. 使用Keychain App将 APNS 证书及其私钥导出到单个 p12 文件中。
  3. 当您在 Amazon SNS 中创建新应用程序时,平台必须匹配 APNS 环境(开发/生产双方)。
  4. 当您请求设备令牌时,您必须在正确的应用程序中(应用程序的捆绑标识符与 APNS 证书匹配)。
  5. 在 AWS SNS 中创建新平台终端节点时,必须将设备令牌添加到正确的应用程序(良好的应用程序证书和良好的开发/生产平台)。

就我而言,我使用第三方 SSL 工具生成了 CSR。我从 Apple 开发者门户获得了有效证书,但没有私钥。然后我尝试了 Windows 的证书工具来导出,但没有成功。浪费时间。启动你的 Mac。

然后我使用 AmazonMobilePush 示例应用程序来获取设备令牌。因为演示的包标识符与我的证书不匹配,所以端点无效。在每个发送端点的 SNS 上都被禁用 (false)。最后原因很明显,但我仍然失去了宝贵的时间。

于 2016-01-09T03:36:21.820 回答
1

如果您收到错误End Point is Disabled消息,请使用以下代码启用端点,然后使用 Amazon 凭证推送通知:

*//Enable Device*

var sns = new AmazonSimpleNotificationServiceClient("AwsAccesskeyId", "AwsSecrteAccessKey", RegionEndpoint.USWest1);
Dictionary<string, string> objDictCheckEndpointEnable = new Dictionary<string, string>();
objDictCheckEndpointEnable.Add("Enabled", "False");
sns.SetEndpointAttributes(new SetEndpointAttributesRequest
    {
        Attributes = objDictCheckEndpointEnable,
        EndpointArn = "AwsEndPointArn" //This is Device End Point Arn
    });

*//End*
于 2014-11-26T13:27:14.243 回答
1

对我来说,我收到“与端点关联的平台令牌无效”,因为我的 SNS 平台应用程序端点设置不正确。具体来说,即使它包含正确的证书和私钥,SNS 控制台也没有从我的 .p12 文件中正确读取凭据。基于这篇文章的解决方案是创建第二个 .p12 文件,其中包含证书但没有密钥。我从第一个 .p12 文件加载了凭据,然后加载了第二个 .p12 文件的凭据。当我这样做时,我可以看到证书字符串发生了变化,之后我就没有问题了。

如果您正在创建生产端点,SNS 会警告您有关不匹配的证书,但它不会对开发端点进行此类检查。您知道端点被破坏的唯一方法是当您收到平台令牌错误时。

我当然希望这对那里的人有所帮助,因为它让我分心。

于 2015-10-31T03:07:07.403 回答
1

我正在使用这个。如果获取终端节点响应发现 NotFound 错误,它会创建一个终端节点(这绝不应该发生,但见鬼,它在 AWS SNS 文档网站上)。如果这没有发生,则意味着您正在获取端点的信息。它可以是好的(令牌匹配并且启用是真的),或者相反(在这种情况下你需要更新它)。

    - (void)getEndpointDetailsWithResponse:(void(^)(AWSSNSGetEndpointAttributesResponse *response, AWSTask *))handleResponse {
    NSString * deviceTokenForAWS = [self deviceTokenForAWS];
    AWSSNS *manager = [AWSSNS SNSForKey:@"EUWest1SNS"];

    AWSSNSGetEndpointAttributesInput *input = [AWSSNSGetEndpointAttributesInput new];
    input.endpointArn = self.endpointArn;
    AWSTask *getEndpointAttributesTask = [manager getEndpointAttributes:input];
    [getEndpointAttributesTask continueWithBlock:^id(AWSTask *task) {
        NSLog(@"%@ Error: %@", task.result, task.error);


        AWSSNSGetEndpointAttributesResponse *result = task.result;
        NSError *error = task.error;

        if (error.code == AWSSNSErrorNotFound) {
            [self createEndpointWithResponse:^(AWSSNSCreateEndpointResponse *createResponse) {


                dispatch_async(dispatch_get_main_queue(), ^{
                    if (handleResponse != nil) {
                        handleResponse(result, task);
                    }
                });
            }];
        } else {

            NSLog(@"response for get endpoint attributes : %@", result);

            NSString *token = [result.attributes valueForKey:@"Token"];
            NSString *enabled = [result.attributes valueForKey:@"Enabled"];
            NSLog(@"token : %@, enabled : %@", token, enabled);
            BOOL wasSuccessful = [token isEqualToString:deviceTokenForAWS] && ([enabled localizedCaseInsensitiveCompare:@"true"] == NSOrderedSame);

            if (!wasSuccessful) {
                NSLog(@"device token does not match the AWS token OR it is disabled!");
                NSLog(@"Need to update the endpoint");

                AWSSNSSetEndpointAttributesInput *seai = [AWSSNSSetEndpointAttributesInput new];
                seai.endpointArn = self.endpointArn;

            NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:deviceTokenForAWS, @"Token", @"true", @"Enabled", nil];
            seai.attributes = attributes;

                AWSTask *setEndpointAttributesTask = [manager setEndpointAttributes:seai];
                [setEndpointAttributesTask continueWithBlock:^id(AWSTask *task) {
                    NSLog(@"response : %@, error: %@", task.result, task.error);

                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (handleResponse != nil) {
                            handleResponse(result, task);
                        }
                    });
                    return nil;
                }];

            } else {
                NSLog(@"all is good with the endpoint");

                dispatch_async(dispatch_get_main_queue(), ^{
                    if (handleResponse != nil) {
                        handleResponse(result, task);
                    }
                });
            }
        }
        return nil;
    }];
}

这是此处找到的 AWS SNS 令牌管理文档的确切副本:https ://mobile.awsblog.com/post/Tx223MJB0XKV9RU/Mobile-token-management-with-Amazon-SNS

如果需要,我可以附上我的实现的其余部分,但这部分是最重要的部分。

于 2016-04-18T06:49:02.983 回答