由于昨天和今天关于 WebService 实施的文档很差,我用尽了我的资源来调查我收到的错误,并假设同一个 DIAN(哥伦比亚的税务实体)没有接听电话(我被挂断了) 2 小时,一无所获……)更不用说电子邮件了,因为我在这里提出了一个问题,即是否有人可以帮助我,并且以同样的方式帮助处于相同情况的任何程序员。
提交发票时,我收到一条错误消息,指出“ JBWEB000120:客户端发送的请求在语法上不正确”。
我通过了完整的请求和响应:
POST /habilitacion/B2BIntegrationEngine/FacturaElectronica HTTP/1.0
Host: facturaelectronica.dian.gov.co
User-Agent: NuSOAP/0.9.5 (1.123)
Content-Type: text/xml; charset=UTF-8
SOAPAction: ""
Content-Length: 28319
<soap-env:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rep="http://www.dian.gov.co/servicios/facturaelectronica/ReportarFactura" xmlns:ns2323="http://tempuri.org">
<soap-env:header>
<wsse:security soapenv:mustunderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:usernametoken wsu:id="UsernameToken-2">
<wsse:username>d8xxx-exxx-4xxx-axxx-aaxxxx</wsse:username>
<wsse:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile1.0#PasswordText">a8bxxxxHash265xxxxxx99</wsse:password>
<wsse:nonce encodingtype="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security1.0#Base64Binary">bW9uxxxxxxxxxxxxxxUyNg==</wsse:nonce>
<wsu:created>2019-01-23T16:08:39-06:00</wsu:created>
</wsse:usernametoken>
</wsse:security>
</soap-env:header>
<soap-env:body>
<rep:enviofacturaelectronicapeticion>
<rep:nit>700xxxx</rep:nit>
<rep:invoicenumber>980000000</rep:invoicenumber>
<rep:issuedate>2019-01-23T16:08:39-06:00</rep:issuedate>
<rep:document>UEsDBBQA.....AuMS4yNzA3</rep:document>
</rep:enviofacturaelectronicapeticion>
</soap-env:body>
</soap-env:envelope>
和回应:
<title>JBoss Web/7.4.8.Final-redhat-4 - JBWEB000064: Error report</title>
<h1>JBWEB000065: HTTP Status 400 - </h1>
<p><b>JBWEB000309: type</b> JBWEB000067: Status report</p>
<p><b>JBWEB000068: message</b> <u></u></p>
<p><b>JBWEB000069: description</b> <u>JBWEB000120: The request sent by the client was syntactically incorrect.</u></p>
---- 2019/01/30 15:38 编辑。我对 NuSOAP 库进行了一些更改,因为在发送信息时它会将所有内容都传递为小写字母 (strtolower()),因此我删除了在包含发送的所有内容中使用 strtolower() 函数,现在错误发生了变化,我他说:
HTTP/1.0 302 找到位置: https ://facturaelectronica.dian.gov.co/habilitacion/B2BIntegrationEngine/FacturaElectronica 服务器:BigIP 连接:关闭内容长度:0
问题仍然存在:(....
---- 编辑于 2019 年 1 月 31 日,13:15。在尝试使用 SOAPUI 之后,我意识到主要问题是 NuSOAP 库,因此由于我在这方面浪费了时间,并考虑通过将框架放在一起来验证是否存在问题,从而在 Socket 中编写代码似乎更可行DIAN 的 WebService 我选择了手工组装。
我对它进行了编码,只是意识到出于某种未知原因,NuSOAP 做了其他一些事情,这些事情会引发开头提到的错误。现在我正在与 DIAN 交谈,因为我正在按照 WebService 的要求手动发送帧,并且它一直给我错误:
客户端安全令牌无法验证或授权;嵌套异常是 org.apache.ws.security.WSSecurityException:无法对安全令牌进行身份验证或授权
到目前为止,我手动测试的代码是:
<?php
public function createXML() {
# crea el XML SOAP
}
public funciton getXML() {
# retorna el xml con $xml->saveXML();
}
public function sendToDIAN($wsUrl) {
$this->createXML();
$s= curl_init();
curl_setopt($s, CURLOPT_URL, $wsUrl);
curl_setopt($s, CURLOPT_HTTPHEADER, array("User-Agent: moneyBox", "Content-Type: text/xml; charset=UTF-8", "SOAPAction:", "Content-Length: ". strlen($this->getXML())) );
curl_setopt($s, CURLOPT_HEADER, 1 );
curl_setopt($s, CURLOPT_POST, 1);
curl_setopt($s, CURLOPT_POSTFIELDS, $this->getXML());
curl_setopt($s, CURLOPT_RETURNTRANSFER, true);
curl_setopt($s, CURLOPT_VERBOSE, TRUE);
curl_setopt($s, CURLINFO_HEADER_OUT, true);
$resp= curl_exec($s);
$rq= curl_getinfo($s);
echo "<br>WS: ". $wsUrl;
echo "<br>XML:<br>";
print_r($this->getXML());
echo "<br>Request:<br>";
print_r($rq["request_header"]);
echo "<br><br>Response:<br>";
print_r($resp);
?>
请求是:
POST /habilitacion/B2BIntegrationEngine/FacturaElectronica/facturaElectronica.wsdl HTTP/1.1
Host: facturaelectronica.dian.gov.co
Accept: */*
User-Agent: PHP
Content-Type: text/xml; charset=UTF-8
Content-Length: 28198
Expect: 100-continue
<!--?xml version="1.0" encoding="UTF-8"?-->
<soapenv:envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rep="http://www.dian.gov.co/servicios/facturaelectronica/ReportarFactura">
<soapenv:header>
<wsse:security soapenv:mustunderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:usernametoken wsu:id="UsernameToken-2">
<wsse:username>d8xxx-exxx-4xx0-axx2-aa4xxxxxda</wsse:username>
<wsse:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile1.0#PasswordText">2fb7a2xxxxxxxxe6de4a</wsse:password>
<wsse:nonce encodingtype="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security1.0#Base64Binary">bW9xxxxxMTU1MA==</wsse:nonce>
<wsu:created>2019-01-31T14:05:50.000Z</wsu:created>
</wsse:usernametoken>
</wsse:security>
</soapenv:header>
<soapenv:body>
<rep:enviofacturaelectronicapeticion>
<rep:nit>700xxxx7</rep:nit>
<rep:invoicenumber>980000000</rep:invoicenumber>
<rep:issuedate>2019-01-31T14:05:50</rep:issuedate>
<rep:document>UEsDBB....jEuMjcwNw==</rep:document>
</rep:enviofacturaelectronicapeticion>
</soapenv:body>
</soapenv:envelope>
回应是:
HTTP/1.1 100 Continue
HTTP/1.1 500 Internal Server Error
Date: Thu, 31 Jan 2019 19:05:51 GMT
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Content-Length: 443
X-Cnection: close
Set-Cookie: TS0133d910=01ca0e1ef6f0097a1348704194309a4e9b294fed9c0bcca644e4ae8558c221f7f76b430cee909654460964cd09e1ac5affe8cd8d04; Path=/
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:header></soap-env:header>
<soap-env:body>
<soap-env:fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xml:lang="en">The security token could not be authenticated or authorized; nested exception is org.apache.ws.security.WSSecurityException: The security token could not be authenticated or authorized</faultstring>
</soap-env:fault>
</soap-env:body>
</soap-env:envelope>
经过最初发布的几个版本,最终解决方案是为了符合 DIAN 税务实体对 SOAP 请求“非常个性化”的组装的要求,我选择不使用 NuSOAP 库或 SOAPClient(),因为附加到标签上的任何不同或附加值都会向我抛出错误消息,而没有具体描述它们的解决方案,并且在调试和解决方案上的时间投入耽误了我很多时间,为此我不得不将 XML 放在一起使用DOMDocument在“手册”中请求并通过 Socket (cURL) 建立连接。
另一个需要注意的重要提示是,在“手动”建立 SOAP 连接后,该错误更“易于访问”,因为它提到了“身份验证错误”,并且对于这种特殊情况,在用尽以下选项后:验证软件 ID、SOAP Url 和密码都正确,我不得不选择从 DIAN 门户中删除软件 ID并重新生成它,这解决了 Authentication Error部分。这可能是由于 DIAN 系统的变化影响了测试模式下的软件 ID ,但这是第二种解决方案。
下面是我最终为手册部分生成的代码的一个想法:
请求: