通过 Jax-WS 调用 eBay API 时出现意外的 XML 标签错误

Unexpected XML tag error when calling eBay API via Jax-WS

我正在尝试通过 JAX-WS 使用 Ebay 交易 API。 (是的,我知道有一个用于交易 API 网络服务的 SDK,但我试图避免使用它,因为其他 Ebay API 没有 SDK。没有意义让我用 SDK 编写一半的程序)

https://go.developer.ebay.com/api-documentation

首先,我使用 wsimport 创建了 JAX-WS 存根,然后创建了 jar 文件。 我正在关注此文档:http://java.boot.by/ocewsd6-guide/ch06.html

我正在尝试调用 GetSessionID 函数。文档在这里: http://developer.ebay.com/Devzone/XML/docs/Reference/eBay/GetSessionID.html

我能走到这一步:
ebay.apis.eblbasecomponents.EBayAPIInterfaceService eais = 新 ebay.apis.eblbasecomponents.EBayAPIInterfaceService();

        ebay.apis.eblbasecomponents.EBayAPIInterface eport= eais.getEBayAPI();

        //here, need to build a request
        ebay.apis.eblbasecomponents.GetSessionIDRequestType gsr = new GetSessionIDRequestType();
        gsr.setRuName(runame);

        //http://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/twbs_cookiejaxws.html
        // Set up the Map that will contain the request headers.
        Map<String, Object> req_ctx = ((BindingProvider)eport).getRequestContext();
        req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://api.ebay.com/ws/api.dll");

//        req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://api.ebay.com/wsapi");

        Map<String, List<String>> headers = new HashMap<String, List<String>>();
        headers.put("runame", Collections.singletonList("BLAHBLAH"));
        headers.put("X-EBAY-API-COMPATIBILITY-LEVEL", Collections.singletonList("907"));
        headers.put("X-EBAY-API-DEV-NAME", Collections.singletonList("BLAHBLAH"));
        headers.put("X-EBAY-API-APP-NAME", Collections.singletonList("BLAHBLAH"));
        headers.put("X-EBAY-API-CERT-NAME", Collections.singletonList("BLAHBLAH"));
        headers.put("X-EBAY-API-CALL-NAME", Collections.singletonList("GetSessionID"));
        headers.put("X-EBAY-API-SITEID", Collections.singletonList("US"));
        headers.put("Content-Type", Collections.singletonList("text/xml"));


        req_ctx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);


        GetSessionIDResponseType gsResponse = eport.getSessionID(gsr);

但是,我得到以下错误。

  1. 谁能告诉我我做错了什么?

  2. 更好的是,任何人都可以生成示例代码来调用这个 API?

错误:

java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:363)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:303)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: com.sun.xml.internal.ws.protocol.soap.MessageCreationException: Couldn't create SOAP message due to exception: unexpected XML tag. expected: {http://schemas.xmlsoap.org/soap/envelope/}Envelope but found: {urn:ebay:apis:eBLBaseComponents}GetSessionIDResponse
    at com.sun.xml.internal.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:304)
    at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:268)
    at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:217)
    at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:130)
    at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:124)
    at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:1121)
    at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:1035)
    at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:1004)
    at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:862)
    at com.sun.xml.internal.ws.client.Stub.process(Stub.java:448)
    at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:178)
    at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93)
    at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:77)
    at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:147)
    at com.sun.proxy.$Proxy35.getSessionID(Unknown Source)
    at Ebluna.main(Ebluna.java:101)
    ... 11 more
Caused by: com.sun.xml.internal.ws.streaming.XMLStreamReaderException: unexpected XML tag. expected: {http://schemas.xmlsoap.org/soap/envelope/}Envelope but found: {urn:ebay:apis:eBLBaseComponents}GetSessionIDResponse
    at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.verifyTag(XMLStreamReaderUtil.java:261)
    at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:205)
    at com.oracle.webservices.internal.impl.encoding.StreamDecoderImpl.decode(StreamDecoderImpl.java:49)
    at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:234)
    at com.sun.xml.internal.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:151)
    at com.sun.xml.internal.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:299)
    ... 26 more
Exception running application Ebluna

caused-by 异常是一个很大的线索。因为您使用的是从 WSDL 创建的 JAX-WS 客户端,所以运行时期望 SOAP xml 响应具有 <Envelope> 的根 xml 元素,但得到的是 <GetSessionIDResponse> 作为 HTTP 响应中的根元素。

根据 eBay trading API docs, they have a plain xml-over-http endpoint and a SOAP-over-http endpoint url. Since you're using SOAP, you need to use only the SOAP endpoint URL; your code is actually specifying both endpoints (luckily last one wins and you're actually using the right one - but you don't need to set the endpoint twice): https://api.ebay.com/wsapi

我相信您可能会收到 non-SOAP 响应的原因可能是您传递的 HTTP headers。文档说这些仅适用于 non-SOAP 端点;但是您正在使用 SOAP 端点并传递它们。对于 SOAP 接口,您应该在端点 URL 上传递这些参数 as URL query string parameters

例如:

Example: Specifying Routing Information in the Request URL
// Define the endpoint (e.g., the Sandbox Gateway URI)      
String endpoint = "https://api.sandbox.ebay.com/wsapi";
// Define the query string parameters.
String queryString = "?callname=AddItem"
                                        + "&siteid=0"
                                        + "&appid=myappid"
                                        + "&version=349";
                                        + "&Routing=new";

String requestURL  = endpoint + queryString;
EBayAPIInterfaceServiceLocator  sl = new EBayAPIInterfaceServiceLocator();
EBayAPIInterface       privBinding = sl.geteBayAPI(new URL(requestURL));
((EBayAPISoapBindingStub)privBinding).setTimeout(60000);