17
votes

I'm looking for examples of using node.js with Amazon SNS and Apple APN push notifications. We use Amazon for our hosting, and I have used SNS before, it's pretty simple. But the examples they have for push notifications are for java, and there is no examples for Node. It's confusing, as usual with them, and I'm hoping to cut my research and time spent short. It can't be that hard. I'm also wondering how they deal with errors, and the differences between the sandbox and production. Apple reacts differently between the two environments, not failing in the sandbox as they do in production.

3

3 Answers

20
votes

It ends up not being that hard, just figuring out the documentation was unpleasant. You need to create the main endpoint for the SNS topic in the console, by far the easiest way, including the loading of the certificate. You then used createPlatformEnpoint to create an endpoint for each device id. That returns another SNS topic, specific fo that device, that you then use to send the message.

So, the following works to send a single message to a single client. If you want send something en masse, not sure you can do that. Also not sure how you deal with Apple's feedback, which you are supposed to check for failed sends.

config = require("./config.js").config;

var token = "1234567898123456789";

var AWS = require('aws-sdk');

AWS.config.update({accessKeyId: config.AWSAccessKeyId, secretAccessKey: config.AWSSecretKey});
AWS.config.update({region: config.AWSRegion});

var sns = new AWS.SNS();

var params = {'PlatformApplicationArn':config["AWSTargetARN"],'Token':token};

var message = 'Test';
var subject = 'Stuff';

sns.createPlatformEndpoint(params,function(err,EndPointResult)
{
    var client_arn = EndPointResult["EndpointArn"];

    sns.publish({
    TargetArn: client_arn,
    Message: message,
    Subject: subject},
        function(err,data){
        if (err)
        {
            console.log("Error sending a message "+err);
        }
        else
        {
            console.log("Sent message: "+data.MessageId);

        }
    });
});
8
votes

It's fairly straightforward as CargoMeister pointed out.

I've written a blog post about getting it setup check it out here http://evanshortiss.com/development/mobile/2014/02/22/sns-push-notifications-using-nodejs.html

I've also a Node.js wrapper module that is easier to use than the AWS SDK as I've worked around the documentation. It supports iOS and Android Push Services (as that's all I've tested/worked with), manages message formats other than Strings and exposes events: https://npmjs.org/package/sns-mobile

I haven't used topics to manage endpoints, not sure is that an issue though. You just create PlatformEndpoints first via the SNS console.

7
votes
var AWS = require('aws-sdk');
var express = require('express');
var app = express();

AWS.config.credentials = new AWS.CognitoIdentityCredentials({
 IdentityPoolId: 'add IdentityPoolId'
});

AWS.config.region = 'add region';

var sns = new AWS.SNS();

   sns.createPlatformEndpoint({
    PlatformApplicationArn: 'add platform application arn',
    Token: 'add device token'
   }, function (err, data) {
    if (err) {
     console.log("errorMessage" + err.stack);
     return;
    }

    var endpointArn = data.EndpointArn;
    var payload = {
     default: 'Hello World',
     APNS: {
      aps: {
       alert: 'Hello World',
       sound: 'default',
       badge: 1
      }
     }
    };

    // first have to stringify the inner APNS object...
    payload.APNS = JSON.stringify(payload.APNS);

    // then have to stringify the entire message payload
    payload = JSON.stringify(payload);

    console.log('sending push');
    sns.publish({
     Message: payload,
     MessageStructure: 'json',
     TargetArn: endpointArn
    }, function (err, data) {
     if (err) {
      console.log(err.stack);
      return;
     }

     console.log('push sent');
     console.log(data);
    });
   });

var server = app.listen(8081, function () {
   var host = server.address().address
   var port = server.address().port

   console.log("Example app listening at http://%s:%s", host, port)
})