如何将PHP SoapClient代码转为Node.js node-soap实现?
解决node-soap连接SOAP API时出现
connect ECONNREFUSED ::1:80错误 1. 核心问题:连接目标错误
connect ECONNREFUSED ::1:80说明你的Node客户端在尝试连接本地80端口,而非实际的API服务地址。对照PHP代码,PHP通过location参数明确指定了API的请求地址,但你的Node代码遗漏了这个关键配置。
修改createSoapClient,在创建客户端时添加location选项,填入API的实际URL:
var client = await soap.createClientAsync(url, { location: "https://kt-ext-portwise.statenspersonadressregister.se/你的API具体路径", // 替换为真实API地址 // 其他配置... });
2. 修正TLS 1.2配置错误
你当前使用secureOptions: tls.SSL_OP_NO_TLSv1_2,这会禁用TLS 1.2,完全违背了API要求必须使用TLS 1.2的规则。正确配置应为强制启用TLS 1.2,禁用更低版本:
const tls = require('tls'); // 强制使用TLS 1.2,禁用不安全的TLS1.0/1.1 const secureOptions = tls.DEFAULT_SECURE_OPTIONS | tls.SSL_OP_NO_TLSv1 | tls.SSL_OP_NO_TLSv1_1;
3. 对齐PHP的证书配置逻辑
PHP中使用local_cert(包含证书+私钥的PEM文件)、cafile(CA证书)做双向验证,Node的ClientSSLSecurity参数顺序需注意,同时要开启CN匹配:
// 参数顺序:私钥路径 → 客户端证书路径 → CA证书路径 var wssec = new soap.ClientSSLSecurity( 'assets/private-key.pem', 'assets/Kommun_A.pem', // 对应PHP的local_cert 'assets/DigiCert.pem' // 对应PHP的cafile ); // 验证服务器CN,对应PHP的CN_match配置 wssec.options.checkServerIdentity = (hostname, cert) => { const expectedCN = 'kt-ext-portwise.statenspersonadressregister.se'; if (cert.subject.CN !== expectedCN) { return new Error(`服务器证书CN不匹配:预期${expectedCN},实际${cert.subject.CN}`); } };
不要设置rejectUnauthorized: false和strictSSL: false,这会关闭证书验证,不符合PHP里verify_peer: true的安全要求,应保持证书验证开启,确保CA证书文件正确。
4. 确保本地WSDL路径解析正确
如果WSDL是本地文件,建议使用file://前缀避免路径解析问题:
const path = require('path'); const wsdlPath = path.resolve(__dirname, './assets/personsok.wsdl'); var url = `file://${wsdlPath}`;
完整修正后的createSoapClient函数
import soap from 'soap'; import fs from 'fs'; import tls from 'tls'; import path from 'path'; export function createSoapClient() { return new Promise(async (resolve, reject) => { // 处理本地WSDL路径,添加file://前缀 const wsdlPath = path.resolve(__dirname, './assets/personsok.wsdl'); const url = `file://${wsdlPath}`; // 配置强制使用TLS 1.2 const secureOptions = tls.DEFAULT_SECURE_OPTIONS | tls.SSL_OP_NO_TLSv1 | tls.SSL_OP_NO_TLSv1_1; try { // 创建客户端并指定API实际地址 const client = await soap.createClientAsync(url, { location: "https://kt-ext-portwise.statenspersonadressregister.se/实际API路径", // 替换为真实地址 secureOptions: secureOptions, rejectUnauthorized: true // 保持证书验证开启 }); // 配置SSL安全参数 const wssec = new soap.ClientSSLSecurity( 'assets/private-key.pem', 'assets/Kommun_A.pem', 'assets/DigiCert.pem' ); // 验证服务器CN wssec.options.checkServerIdentity = (hostname, cert) => { const expectedCN = 'kt-ext-portwise.statenspersonadressregister.se'; if (cert.subject.CN !== expectedCN) { return new Error(`服务器证书CN不匹配:预期${expectedCN},实际${cert.subject.CN}`); } }; client.setSecurity(wssec); console.log("Created SOAP Client"); resolve(client); } catch (err) { reject(`创建SOAP客户端失败:${err.message}`); } }); }
额外排查建议
- 确认API地址是否正确,若服务器在内部网络,需检查代理配置
- 用
fs.accessSync验证证书文件是否可读、路径是否正确 - 开启node-soap调试模式:
soap.createClientAsync(url, { trace: true, debug: true }),查看请求详情辅助定位问题
内容的提问来源于stack exchange,提问作者Alfred Toscha
相关产品推荐
相关产品推荐

