从Amazon SNS获取“EndpointDisabled”

59

我正在使用亚马逊 SNS。通知正常工作,但有时会出现以下错误:

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

或许你知道原因。

9个回答

75
您可以创建一个名为push-notification-failures的新SNS主题,然后将您的APNS / APNS_SANDBOX应用程序的“投递失败”事件与其关联。通过电子邮件订阅此事件(并确认),您将获得有关故障的有用调试信息。所有这些都可以通过SNS控制台完成,不需要进行API调用。
值得注意的是,订阅此SNS主题的HTTP端点并记录所有投递失败可能很值得,这样您就可以获得历史数据以便于从中进行调试和解决生产问题。
例如,“与终端点关联的平台令牌无效”的投递FailureMessage 表示您正在从APNS_SANDBOX发送消息到已注册的APNS设备或反之亦然。这可能意味着您的构建系统的APNS设置错误。(我们存在一些令人沮丧的问题,即使用APNS_SANDBOX来构建开发人员二进制文件而使用APNS进行本地测试和QA的TestFlight构建二进制文件,这就是我走上这条路的原因。)

4
配置“传递失败”:SNS首页 > 应用程序 > 选择应用程序 > 操作 > 配置事件。 - Jon

40

目前我已经找到了3个原因:

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

这些问题涉及到Iphone / Ipad。


你确定第二种情况(用户在手机设置中关闭通知)会导致这种情况吗?这是否意味着我们应该继续向此端点发送未来的通知,以防他将来重新打开设置? - Walty Yeung
是的,在我回答2014年的时候,我对此非常确定。如果我没记错的话,我使用了尝试它们的策略,但你应该重新审查一下。 - Bartosz Dabrowski
截至目前,如果2仍然是一个有效的情况,我会感到非常惊讶。像SNS Messaging这样的提供商甚至宣传了这样一个事实,即您可以使用通知来让应用程序执行任何您想要的操作(不仅仅是向用户显示通知)。如果用户可以轻松地挫败您试图让应用程序执行您想要的操作(例如强制更新),他们不会宣传这一点。 - setholopolus

37
有几个原因可能导致终端点被禁用。我没有在文档中看到相关说明(可能我错过了),以下是我从支持中获得的信息:
  • 您向终端点推送消息,但令牌无效/已过期。令牌会在以下情况下变为无效:

  • 它属于一个已经卸载了的应用。

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

  • 已重新在同一设备上安装应用。对于 Android 设备,应用将被分配一个新令牌。这种情况也会发生在 APNs 上,但在 Android 上更为常见。

  • 如果在 xCode 中选择了错误的配置文件,则 APNs 会失败,并且设备稍后会被禁用。

  • 如果错误地将 IOS 开发的令牌用于 IOS 生产应用程序或反之亦然。

  • 如果 Apple 因任何原因无效您的 IOS 推送证书或某人从 itunes connect 门户撤销了推送证书,则需要几个小时才能使设备停用。

  • 如果您在 Google 开发人员控制台中更新了 API 密钥,但没有相应地更新 SNS 平台应用程序凭据,则同样适用于 GCM。

  • 您向 APNs 设备终端点推送消息,但由于过期的推送证书而禁用了应用程序。

  • 您向 GCM 设备终端点推送消息,但未相应地更新 SNS 平台应用程序凭据中的 API 密钥。

有关详细信息,我建议阅读这篇优秀的文章,它解决了我的问题。


18
根据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中得知:
Enabled -- 启用/禁用向终端点发送消息的标志。当通知服务向SNS指示终端点无效时,消息处理器将此设置为false。用户可以将其设置回true,通常在更新令牌后。
在这种情况下,“通知服务”是指Google的GCM、Apple的APNS或Amazon的ADM。

对于那些被禁用的端点,我们是否应该考虑设备已经失效并丢弃消息? - Hesky

6

我有同样的问题。

这是我所做的:

  1. export the FULL CERTIFICATE from Keychain Access to a .p12 file
  2. export the PRIVATE KEY from Keychange Access to a *private.p12 file

  3. use openssl with the downloaded .cer file (from iOS Developer MemberCenter) to create a public .pem certificate

  4. use openssl with the generated *private.p12 file to create a private .pem keyfile

  5. In AWS SNS create a new Application. Give it a name. Choose Apple Development.
  6. Choose the FULL CERTIFICATE from Keychain Access with a .p12 extension, and type in the passphrase you chose when exporting from Keychain Access Copy the content of the public CERTIFICATE .pem file, to the textarea labelled "Certificate", including the starting and ending lines:

    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    
  7. Copy only the part of the private key .pem file starting and ending with the following lines, to the textarea labelled "Private Key":

    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----
    
