Axios/Node-fetch调用支付接口报SSL EPROTO错误curl正常如何解决
Node.js调用Chapa支付接口报SSL unrecognized name错误解决
问题现象
- 基于Axios、node-fetch等Node.js生态HTTP客户端调用Chapa支付验证接口时,触发TLS协议错误,报错信息:
Error: write EPROTO 139867624232896:error:14094458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name:../deps/openssl/openssl/ssl/record/rec_layer_s3.c:1546:SSL alert number 112
- 相同请求头、相同参数用curl命令发起请求可正常返回,调用全程未使用任何代理
- 复现代码片段:
try { let result = await axios.get( "https://api.chapa.dev/v1/transaction/verify/" + req.query.tx_ref, { headers: { Authorization: "Bearer " + CHAPA_SECRET_KEY, }, } ); console.log("Result: " + result.data); //TODO: 存储交易验证结果 } catch (error) { console.log("something happened " + error); }
根因说明
报错对应的TLS告警码112为unrecognized_name,本质是TLS握手阶段的SNI(服务器名称指示)匹配失败:Chapa的API网关做了多域名TLS校验,部分Node.js版本的内置HTTPS模块在特定场景下不会自动正确传递SNI字段,导致网关无法识别请求对应的服务,直接在SSL层断开连接。
curl能正常请求是因为其默认TLS握手逻辑会强制携带和请求域名一致的SNI字段,符合网关校验规则。
可行解决方案
方案1:显式配置HTTPS Agent指定SNI(生产环境推荐)
手动创建HTTPS代理实例,强制指定SNI服务器名为接口域名,传入请求配置即可,无安全风险,Axios适配示例:
const https = require('https'); // 初始化自定义HTTPS代理,固定SNI值 const chapaApiAgent = new https.Agent({ servername: 'api.chapa.dev' }); try { let result = await axios.get( "https://api.chapa.dev/v1/transaction/verify/" + req.query.tx_ref, { headers: { Authorization: "Bearer " + CHAPA_SECRET_KEY, }, httpsAgent: chapaApiAgent // 注入自定义代理 } ); console.log("Result: " + result.data); //TODO: 存储交易验证结果 } catch (error) { console.log("something happened " + error); }
使用node-fetch时配置逻辑一致,在请求options中传入对应agent参数即可。
方案2:升级Node.js到稳定LTS版本
将Node.js升级到18.17.0及以上、20.x/22.x系列官方LTS版本,新版本内置的OpenSSL库修复了部分场景下SNI字段自动传递异常的问题,无需额外配置即可正常发起请求。
方案3:临时关闭TLS校验(仅本地调试可用)
如果仅做本地功能调试,可临时跳过TLS证书校验,该方案存在中间人攻击风险,禁止在生产环境使用:
// 仅本地调试阶段临时添加 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
内容的提问来源于stack exchange,提问作者Aman
相关产品推荐
相关产品推荐

