AJAX发送XML请求始终触发错误回调的原因排查
这种情况确实挺闹心的——明明Network面板里看着请求发出去了,响应也回来了,可代码偏偏钻进error回调里不肯出来。结合你贴的代码,我梳理了几个最可能的原因,你可以挨个排查试试:
XML格式或转义错误
你构建请求XML的时候用了<这种HTML转义字符,但jQuery在发送数据时可能会再次转义,导致服务器收到的XML格式完全混乱。另外,你设置了dataType: "text/xml",jQuery会自动尝试把响应解析成XML文档,如果返回的XML有语法问题(比如未闭合标签、编码声明和实际内容不匹配),哪怕HTTP状态码是200,也会直接触发error回调。
建议你先把dataType改成text,在success里直接打印原始响应内容,看看是不是XML本身有问题。同时,构建XML的时候改用ES6模板字符串,可读性更高还不容易出错:var req = `<?xml version='1.0' encoding='utf-8'?> <API3G> <CompanyToken>TOKEN-TO-BE-PLACED-HERE</CompanyToken> <Request>createToken</Request> <!-- 其他XML内容 --> </API3G>`;跨域(CORS)限制
你的请求地址是https://secure1.sandbox.directpay.online,而页面是在localhost运行的,这肯定涉及跨域。哪怕Network显示请求发送成功,只要服务器没有返回正确的CORS响应头(比如Access-Control-Allow-Origin),浏览器就会拦截响应,不让JS代码访问,从而触发error回调。
你可以去Network面板的Response Headers里检查有没有CORS相关的头,如果没有,那你需要用后端代理来转发请求,或者联系服务提供商开启CORS支持。请求Content-Type未正确设置
你发送的是XML数据,但没有明确设置contentType,jQuery默认的contentType是application/x-www-form-urlencoded,这会让服务器误以为你发的是表单数据,无法正确解析XML,最后返回错误响应。
一定要加上这个配置:contentType: "text/xml; charset=utf-8",这样服务器才知道要按XML格式处理你的请求。
服务器返回非2xx状态码
jQuery的success回调只在HTTP状态码为2xx时触发,哪怕请求发出去了,如果服务器返回3xx(重定向)、4xx(客户端错误)或5xx(服务器错误),都会直接走error回调。你可以在error回调里打印xhr.status和xhr.responseText,看看服务器到底返回了什么:error: function(xhr, status, error) { console.log("状态码:", xhr.status); console.log("服务器返回内容:", xhr.responseText); console.log("错误信息:", error); }XML解析环节出错
你用了X2JS来解析XML,但如果jQuery在解析XML时就出问题(因为dataType: "text/xml"会让jQuery先把响应转换成XML文档),那还没到X2JS的环节就会触发error。所以先把dataType改成text,确认原始响应没问题后,再手动用X2JS解析,还能加个try-catch捕获解析错误:success: function(response) { console.log("原始响应:", response); try { var res = JSON.stringify(x2js.xml_str2json(response)); console.log(res); document.getElementById("response").innerHTML = res; } catch (err) { console.log("X2JS解析出错:", err); } }
给你一个修改后的完整代码示例,整合了上面的建议:
const endpoint = "https://secure1.sandbox.directpay.online/API/v6/"; $(document).ready(function() { $("#sendBtn").click(function() { var x2js = new X2JS(); // 用模板字符串构建XML,避免转义错误 var req = `<?xml version='1.0' encoding='utf-8'?> <API3G> <CompanyToken>TOKEN-TO-BE-PLACED-HERE</CompanyToken> <Request>createToken</Request> <Transaction> <PaymentAmount>450.00</PaymentAmount> <PaymentCurrency>USD</PaymentCurrency> <CompanyRef>49FKEOA</CompanyRef> <RedirectURL>https://secure1.sandbox.directpay.online/payv2.php?ID=TOKEN-HERE</RedirectURL> <BackURL>http://localhost/computicket_node_server/</BackURL> <CompanyRefUnique>0</CompanyRefUnique> <PTL>5</PTL> </Transaction> <Services> <Service> <ServiceType>5525</ServiceType> <ServiceDescription>Flight from Malawi to India</ServiceDescription> <ServiceDate>2013/12/20 19:00</ServiceDate> </Service> </Services> </API3G>`; $.ajax({ url: endpoint, type: "POST", data: req, contentType: "text/xml; charset=utf-8", // 明确设置Content-Type dataType: "text", // 先获取原始文本排查问题 success: function(response) { console.log("原始响应内容:", response); try { var res = JSON.stringify(x2js.xml_str2json(response)); console.log("解析后的JSON:", res); document.getElementById("response").innerHTML = res; } catch (parseError) { console.error("XML解析出错:", parseError); } }, error: function(xhr, status, error) { console.log("请求状态码:", xhr.status); console.log("错误信息:", error); console.log("服务器返回内容:", xhr.responseText); } }); }); });
内容的提问来源于stack exchange,提问作者CliffTheCoder

