生产环境用SignedDataVerifier验证苹果IAP收据时出现PEM错误
问题排查与解决方案
1. 核心错误:证书格式不匹配(error:0480006C:PEM routines::no start line)
这个错误是因为你读取的.cer证书是DER二进制格式,而SignedDataVerifier要求传入PEM文本格式的证书。两种解决方式:
提前转换证书格式
用OpenSSL命令把.cer转成PEM格式:openssl x509 -inform der -in AppleIncRootCertificate.cer -out AppleIncRootCertificate.pem对所有4个根证书执行该命令,之后代码里读取转换后的
.pem文件即可。代码内动态转换
借助Node.js的crypto模块将DER格式转为PEM:const crypto = require('crypto'); function derToPem(derBuffer) { return crypto.createPublicKey({ key: derBuffer, format: 'der', type: 'spki' }).export({ format: 'pem', type: 'spki' }); } const appleRootCAs = [ derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleIncRootCertificate.cer'))), derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleComputerRootCertificate.cer'))), derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleRootCA-G2.cer'))), derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleRootCA-G3.cer'))), ];
2. appAppleId格式错误
你当前用teamId+"."+bundleId拼接的格式完全错误。正确的appAppleId是App Store Connect中你的应用对应的数字ID(比如123456789),可以在应用详情页的「App信息」板块找到。
3. TestFlight环境配置错误
TestFlight测试构建的内购验证必须用沙盒环境,而非生产环境。修改环境配置:
const appleEnv = Environment.SANDBOX;
苹果官方明确规定:TestFlight应用使用沙盒环境做内购验证,生产环境仅适用于已上架App Store的正式版本。
4. enableOnlineChecks配置建议
enableOnlineChecks设为true是合理的,它会在线检查证书吊销状态,提升验证安全性。如果测试阶段遇到网络问题,可以临时设为false排查,但正式上线建议保持true。
修正后的关键代码片段
const issuerId = '6f1337a3-1234-4929-9ccd-774e8c02fa18'; const keyId = 'FG7N3NY68Y'; const bundleId = 'com.appname.app'; const teamId = '6JZPD4JMSJ'; // 替换为App Store Connect中应用的数字Apple ID const appAppleId = '123456789'; // TestFlight使用沙盒环境 const appleEnv = Environment.SANDBOX; const filePath = path.join(ROOT_FOLDER, `/keys/AppleApi_AuthKey_${keyId}.p8`); const privateKey = fs.readFileSync(filePath, 'utf8'); const client = new AppStoreServerAPIClient(privateKey, keyId, issuerId, bundleId, appleEnv); // 转换DER证书为PEM格式 const crypto = require('crypto'); function derToPem(derBuffer) { return crypto.createPublicKey({ key: derBuffer, format: 'der', type: 'spki' }).export({ format: 'pem', type: 'spki' }); } const appleRootCAs = [ derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleIncRootCertificate.cer'))), derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleComputerRootCertificate.cer'))), derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleRootCA-G2.cer'))), derToPem(fs.readFileSync(path.join(ROOT_FOLDER, '/keys/AppleRootCer/AppleRootCA-G3.cer'))), ]; const enableOnlineChecks = true; const verifier = new SignedDataVerifier(appleRootCAs, enableOnlineChecks, appleEnv, bundleId, appAppleId);
内容的提问来源于stack exchange,提问作者Guian
相关产品推荐
相关产品推荐

