Twinfield - 服务器无法识别HTTP Header SOAPAction的值

时间:2014-11-21 19:56:34

标签: java web-services soap soap-client

我试图通过Java连接Twinfield logon api。我试过的代码是

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.MimeHeaders;
import java.io.ByteArrayInputStream;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class SoapTest {

    public static void main(String[] args) {
        try {
            SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = sfc.createConnection();

            MessageFactory mf = MessageFactory.newInstance();
            SOAPMessage sm = mf.createMessage();

            SOAPHeader sh = sm.getSOAPHeader();
            SOAPBody sb = sm.getSOAPBody();
            //sh.detachNode();
            QName logonName = new QName("http://www.twinfield.com", "Logon");
            SOAPBodyElement logonElement = sb.addBodyElement(logonName);

            QName userTag = new QName("user");
            SOAPElement user = logonElement.addChildElement(userTag);
            user.addTextNode("myuser");

            QName passwordTag = new QName("password");
            SOAPElement password = logonElement.addChildElement(passwordTag);
            password.addTextNode("mypassword");

            QName organisationTag = new QName("organisation");
            SOAPElement organisation = logonElement.addChildElement(organisationTag);
            organisation.addTextNode("myorg");

            System.out.println("\n Soap Request:\n");
            sm.writeTo(System.out);
            System.out.println();

            URL endpoint = new URL("https://login.twinfield.com/webservices/session.asmx");
            SOAPMessage response = connection.call(sm, endpoint);

            connection.close();

            //System.out.println(response.getContentDescription());
            //System.out.println("--------------------------");

            // Reading response
            printSOAPResponse(response);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        Source sourceContent = soapResponse.getSOAPPart().getContent();
        System.out.print("\nResponse SOAP Message = ");
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
    }   
}

似乎一切都是正确的,但我经常收到回复<faultstring>Server did not recognize the value of HTTP Header SOAPAction: .</faultstring>。以上程序的完整输出如下:

java SoapTest

 Soap Request:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <Logon xmlns="http://www.twinfield.com">
            <user>NLG001136</user>
            <password>qura976yj</password>
            <organisation>TWF-SAAS</organisation>
        </Logon>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Response SOAP Message = 
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Client</faultcode>
            <faultstring>Server did not recognize the value of HTTP Header SOAPAction: .</faultstring>
            <detail/>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

相同的请求/凭据在Soapclient.com上正常运行。有人可以指出我的程序出错了吗?

2 个答案:

答案 0 :(得分:2)

由于故障代码是客户端,因此您发送的soap消息导致问题。尝试使用SOAP UI传递相同内容,我尝试将WSDL导入到我的SOAP UI中,但是我收到了错误...

加载[https://login.twinfield.com/webservices/session.asmx?wsdl]时出错:org.apache.xmlbeans.XmlException:org.apache.xmlbeans.XmlException:错误:未关闭标记

由于Web服务已经被文件/文字包装,只需尝试使用wsimport创建客户端代码,您就可以获得所有需要的文件,并且可以轻松发送相同的请求。

如果您只对SAAJ方式感兴趣,那么我会尝试传递通过SOAP UI创建的消息。

希望这会有所帮助。

答案 1 :(得分:0)

最好使用Twinfield建议使用Twinfield Openid oAuth进行身份验证。要进行初始连接,请检查以下链接 https://stackoverflow.com/a/54652064

一旦您完成了初始连接设置并具有访问令牌,就可以继续获取公司列表。将Twinfield Web服务与访问令牌结合使用时,有必要在请求标头中提供公司ID或公司代码。 首先使用https://accounting.twinfield.com/webservices/processxml.asmx?wsdl

生成Java代码(twinfield的存根)

您可以使用以下代码来请求获取公司列表

package example;

import com.user.defined.package.twinfield.Header;
import com.user.defined.package.twinfield.ObjectFactory;
import com.user.defined.package.twinfield.ProcessXml;
import com.user.defined.package.twinfield.ProcessXmlSoap;
import com.sun.xml.internal.ws.developer.WSBindingProvider;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.soap.SOAPException;


public class HelloWorldClient {
 public static void main(String[] argv) throws JAXBException, SOAPException {


     ProcessXml processXmlService = new ProcessXml();
     ProcessXmlSoap processXmlSoap = processXmlService.getProcessXmlSoap();


     WSBindingProvider bp = (WSBindingProvider)processXmlSoap;

     JAXBContext jaxbContext = JAXBContext.newInstance(Header.class);
     Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);


     ObjectFactory objectFactory = new ObjectFactory();
     Header header = new Header();
     //active access token
     header.setAccessToken("95cd6bb91a59751....................");

     JAXBElement<Header> jaxbElement = objectFactory.createHeader(header);

     //Just to check the soap header 
     jaxbMarshaller.marshal(jaxbElement, System.out);

     //Set it to the bindingprovider
     bp.setOutboundHeaders(
             jaxbElement
     );


     String xmlRequest = "<list><type>offices</type></list>";
     System.out.println(processXmlSoap.processXmlString(xmlRequest));
  }
}