调用Kazpost WSDL接口时XMLHttpRequest readyState=4但status=0问题求助
解决XMLHttpRequest请求Kazpost SOAP接口时status为0的问题
首先,你遇到的readyState=4但status=0的问题,绝大多数情况是浏览器同源策略(CORS)限制导致的,再加上你可能搞错了请求地址,这两个因素共同引发了失败。下面给你拆解问题和解决方案:
核心问题分析
- 跨域限制:浏览器不允许前端页面直接请求不同域名的接口(除非目标服务器配置了CORS响应头)。你请求的
http://rates.kazpost.kz和你的页面域名不属于同源,浏览器会拦截这个请求,最终返回status=0。 - 请求地址错误:你当前请求的是WSDL文档的地址(
postratesws.wsdl),但实际调用SOAP接口应该请求服务的端点地址——你需要打开这个WSDL文件,找到<soap:address location="..." />标签里的URL,那才是真正的接口调用地址。
解决方案
方案1:搭建后端代理(最可靠的解决方式)
前端直接跨域请求几乎绕不开浏览器的限制,所以推荐在你的后端搭建一个代理服务:
- 前端请求你自己的后端接口(同源,不会被拦截)
- 后端再去调用Kazpost的SOAP接口(后端不受浏览器同源策略限制)
- 后端把接口返回的结果转发给前端
举个简单的Node.js/Express代理示例(你可以根据自己的后端技术栈调整):
const express = require('express'); const request = require('request'); const app = express(); app.use(express.text({ type: 'text/xml' })); app.post('/proxy-kazpost-rate', (req, res) => { // 替换成WSDL里找到的实际SOAP端点地址 const kazpostEndpoint = 'http://rates.kazpost.kz/postratesprodv2/postratesws'; request.post({ url: kazpostEndpoint, body: req.body, headers: { 'Content-Type': 'text/xml' } }, (err, response, body) => { if (err) { res.status(500).send(err); return; } res.set('Content-Type', 'text/xml'); res.send(body); }); }); app.listen(3000, () => console.log('Proxy server running on port 3000'));
然后修改你的前端代码,把请求地址改成代理地址:
var xmlhttp = new XMLHttpRequest(); // 改成你的代理接口地址 xmlhttp.open('POST', 'http://localhost:3000/proxy-kazpost-rate', true); // 后面的SOAP请求体保持不变 var sr = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pos="http://webservices.kazpost.kz/postratesws">' + '<soapenv:Header/>' + '<soapenv:Body>' + '<pos:GetPostRateRequest>' + '<pos:GetPostRateInfo>' + '<pos:SndrCtg>1</pos:SndrCtg>' + '<pos:Product>P102</pos:Product>' + '<pos:MailCat>1</pos:MailCat>' + '<pos:SendMethod>2</pos:SendMethod>' + '<pos:Weight>750</pos:Weight>' + '<pos:Dimension>s</pos:Dimension>' + '<pos:Value>100</pos:Value>' + '<pos:From>050031</pos:From>' + '<pos:To>010001</pos:To>' + '<pos:ToCountry>au</pos:ToCountry>' + '</pos:GetPostRateInfo>' + '</pos:GetPostRateRequest>' + '</soapenv:Body>' + '</soapenv:Envelope>'; xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { if (xmlhttp.status == 200) { console.log('请求成功,响应内容:', xmlhttp.responseText); } else { console.error('请求失败,状态码:', xmlhttp.status, '状态信息:', xmlhttp.statusText); } } } xmlhttp.setRequestHeader('Content-Type', 'text/xml'); xmlhttp.send(sr);
方案2:检查并修正SOAP端点地址
先确认你请求的URL是否正确:打开http://rates.kazpost.kz/postratesprodv2/postratesws.wsdl,找到类似下面的标签:
<soap:address location="http://rates.kazpost.kz/postratesprodv2/postratesws"/>
把这个location里的URL作为你的请求地址,替换掉当前的.wsdl地址。不过即使地址正确,跨域问题仍然存在,所以还是需要结合代理方案。
调试建议
打开浏览器开发者工具的Network面板,查看这个请求的详细信息:
- 如果看到
CORS相关的报错,那就是跨域问题实锤了 - 如果看到
404错误,说明你请求的地址(WSDL文件)不是正确的接口端点
内容的提问来源于stack exchange,提问作者GoldenScrew
相关产品推荐
相关产品推荐

