APNS (Apple Push Notification Service) with Node JS

徘徊边缘 提交于 2020-05-10 06:46:50

问题


I am looking to create APNS (Apple Push Notification Service), where the server will be sending notifications to the iOS devices. I am able to make the push notifications work via PHP using the SAME device token and the SAME certificate, however, I would like to send notifications via Node JS instead of PHP.

I have the following valid files/certificates to help me get started:

  • cert.pem
  • key.pem
  • aps_development.cer
  • cert.p12
  • key.p12,
  • ck.pem

I've been looking through several resources/links such as:

  • https://github.com/argon/node-apn
  • How to implement APNS notifications through nodejs?

After doing so, I was able to come up with the following sample code, where PASSWORD stands for the password of the key.pem and TOKEN stands for my device's token:

    var apn = require("apn");
    var path = require('path');
    try {
        var options = {
            cert: path.join(__dirname, 'cert.pem'),         // Certificate file path
            key:  path.join(__dirname, 'key.pem'),          // Key file path
            passphrase: '<PASSWORD>',                             // A passphrase for the Key file
            ca: path.join(__dirname, 'aps_development.cer'),// String or Buffer of CA data to use for the TLS connection
            production:false,
            gateway: 'gateway.sandbox.push.apple.com',      // gateway address
            port: 2195,                                     // gateway port
            enhanced: true                                  // enable enhanced format
        };
        var apnConnection = new apn.Connection(options);
        var myDevice = new apn.Device("<TOKEN>");
        var note = new apn.Notification();
        note.expiry = Math.floor(Date.now() / 1000) + 3600; // Expires 1 hour from now.
        note.badge = 3;
        note.sound = "ping.aiff";
        note.alert = "You have a new message";
        note.payload = {'msgFrom': 'Alex'};
        note.device = myDevice;
        apnConnection.pushNotification(note);



        process.stdout.write("******* EXECUTED WITHOUT ERRORS************ :");


    } catch (ex) {
        process.stdout.write("ERROR :"+ex);
    }

I get no errors when executing this code, but The problem is that no notification is received on my iOS device. I have also tried setting the ca:null & debug:true (in options var). But same thing happens.

Again, when I use the ck.pem & device token that I have and use it with PHP, it works, but i'm not able to make it work in Node JS. PLEASE HELP!!

Thank you so much!


回答1:


You are probably running into the asynchronous nature of NodeJS itself. I use the same node-apn module with great success. But you don't just call it directly like you're used to in PHP - that's a synchronous model that doesn't map from PHP->Node. Your process is exiting before anything can actually happen - the apnConnection.pushNotification(note); is an asynchronous call that just barely gets started before your script returns/exits.

As noted in the node-apn docs you probably want to "listen for" additional events on apnConnection. Here's an excerpt of code that I use to log out various events that are occurring on the connection after it's created:

// We were unable to initialize the APN layer - most likely a cert issue.
connection.on('error', function(error) {
    console.error('APNS: Initialization error', error);
});

// A submission action has completed. This just means the message was submitted, not actually delivered.
connection.on('completed', function(a) {
    console.log('APNS: Completed sending', a);
});

// A message has been transmitted.
connection.on('transmitted', function(notification, device) {
    console.log('APNS: Successfully transmitted message');
});

// There was a problem sending a message.
connection.on('transmissionError', function(errorCode, notification, device) {
    var deviceToken = device.toString('hex').toUpperCase();

    if (errorCode === 8) {
        console.log('APNS: Transmission error -- invalid token', errorCode, deviceToken);
        // Do something with deviceToken here - delete it from the database?
    } else {
        console.error('APNS: Transmission error', errorCode, deviceToken);
    }
});

connection.on('connected', function() {
    console.log('APNS: Connected');
});

connection.on('timeout', function() {
    console.error('APNS: Connection timeout');
});

connection.on('disconnected', function() {
    console.error('APNS: Lost connection');
});

connection.on('socketError', console.log);

Equally important, you need to make sure your script STAYS RUNNING while the async requests are being processed. Most of the time, as you build a bigger and bigger service, you're going to end up with some kind of event loop that does this, and frameworks like ActionHero, ExpressJS, Sails, etc. will do this for you.

In the meantime, you can confirm it with this super-crude loop, which just forces the process to stay running until you hit CTRL+C:

setInterval(function() {
    console.log('Waiting for events...');
}, 5000);



回答2:


I will explain it with simple code

  1. First install apn module using this command npm install apn .
  2. Require that module in code

    var apn = require('apn');

      let service = new apn.Provider({
        cert: "apns.pem",
        key: "p12Cert.pem",
        passphrase:"123456",
        production: true //use this when you are using your application in production.For development it doesn't need
        });
    
  3. Here is the main heart of notification

let note = new apn.Notification({
    			payload:{
    			 "staffid":admins[j]._id,
    			 "schoolid":admins[j].schoolid,
    			 "prgmid":resultt.programid
    			},
    category:"Billing",
    alert:"Fee payment is pending for your approval",
    sound:"ping.aiff",
    topic:"com.xxx.yyy",//this is the bundle name of your application.This key is needed for production
    contentAvailable: 1//this key is also needed for production
    });
    console.log(`Sending: ${note.compile()} to ${ios}`);
    services.send(note, ios).then( result => {//ios key is holding array of device ID's to which notification has to be sent
        console.log("sent:", result.sent.length);
        console.log("failed:", result.failed.length);
        console.log(result.failed);
    });
    services.shutdown(); 

   

In Payload you can send data with custom keys.I hope it helps




回答3:


Still facing issue, try

note.topic = "com.YOURWESITENAME.app";


来源:https://stackoverflow.com/questions/36633188/apns-apple-push-notification-service-with-node-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!