我使用Cordova和phonegap-plugin-push 1.4.4,但我的问题与phonecap无关。除了上述有点困惑之外,最终对我有用的是在XCode中打开我的项目,找到我的项目目标,然后启用推送通知。这会自动将“推送通知”授权添加到应用程序ID。下次在您的设备上安装应用程序时,推送通知应该可以正常工作。至少对我来说是这样的。
希望这可以为遇到与我同样问题的人节省半天的工作时间! :)

嗨,我已经按照您的要求完成了所有工作,而且我已经尝试过从控制台直接发布消息,但依然没有成功。请帮忙! - Mohsin Khubaib Ahmed
请记得为您刚创建的新应用程序配置IAM访问权限。 - wz366

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)。最后原因显而易见,但我仍然浪费了宝贵的时间。

1
当我尝试在我的iPhone上进行测试时,我遇到了这个问题。我犯的错误是第三个,即在创建新的平台应用程序时没有勾选“用于沙盒中的开发”的框。 - jsteele

2
如果您收到“终端点已禁用”错误,请使用以下代码启用 endPoint,然后使用 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*

2
我非常确定你的意思是将其设置为True:objDictCheckEndpointEnable.Add("Enabled", "True"); - Nicholas Petersen
是的,如果设备被禁用,则可以通过上述代码启用。 - Sanjay Dwivedi
1
请将代码修改为 .Add("Enabled", "True");。顺便提一下,昨天在处理这个问题时我注意到AWS将值小写化,即"true"或"false",但这可能并不重要。 - Nicholas Petersen

1
我正在使用这个。如果获取端点响应发现NotFound错误,则创建一个端点(这永远不应该发生,但是嘿,它在AWS SNS文档网站上)。 如果没有发生这种情况,那么意味着您正在获取端点的信息。它可以是正常的(令牌匹配且启用为true),也可以是相反的(在这种情况下,您需要更新它)。
    - (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
如果需要,我可以附上我的实现的其余部分,但这部分是最重要的。

请提供您的实现代码,需要确认一下我的端口。非常感谢您的帮助 :) - Mohsin Khubaib Ahmed

1
对我来说,我之所以会收到“与端点关联的平台令牌无效”的消息,是因为我的SNS平台应用程序端点没有正确设置。具体来说,尽管我的.p12文件包含正确的证书和私钥,但SNS控制台无法正确读取凭据。根据this post提供的解决方案是创建第二个只包含证书而不包含密钥的.p12文件。我首先加载了第一个.p12文件的凭据,然后再加载第二个.p12文件的凭据。当我这样做时,我可以看到证书字符串发生变化,之后我就没有遇到任何问题了。
如果您正在创建生产端点,SNS将警告您存在不匹配的证书,但它不会对开发端点进行任何检查。唯一的方法是在收到平台令牌错误时才知道端点出现故障。
我真心希望这能帮助到某些人,因为它让我非常苦恼。

这真让我抓狂!我不理解你的生产端点。你能详细说明一下吗? - Mohsin Khubaib Ahmed
如果您正在创建APNS沙盒端点,则SNS控制台将允许您使用无效证书而不警告您,至少截至2015年10月。对于APNS生产端点,您将收到有关无效证书的警告。 - phatmann
1
如果我(1)为每个证书创建一个新的CSR,(2)注意将其电子邮件地址与iOS帐户匹配,并且(3)在从Keychain导出到p12文件时选择证书和密钥,则当阅读p12文件时,SNS控制台似乎可以正常工作。我最终还是遇到了一个无法工作的生产端点,直到我使用新证书更新了凭据。SNS控制台存在缺陷*,而整个证书生成过程由于步骤繁多而非常容易出错。因此,请耐心,小心并不断尝试直到成功。 - phatmann
又出现了一个奇怪的错误!已经两天了,伙计,两天了:S https://dev59.com/x5jga4cB1Zd3GeqPEQd- - Mohsin Khubaib Ahmed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接