带有 Node JS 的 APNS(Apple 推送通知服务)

APNS (Apple Push Notification Service) with Node JS

我想创建 APNS(Apple 推送通知服务),服务器将在其中向 iOS 设备发送通知。 我可以使用相同的设备令牌和相同的证书通过 PHP 使推送通知工作,但是,我想通过 Node JS 而不是 PHP.

发送通知

我有以下有效的 files/certificates 来帮助我开始:

我浏览了几个 resources/links 例如:

这样做之后,我能够得出以下示例代码,其中 PASSWORD 代表 key.pem 的密码,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);
    }

执行此代码时我没有收到任何错误,但问题是我的 iOS 设备没有收到通知。我还尝试设置 ca:null & debug:true (在选项 var 中)。但同样的事情发生了。

同样,当我使用我拥有的 ck.pem & 设备令牌并将其与 PHP 一起使用时,它可以工作,但我无法使其在 Node JS 中工作。请帮忙!!

非常感谢!

您可能 运行 了解 NodeJS 本身的异步特性。我使用相同的 node-apn 模块取得了巨大成功。但是你不能像在 PHP 中习惯的那样直接调用它——这是一个不从 PHP->Node 映射的同步模型。你的进程在任何事情真正发生之前就已经退出了 - apnConnection.pushNotification(note); 是一个异步调用,在你的脚本 returns/exits.

之前几乎没有开始

node-apn 文档中所述,您可能希望在 apnConnection 上 "listen for" 其他事件。这是我用来注销连接创建后发生的各种事件的代码摘录:

// 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);

同样重要的是,您需要确保您的脚本在处理异步请求时保持 运行。大多数时候,当你构建一个越来越大的服务时,你最终会得到某种事件循环来做这件事,而 ActionHero、ExpressJS、Sails 等框架会为你做这件事。

与此同时,你可以用这个超级粗略的循环来确认它,它只会强制进程停留在 运行 直到你按下 CTRL+C:

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

我会用简单的代码来解释

  1. 首先使用此命令安装 apn 模块 npm install apn .
  2. 在代码中需要该模块

    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. 这里是通知的主要内容

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(); 

   

在 Payload 中,您可以使用自定义发送数据keys.I希望对您有所帮助