Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Format APNS-style JSON message in Python for use with Amazon SNS

I'm creating an iOS app, and for our push notifications, we're using Amazon's Simple Notification Service (SNS).

SNS is wonderful, but the documentation is pretty sparse. I'm using boto, Amazon's Python library, and I've figured out how to send plain-text push notifications:

device_arn = 'MY ENDPOINT ARN GOES HERE'
plain_text_message = 'a plaintext message'
sns.publish(message=plain_text_message,target_arn=device_arn)

However, what's not clear from the documentation is how to create an an Apple Push Notification Service (APNS) message. I need to send a sound and a badge along with the push notification, but can't figure out how to format the JSON for the message.

Here's my best guess so far:

message = {'default':'default message', 'message':{'APNS_SANDBOX':{'aps':{'alert':'inner message','sound':'mySound.caf'}}}}
messageJSON = json.dumps(message,ensure_ascii=False)
sns.publish(message=messageJSON,target_arn=device_arn,message_structure='json')

When I run this code, though, all I see on the notification is "default message" - which means that Amazon SNS rejected my message's format, and displayed the default instead.

How do I format this JSON correctly?

like image 848
bryanjclark Avatar asked Nov 21 '13 22:11

bryanjclark


People also ask

What is the format of structured notification messages sent by Amazon SNS?

The notification message sent by Amazon SNS for deliveries over HTTP, HTTPS, Email-JSON and SQS transport protocols will consist of a simple JSON object, which will include the following information: MessageId: A Universally Unique Identifier, unique for each notification published.

What is the format of an SNS endpoint message?

HTTP/HTTPS notification JSON format When Amazon SNS sends a notification to a subscribed HTTP or HTTPS endpoint, the POST message sent to the endpoint has a message body that contains a JSON document with the following name-value pairs. The Message value specified when the notification was published to the topic.

Does AWS SNS use FCM?

AWS SNS does support FCM. No AWS does not store messages after sending push notifications.

How can I read SNS messages?

Amazon SNS does not directly allow messages to be retrieved. Rather, for a given topic in Amazon SNS, you configure subscribers. Subscribers can be, for example, an email address, an Amazon SQS queue, an HTTP endpoint or a few other options.


2 Answers

I figured it out! Turns out, the APNS payload has to be encoded as a string within the larger payload - and it totally works.

Here's the final, working code:

apns_dict = {'aps':{'alert':'inner message','sound':'mySound.caf'}}
apns_string = json.dumps(apns_dict,ensure_ascii=False)
message = {'default':'default message','APNS_SANDBOX':apns_string}
messageJSON = json.dumps(message,ensure_ascii=False)
sns.publish(message=messageJSON,target_arn=device_arn,message_structure='json')

Here's a walkthrough of what's going on in this code:

First, create the python dictionary for APNS:

apns_dict = {'aps':{'alert':'inner message','sound':'mySound.caf'}}

Second, take that dictionary, and turn it into a JSON-formatted string:

apns_string = json.dumps(apns_dict,ensure_ascii=False)

Third, put that string into the larger payload:

message = {'default':'default message','APNS_SANDBOX':apns_string}

Next, we encode that in its own JSON-formatted string:

messageJSON = json.dumps(message,ensure_ascii=False)

The resulting string can then be published using boto:

sns.publish(message=messageJSON,target_arn=device_arn,message_structure='json')
like image 147
bryanjclark Avatar answered Oct 15 '22 19:10

bryanjclark


When I use the SNS publish tool it autogenerates JSON that looks like this:

{ 
    "default": "<enter your message here>", 
    "email": "<enter your message here>", 
    "sqs": "<enter your message here>", 
    "http": "<enter your message here>", 
    "https": "<enter your message here>", 
    "sms": "<enter your message here>", 
    "APNS": "{\"aps\":{\"alert\": \"<message>\",\"sound\":\"default\"} }", 
    "GCM": "{ \"data\": { \"message\": \"<message>\" } }", 
    "ADM": "{ \"data\": { \"message\": \"<message>\" } }" 
 }

This looks closer to the spec talked about by apple in their "Notification Payload" section. Where they state that the message should be

a JSON dictionary object (as defined by RFC 4627). 
This dictionary must contain another dictionary identified by the key aps.
The aps dictionary contains one or more properties

Have you tried providing a message closer to that specification? Something like this for instance:

{
    'default':'default message', 
    {
        'aps':{
            'alert':'inner message',
            'sound':'mySound.caf'
         }
    }
 }

Or following the example from the publish SNS publish tool:

{
    'default':'default message',
    'APNS': {
        'aps':{
            'alert':'inner message',
            'sound':'mySound.caf'
         }\
     }
 }

Maybe also using their backslash escaping.

like image 33
aychedee Avatar answered Oct 15 '22 19:10

aychedee