带有自定义 iOS 有效负载的 Amazon Simple Notification Service 并不那么简单

Posted

技术标签:

【中文标题】带有自定义 iOS 有效负载的 Amazon Simple Notification Service 并不那么简单【英文标题】:Amazon Simple Notification Service with custom iOS payload not so simple 【发布时间】:2016-01-02 18:25:33 【问题描述】:

发送纯文本通知很容易并且有据可查。但我今天一直在为 ios 发送一个自定义通知而烦恼,该通知包含警报和一些字段,如 userId。

我从this help page 开始并实现了与上一个示例类似的东西,然后我发现this answer 似乎使帮助页面上的最后一个示例无效,因为“url”属性应该在“aps”对象之外.我尝试了很多组合,但每个组合都作为文本发送到应用程序(整个消息,带有“默认”属性和“APNS”对象)......

如果我将 MessageStructure 显式设置为 json,我会收到错误:“无效参数:消息结构 - JSON 消息正文无法解析”但我很确定我的 JSON 是好的,当发送到 SNS 时,消息属性中的字符串看起来像这样:

 "default":"You received a new message from X.", 
 "APNS_SANDBOX":" \"aps\": \"alert\":\"You received a new message from X.\", 
                \"event\":\"Message\", 
                \"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"
            ", 
 "APNS":" \"aps\": \"alert\":\"You received a new message from X.\", 
                \"event\":\"Message\", 
                \"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"
            " 

有没有人有通过 C# 中的 SNS 发送带有自定义有效负载的通知的好例子?因为亚马逊肯定没有……谢谢!

【问题讨论】:

【参考方案1】:

奇怪的是,当我通过使用类和序列化对象而不是仅仅发送格式化的字符串来实现这一点时,它可以工作。唯一的区别是间距......在干净的版本中,除了属性值之外没有空格:

"default":"You received a new message from X.","APNS_SANDBOX":"\"aps\":\"alert\":\"You received a new message from X.\",\"event\":\"Message\",\"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\"","APNS":"\"aps\":\"alert\":\"You received a new message from X.\",\"event\":\"Message\",\"objectID\":\"7a39d9f4-2c3f-43d5-97e0-914c4a117cee\""

这些是我正在序列化的类(目前仅适用于 APNS),请使用您需要的任何属性,而不是 Event 和 ObjectID:

[DataContract]
public class AmazonSNSMessage

    [DataMember(Name = "default")]
    public string Default  get; set; 

    [DataMember(Name = "APNS_SANDBOX")]
    public string APNSSandbox  get; set; 

    [DataMember(Name = "APNS")]
    public string APNSLive  get; set; 

    public AmazonSNSMessage(string notificationText, NotificationEvent notificationEvent, string objectID)
    
        Default = notificationText;
        var apnsSerialized = JsonConvert.SerializeObject(new APNS
        
            APS = new APS  Alert = notificationText ,
            Event = Enum.GetName(typeof(NotificationEvent), notificationEvent),
            ObjectID = objectID
        );
        APNSLive = APNSSandbox = apnsSerialized;
    

    public string SerializeToJSON()
    
        return JsonConvert.SerializeObject(this);
    


[DataContract]
public class APNS 

    [DataMember(Name = "aps")]
    public APS APS  get; set; 

    [DataMember(Name = "event")]
    public string Event  get; set; 

    [DataMember(Name = "objectID")]
    public string ObjectID  get; set; 


[DataContract]
public class APS

    [DataMember(Name = "alert")]
    public string Alert  get; set; 

所以我通过以下方式收到 Amazon SNS 消息:

new AmazonSNSMessage(...).SerializeToJSON();

【讨论】:

感谢您的回答,您节省了我的时间。 :) 很好的答案,多年来一直在寻找解决方案! 就像一个魅力。感谢您发布解决方案。【参考方案2】:

刚刚为我解决此问题的关键是意识到特定于 SNS 的外部 JSON(例如“默认”和“APNS”属性)不得转义,只能转义内部有效负载。例如,这个 Message 值成功(只是发布开始):

"APNS":"\"aps\" ... 

注意第一个属性"APNS" 没有被转义,但是它的值(你的实际有效载荷将命中设备)被转义。以下完成了工作:

JObject payload = ... // your apns, etc payload JObject

var snsMsgJson = new JObject(
    new JProperty("default", "message 1 2 3"), // "default" is optional if APNS provided
    new JProperty("APNS", payload.ToString(Formatting.None))
);

string str = snsMsgJson.ToString(Formatting.None);

看上面的例子我就明白了,谢谢!但是,我知道上述“清洁类”所谓的解决方案实际上不能也不应该成为要求。所以当他说:“唯一的区别是间距......在干净的版本中,除了属性值之外没有空格”,这是不正确的。真正的区别在于,正如我所说,外部(特定于 SNS)JSON 应该被转义,但内部 必须

肥皂盒:那个文档怎么样啊?这个 API 中有很多东西浪费了很多时间,同样重要的是:一个人的幸福感。无论如何,我都非常感谢这项服务。

【讨论】:

以上是关于带有自定义 iOS 有效负载的 Amazon Simple Notification Service 并不那么简单的主要内容,如果未能解决你的问题,请参考以下文章

使用基于负载的实例时,Amazon OpsWorks 自定义说明书未更新

使用 keycloak 将自定义键/值添加到 JWT 令牌有效负载或用户

自定义序列化设置

带有自定义声音的推送通知未在 iOS 中显示

PhoneGap PushPlugin - 访问 iOS APNS 有效负载?

带有 IIS 的 Amazon 弹性负载均衡器