使用Firebase Functions集成Apple Pay时请求失败的排查与解决
使用Firebase Functions作为后端、Firebase Hosting托管网站,集成Apple Pay JS API时,后端调用Apple服务器获取支付会话失败。核心流程为:客户端启动支付会话后调用后端接口,后端携带商户身份证书请求Apple服务器。
后端核心代码
const { validationUrl } = req.body const axiosInstance = axios.create({ httpsAgent: new https.Agent({ cert: fs.readFileSync(`${__dirname}/merchantIdentity.crt.pem`), key: fs.readFileSync(`${__dirname}/merchantIdentity.key.pem`), rejectUnauthorized: false }) }) const appleUrl = `https://${validationUrl}/paymentSession` const validateMerchantData = { merchantIdentifier: <my merchant id>, displayName: "Mercado", initiative: "web", initiativeContext: process.env.CLIENT_URL.replace("https://", "") } const appleRes = await axiosInstance.post(appleUrl, validateMerchantData)
报错信息
Error: getaddrinfo EAI_AGAIN https at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:71:26) at GetAddrInfoReqWrap.callbackTrampoline (node:internal/async_hooks:130:17)
已完成托管域名的Apple Pay验证,但Firebase Functions域名无法配置.well-known验证文件,目前通过Firebase Hosting重定向指向Apple Pay相关的Functions接口。需明确错误原因及解决方法,不考虑第三方支付方案。
错误根源
getaddrinfo EAI_AGAIN https 是DNS解析失败错误,直接原因是URL构建格式错误:
Apple返回的validationUrl本身已包含完整HTTPS前缀(例如https://apple-pay-gateway.apple.com/paymentservices/startSession),代码中手动添加https://后,最终URL变为https://https://apple-pay-gateway.apple.com/...,DNS将无效的https当作域名解析,导致失败。
修复步骤
修正Apple请求URL
直接使用validationUrl拼接路径,无需额外添加HTTPS前缀:const appleUrl = `${validationUrl}/paymentSession`确认域名验证范围
Apple Pay要求验证的是展示Apple Pay按钮的前端域名(即Firebase Hosting托管域名),与后端Functions域名无关:- 你已完成托管域名验证,此操作正确,无需验证Functions域名。
- 确保
initiativeContext值为已验证的托管域名(不带https://),当前代码中process.env.CLIENT_URL.replace("https://", "")的处理逻辑是正确的,需确认该环境变量指向托管域名而非Functions域名。
优化HTTPS Agent配置
移除rejectUnauthorized: false,该设置会关闭SSL证书验证,存在安全风险。Apple服务器证书为可信证书,只要商户证书、密钥有效,无需关闭验证。若后续出现证书错误,需检查:- 证书文件路径是否正确(Firebase Functions部署时,确保
merchantIdentity.crt.pem和merchantIdentity.key.pem已打包到部署包中) - 商户证书是否与
merchantIdentifier对应且在有效期内
- 证书文件路径是否正确(Firebase Functions部署时,确保
额外检查项
- 确认Firebase Functions网络可访问Apple支付网关(
apple-pay-gateway.apple.com),默认公网访问权限正常,无需额外配置。
内容的提问来源于stack exchange,提问作者mef27

