从Amazon SNS获取“EndpointDisabled”

时间:2013-10-15 06:14:13

标签: amazon-web-services amazon-sns

我正在使用Amazon SNS。通知效果很好,但有时我会收到此错误:

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

也许你知道为什么。

9 个答案:

答案 0 :(得分:69)

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

为此SNS主题订阅HTTP端点并记录所有传递失败可能是值得的,因此您可以使用历史数据来处理和调试生产问题。

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

答案 1 :(得分:37)

到目前为止,我找到了3个理由:

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

这些是关于Iphons / Ipads。

答案 2 :(得分:20)

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

  • 您推送到端点但令牌无效/已过期。如果出现以下情况,则令牌无效:

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

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

  • App已重新安装在同一设备上。对于Android,应用程序会分配一个新令牌。这种情况与APN一样,但更常见于Android。

  • 如果是APN,则在xCode中选择了错误的配置文件。在这种情况下,通知失败,设备在APN反馈后被禁用。

  • 如果错误地将令牌用于IOS开发到IOS制作应用程序,反之亦然。

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

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

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

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

有关详细信息,我建议使用这个解决我问题的优秀article

答案 3 :(得分:16)

根据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指示端点无效时,Message Processor将此设置为false。用户可以将其设置回true,通常在更新令牌后。

在这种情况下,“通知服务”指的是Google的GCM,Apples APNS或亚马逊的ADM。

答案 4 :(得分:5)

我有同样的问题。 这就是我所做的:

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

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

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

  5. 在AWS SNS中创建一个新的应用程序。给它起个名字。选择Apple Development。
  6. 从Keychain Access中选择带有.p12扩展名的完整证书,并输入从Keychain Access导出时选择的密码短语 将公共CERTIFICATE .pem文件的内容复制到标有"证书"的textarea,包括起始行和结束行:

    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    
  7. 仅将以下行开头和结尾的私钥.pem文件的一部分复制到标有"私钥"

    的文本区域
    -----BEGIN RSA PRIVATE KEY-----
    -----END RSA PRIVATE KEY-----
    
  8. 我使用Cordova和phonegap-plugin-push 1.4.4,但我的问题与phonecap无关。除了对上述内容有点混淆之外,最终为我做的诀窍是在XCode中打开我的项目,为我的项目找到Target,然后启用推送通知。这会自动添加"推送通知"应用程序ID的权利..下次在您的设备上安装该应用程序时,推送通知应该有效。至少它对我有用。

    我希望这可以拯救遇到与我一样半天工作同样问题的人! :)

答案 5 :(得分:4)

在采取严厉措施之前快速检查清单:

  1. 使用钥匙串应用生成证书签名请求(CSR)。
  2. 使用 Keychain App 将APNS证书及其私钥导出到单个p12文件中。
  3. 在Amazon SNS中创建新应用程序时,该平台必须与APNS环境匹配(双方的开发 / 生产)。
  4. 当您请求设备令牌时,您必须位于正确的应用程序(应用程序的捆绑包标识符与APNS证书匹配)。
  5. 在AWS SNS中创建新的平台端点时,必须将设备令牌添加到正确的应用程序(良好的应用程序证书和良好的开发/生产平台)。
  6. 在我的情况下,我使用第三方SSL工具生成了CSR。我从Apple开发人员门户网站获得了有效证书但没有私钥。然后我尝试使用Windows的证书工具导出但没有取得很大成功。浪费时间。启动你的Mac。

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

答案 6 :(得分:1)

如果您收到错误End Point is Disabled,请使用以下代码启用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*

答案 7 :(得分:1)

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

如果您正在创建生产端点,SNS将警告您不匹配的证书,但它没有检查开发端点。您知道端点被borked的唯一方法是当您收到平台令牌错误时。

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

答案 8 :(得分:1)

我正在使用它。如果get端点响应发现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

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