ssl 如何从APNS开发商过渡到生产提供商?

bqjvbblv  于 2023-02-19  发布在  其他
关注(0)|答案(1)|浏览(173)

API是在NodeJS中编写的目前,

  • 该应用程序能够使用以下代码在Apple的开发环境中发送推送通知。
  • 获取坏设备令牌400错误
  • 此外,注意开发通知工作(SO将不会格式化我的代码如下):
module.exports.sendNotification = (deviceToken, msg, payload) => {
      const jwt = require("jsonwebtoken");
      const http2 = require("http2");
      const fs = require("fs");
    
      const key = fs.readFileSync(process.env.APNS_KEY, "utf8");
    
      // "iat" should not be older than 1 hr from current time or will get rejected
      const token = jwt.sign(
        {
          iss: process.env.APNS_TEAM_ID, // "team ID" of your developer account
          iat: Date.now() / 1000 // Replace with current unix epoch time 
        },
        key,
        {
          header: {
            alg: "ES256",
            kid: process.env.APNS_KEY_ID // issuer key which is "key ID" of your p8 file
          }
        }
      );
    
      /*
              Use 'https://api.production.push.apple.com' for production build
            */
    
      const host = process.env.APNS_HOST;
      const path = `/3/device/${deviceToken}`;
    
      const client = http2.connect(host);
    
      client.on("error", (err) => console.error(err));
    
      const body = {
        aps: {
          alert: msg,
          "content-available": 1,
          payload
        }
      };
    
      const headers = {
        ":method": "POST",
        "apns-topic": process.env.APNS_TOPIC, // your application bundle ID
        ":scheme": "https",
        ":path": path,
        authorization: `bearer ${token}`
      };
    
      const request = client.request(headers);
    
      request.on("response", (headers, flags) => {
        for (const name in headers) {
          console.log(`${name}: ${headers[name]}`);
        }
    
        return {
          headers
        }
      });
    
      request.setEncoding("utf8");
      let data = "";
      request.on("data", (chunk) => { data += chunk; });
      request.write(JSON.stringify(body));
      request.on("end", () => {
        console.log(`\n${data}`);
        client.close();
      });
      request.end();
    };
    • 期望的结果**是使用Apple的生产APNS环境发送推送通知。解决此问题的最佳尝试是将开发URL替换为生产URL,这将返回"{" reason":"BadDeviceToken "}:status:400个APNS-识别号:"
    • 到目前为止的尝试次数...**以下是我正在使用的主机:
  • 生产="www.example.com"也尝试了"www.example.com"https://api.push.apple.com" also tried "https://api.push.apple.com:443"
  • Development ="www.example.com"我尝试过的其他方法:https://api.sandbox.push.apple.com" Other things I've tried:
  • 用证书代替令牌;我不确定我做的是否正确。如果你知道,请删除代码。
  • ChatGPT的解决方案:const apn = require('apn ');//证书文件的路径和密码短语(如果有)const cert = '/path/to/cert. pem';
常量密钥= '/路径/到/密钥. pem ';
const passphrase ='your_certificate_passphrase';//使用证书和密钥创建APN提供程序const provider = new APN.提供程序({cert:证书,密钥:密钥,密码:密码,生产:
true//对于开发环境设置为false});//创建通知负载const payload = new apn. payload({alert:"Hello World!",声音:"默认",标记:1});//发送通知给设备令牌const deviceToken ='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
const note =新的apn.通知();注:到期日=数学下限(www.example.com()/1000)+3600;注:有效载荷=有效载荷;注意.主题='com.示例.我的应用程序';
发送(注意,设备令牌)。然后(结果=〉{console. log(结果);}); note.expiry = Math.floor(Date.now() / 1000) + 3600; note.payload = payload; note.topic = 'com.example.myapp'; provider.send(note, deviceToken).then(result => { console.log(result); });

我不知道在哪里可以找到上面的密码,所以我只是删除了它。密钥,我在. pem文件中找到,只是剪切和粘贴它从关键的开始和结束,并取代了旧的.p8文件的文本。

  • 也尝试过,SO回答:如何将证书从开发状态切换到生产状态?
  • 也尝试过,SO回答:用于开发和生产的iOS推送通知设备令牌
  • 还尝试了iOS APNS开发[沙盒]与生产
  • 还尝试将授权文件中"APS环境"项下的环境从"开发"更改为"生产",然后生成新的设备令牌。
xxhby3vn

xxhby3vn1#

在转换APNS API/后端提供程序时,您需要如下构建提供程序...

const fs = require("fs");
  const apn = require('apn');

  // Create the APN provider with the certificate and key
  const key = fs.readFileSync(process.env.APNS_KEY, "utf8");
  const cert = fs.readFileSync(process.env.APNS_CERT, "utf8");

  const provider = new apn.Provider({
    token: {
      cert: cert,
      key: key,
      teamId: process.env.APNS_TEAM_ID,
      keyId: process.env.APNS_KEY_ID
    },
    production: true // set to false for development environment
  });

构建提供程序、证书和密钥外观

请注意,我使用的是来自开发者门户的证书和用于签名的密钥,它与开发令牌位于Apple开发者门户的同一部分(例如.p8文件)。这些文件(.pem和.p8)以“-----开始证书----“、“-----结束证书-----"、“-----开始私钥----“开始和结尾,“-----END PRIVATE KEY----"。您经常会在联机说明中看到“token”,它是您作为参数传递到Provider构造函数中的对象。该token包括证书和密钥,沿着您在代码中看到的其他字段。
接下来,我花了几天时间才弄明白。你不能通过将XCode中的授权文件更改为“生产”而不是“开发”来强制模拟器或侧加载创建生产设备令牌。你必须(因为没有推送通知,使其通过我的API到APNS到我的设备到我的侧载应用程序,而我得到的是“BadDeviceToken”)至少安装应用的TestFlight版本才能获得生产设备令牌。一旦你有了它,你可以将它传递给你的API,然后使用它向设备发送APN。

初始化提供程序选项

你也可以像上面那样初始化你的提供者,而不是“jwt”方法。我已经试过了,上面的方法似乎是最简单和干净的(代码较少)。
注意那些声称有一种方法可以确定这两个令牌之间的教程,其中包含“

const firstByte = parseInt(deviceToken.substr(0, 2), 16);

  // Successfully determines the aps environment
  const apsEnvironment = (firstByte & 0x80) ? 'production' : 'development';

通知内容和交付

下面是上面的代码片段...

const notification = new apn.Notification();

  notification.alert = {
    title: 'Hello World',
    body: 'This is a test notification'
  };

  notification.topic = process.env.APNS_TOPIC;

  console.log(`notification ${JSON.stringify(notification)}`)

  provider.send(notification, deviceToken).then((result) => {
    console.log(JSON.stringify(result));
  });

这似乎是自我感叹,并没有阻碍我。此外,如果你去定义通知,有一个有效负载属性,你可以定义为其他教程提到。
干杯!黑客快乐!

相关问题