【问题标题】:APNS (Apple Push Notification Service) with Node JS带有 Node JS 的 APNS(Apple 推送通知服务)
【发布时间】:2016-08-06 14:27:47
【问题描述】:

我正在寻找创建 APNS(Apple 推送通知服务),服务器将在其中向 iOS 设备发送通知。 我可以使用 SAME 设备令牌和 SAME 证书通过 PHP 进行推送通知,但是,我想通过 Node JS 而不是 PHP 发送通知。

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

  • 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 (在选项 var 中)。但同样的事情也会发生。

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

非常感谢!

【问题讨论】:

    标签: ios node.js apple-push-notifications apn


    【解决方案1】:

    您可能遇到了 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);”我收到以下错误消息:[错误:连接超时]
    • 尝试删除一些不必要的选项,尤其是 ca、网关、端口和增强。在我的设置中,我只使用三个选项:certkeyproduction:真/假。我按照github.com/argon/node-apn/wiki/Preparing-Certificates 的说明准备了证书和密钥文件。
    • 好的,我做了你所说的一切。如果我故意犯错,我现在正在接收事件。该请求似乎通过了,但我没有收到任何回复。我唯一得到的是:来自“transmissionError”事件的[错误:连接超时]。上网查了一下,发现有人说可能是网络问题。所以我打电话给 HostGator 进行验证,但他们说我根本不应该有任何问题。您知道可能导致此问题的原因吗?这是我的参考链接:github.com/argon/node-apn/issues/327#issuecomment-152564768
    • 尝试在您自己的计算机上本地运行它,而不是在 HostGator 中运行,看看会发生什么。
    • 我个人不会使用 setInterval 只是因为如果第一个请求需要很长时间才能完成,您可能会收到重叠请求。但无论哪种方式都有效 - 这只是我个人的喜好!
    【解决方案2】:

    我会用简单的代码解释一下

    1. 首先使用此命令 npm install apn 安装 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 中,您可以使用自定义键发送数据。希望对您有所帮助

    【讨论】:

      猜你喜欢
      • 2012-12-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      相关资源
      最近更新 更多