APNS(Apple Push Notification Service)与Node JS

4

我希望创建 APNS(Apple 推送通知服务),其中服务器将向 iOS 设备发送通知。我能够使用相同的设备令牌和相同的证书通过 PHP 实现推送通知,但我想改用 Node JS 发送通知。

我有以下有效的文件/证书可帮助我入门:

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

我一直在查阅多个资源链接,例如:

在这样做之后,我能够编写出以下示例代码,其中 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。但是仍然发生相同的情况。

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

非常感谢!

2个回答

3
您可能遇到了NodeJS本身的异步特性。我非常成功地使用了同样的node-apn模块。但是,您不能像在PHP中那样直接调用它-这是一种不从PHP->Node映射的同步模型。在任何实际发生之前,您的进程将退出-apnConnection.pushNotification(note);是一个异步调用,在您的脚本返回/退出之前仅刚刚开始。
正如在 node-apn 文档中所指出的那样,您可能希望在 apnConnection 上“监听”其他事件。以下是我在创建连接后用于记录发生在连接上的各种事件的代码摘录:
// 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);

非常感谢您的回复。感谢您的澄清,现在我对此有了更深入的了解。为了测试,我已经按照您所说的将事件放置在setInterval中。不幸的是,当我运行它时,它返回以下错误:**如果我调用“apnConnection.pushNotification(note);”那么会调用'transmissionError'并且我会得到一个错误代码2(缺少设备令牌)。 **如果我调用“apnConnection.pushNotification(note,myDevice);”我会得到以下错误消息:[Error: Connect timed out] - galhe2
1
尝试删除一些不必要的选项,特别是ca、gateway、port和enhanced。在我的设置中,我只使用了三个选项:certkeyproduction:true/false。我按照https://github.com/argon/node-apn/wiki/Preparing-Certificates上的说明准备了证书和密钥文件。 - Chad Robinson
好的,我按照你说的做了。现在如果我故意出错,我会收到事件。请求似乎已经通过了,但是我没有收到任何响应。我唯一得到的是来自“transmissionError”事件的[错误:连接超时]。在网上查找后,我发现人们说这可能是由于网络问题引起的。所以我打电话给HostGator进行验证,但他们说我根本不应该有任何问题。你有什么想法可能会导致这个问题吗?这是我的参考链接:https://github.com/argon/node-apn/issues/327#issuecomment-152564768 - galhe2
1
尝试在自己的电脑上本地运行它,而不是在HostGator上运行,看看会发生什么。 - Chad Robinson
1
个人而言,我不会使用 setInterval,因为如果第一个请求花费的时间太长,就会出现重叠请求。但无论哪种方式都可以 - 这只是我的个人偏好! - Chad Robinson
显示剩余2条评论

1

我将用简单的代码来解释它

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

   

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接