我已经花了一个星期的时间,试图在MacOS上获得Safari推送通知。我已经按照此处列出的步骤进行操作:https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW24和此处:https://medium.com/@rossbulat/safari-push-notifications-complete-setup-ef57f19bbb89,实现了为zip包和日志记录终结点提供服务的终结点,但是我不断收到错误消息“推送包的签名验证失败”。 / p>
我正在使用nodejs创建zip包并签署清单文件。
执行此操作的代码:
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const child_process = require('child_process');
const rimraf = require('rimraf');
const archiver = require('archiver');
const websiteName = 'mywebsite.com';
const websiteFolder = 'mywebsite.com';
const websitePushID = 'web.com.mywebsite';
const allowedDomains = [
'https://www.mywebsite.nl',
'https://www.mywebsite.com'
];
const webServiceURL = 'https://api.mywebsite.com';
const urlFormatString = 'https://www.mywebsite.com/%@';
const authenticationToken = '3F2UyWU8VfJ6EHGZqd5TMteQ';
const certP12 = '../cert/certificate.p12';
const wwdrca = '../cert/AppleWWDRCA.pem';
const certPasswd = 'my password'; //p12 password
const raw_files = [
'website.json',
'icon.iconset/icon_16x16.png',
'icon.iconset/icon_16x16@2x.png',
'icon.iconset/icon_32x32.png',
'icon.iconset/icon_32x32@2x.png',
'icon.iconset/icon_128x128.png',
'icon.iconset/icon_128x128@2x.png'
];
const website = {
websiteName,
websitePushID,
allowedDomains,
urlFormatString,
authenticationToken,
webServiceURL
};
const manifest = {};
const createZip = () => {
return new Promise((resolve, reject) => {
const basePath = `${__dirname}/${websiteFolder}.pushpackage`;
console.log('website.json', `${basePath}/website.json`);
fs.writeFileSync(`${basePath}/website.json`, JSON.stringify(website));
console.log('manifest.json');
raw_files.forEach(file => {
const sha512 = crypto.createHash('sha512');
sha512.update(fs.readFileSync(`${basePath}/${file}`), 'binary');
manifest[file] = {
hashType: 'sha512',
hashValue: sha512.digest('hex')
};
});
fs.writeFileSync(`${basePath}/manifest.json`, JSON.stringify(manifest));
child_process.execSync(`openssl pkcs12 -in ${path.join(__dirname, certP12)} -nocerts -out private.pem -passin pass:${certPasswd} -passout pass:${certPasswd}`);
child_process.execSync(`openssl pkcs12 -in ${path.join(__dirname, certP12)} -clcerts -nokeys -out cert.pem -passin pass:${certPasswd}`);
child_process.execSync(`openssl smime -binary -sign -certfile ${path.join(__dirname, wwdrca)} -signer ${path.join(__dirname, '../cert', 'certificate.pem')} -inkey private.pem -in ${basePath}/manifest.json -out ${basePath}/signature -outform DER -passin pass:${certPasswd}`);
raw_files.push('manifest.json');
raw_files.push('signature');
if(fs.existsSync(`${basePath}.zip`)) {
fs.unlinkSync(`${basePath}.zip`);
}
const archive = archiver('zip');
const output = fs.createWriteStream(`${basePath}.zip`);
archive.pipe(output);
console.log('building Package');
raw_files.forEach(file => archive.append(fs.createReadStream(`${basePath}/${file}`), {name: file}));
archive.on('finish', () => {
console.log('finished');
return resolve();
});
console.log('finalize');
archive.finalize((err, bytes) => {
if(err) {
throw err;
}
console.log(`${bytes} total bytes`);
fs.unlink('cert.pem');
fs.unlink('private.pem');
rimraf.sync(basePath);
});
});
};
module.exports = createZip;
由于签名验证失败,因此问题可能出在此行:
child_process.execSync(`openssl smime -binary -sign -certfile ${path.join(__dirname, wwdrca)} -signer ${path.join(__dirname, '../cert', 'certificate.pem')} -inkey private.pem -in ${basePath}/manifest.json -out ${basePath}/signature -outform DER -passin pass:${certPasswd}`);
对于-signer
参数,我首先使用cert.pem
,它是在上一行中生成的:
child_process.execSync(`openssl pkcs12 -in ${path.join(__dirname, certP12)} -clcerts -nokeys -out cert.pem -passin pass:${certPasswd}`);
但是我认为这应该是我使用以下命令从certificate.pem
文件生成的certificate.p12
文件:
openssl pkcs12 -in certificate.p12 -out certificate.pem -nodes
但是,这不能解决问题。 我几次按照步骤获得正确的证书,我敢肯定我做得正确,但是我对证书专家的了解还很遥远,所以也许我在这里做错了。 也许有人可以验证上面的代码以查看其是否正确。
任何帮助都将不胜感激,因为我的头几乎没有任何头发可以拔出来……谢谢!