如何将带有 SOAP 正文的 CFHTTP 请求转换为 CFINVOKE 请求
How to convert a CFHTTP request with SOAP body in to a CFINVOKE request
我有一个 ColdFusion 11 站点,需要使用 SOAP 请求与支付处理器进行通信。我已经让它可以很好地处理 CFHTTP 请求,但是 return 值(在 SOAP 消息中传递)有点难以处理。
为了寻找更好的东西,我遇到了 CFINVOKE 和 webservice 属性。看来我正确地调用了 webservice 方法,但我认为我传递给服务的数据格式不正确。
这是有效的 SOAP/CFHTTP 请求(“...”替换了敏感的实施细节):
<!--- build SOAP data --->
<cfsavecontent variable="soapBody">
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<PreparePaymentv2 xmlns="https://common.checkout.cdc.nicusa.com">
<request xmlns:a="http://schemas.datacontract.org/2004/07/Common.Payment.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:STATECD>...</a:STATECD>
<a:HASHVALUE i:nil="true"/>
<a:AMOUNT i:nil="true"/>
<a:CID i:nil="true"/>
<a:SERVICECODE>...</a:SERVICECODE>
<a:UNIQUETRANSID>...</a:UNIQUETRANSID>
<a:DESCRIPTION>...</a:DESCRIPTION>
<a:LOCALREFID>...</a:LOCALREFID>
<a:MERCHANTID>...</a:MERCHANTID>
<a:MERCHANTKEY>...</a:MERCHANTKEY>
<a:PAYTYPE i:nil="true"/>
<a:NAME>...</a:NAME>
<a:COMPANYNAME i:nil="true"/>
<a:COUNTRY>...</a:COUNTRY>
<a:FAX i:nil="true"/>
<a:ADDRESS1 >...</a:ADDRESS1>
<a:ADDRESS2 i:nil="true"/>
<a:CITY>...</a:CITY>
<a:STATE>...</a:STATE>
<a:ZIP>...</a:ZIP>
<a:PHONE>...</a:PHONE>
<a:EMAIL>...</a:EMAIL>
<a:EMAIL1 i:nil="true"/>
<a:EMAIL2 i:nil="true"/>
<a:EMAIL3 i:nil="true"/>
<a:HREFSUCCESS>...</a:HREFSUCCESS>
<a:HREFFAILURE>...</a:HREFFAILURE>
<a:HREFDUPLICATE>...</a:HREFDUPLICATE>
<a:HREFCANCEL>...</a:HREFCANCEL>
<a:ORDERATTRIBUTES i:nil="true"/>
<a:LINEITEMS>
<a:LINEITEM>
<a:ITEM_ID>...</a:ITEM_ID
<a:SKU>...</a:SKU>
<a:DESCRIPTION>...</a:DESCRIPTION>
<a:UNIT_PRICE>...</a:UNIT_PRICE>
<a:QUANTITY>....</a:QUANTITY>
<a:ATTRIBUTES/>
</a:LINEITEM>
</a:LINEITEMS>
<a:ALTNAME i:nil="true"/>
<a:ALTADDRESS1 i:nil="true"/>
<a:ALTADDRESS2 i:nil="true"/>
<a:ALTCITY i:nil="true"/>
<a:ALTSTATE i:nil="true"/>
<a:ALTZIP i:nil="true"/>
<a:ALTCOUNTRY i:nil="true"/>
</request>
</PreparePaymentv2>
</s:Body>
</s:Envelope>
</cfsavecontent>
<!--- submit info to SOAP endpoint --->
<cfhttp url="https://stageccp.dev.cdc.nicusa.com/CommonCheckout/CCPWebService/ServiceWeb.svc" method="post" result="httpResponse">
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="https://common.checkout.cdc.nicusa.com/IServiceWeb/PreparePaymentv2">
<cfhttpparam type="header" name="content-length" value="#len(soapBody)#">
<cfhttpparam type="header" name="charset" value="utf-8">
<cfhttpparam type="header" name="Accept-Encoding" value="*">
<cfhttpparam type="Header" name="TE" value="deflate;q=0">
<cfhttpparam type="xml" value="#soapBody#">
</cfhttp>
这是我要开始工作的 CreateObject / CFINVOKE 请求:
<cfscript>
nullValue = "";
args = {
STATECD = ...,
HASHVALUE = nullValue,
AMOUNT = nullValue,
CID = nullValue,
SERVICECODE = ...,
UNIQUETRANSID = ...,
DESCRIPTION = ...,
LOCALREFID = ...,
MERCHANTID = ...,
MERCHANTKEY = ...,
PAYTYPE = nullValue,
NAME = ...,
COMPANYNAME = nullValue,
COUNTRY = ...,
FAX = nullValue,
ADDRESS1 = ...,
ADDRESS2 = ...,
CITY = ...,
STATE = ...,
ZIP = ...,
PHONE = ...,
EMAIL = ...,
EMAIL1 = nullValue,
EMAIL2 = nullValue,
EMAIL3 = nullValue,
HREFSUCCESS = ...,
HREFFAILURE = ...,
HREFDUPLICATE = ...,
HREFCANCEL = ...,
ORDERATTRIBUTES = nullValue,
LINEITEMS = [
{
ITEM_ID = ...,
SKU = ...,
DESCRIPTION = ...,
UNIT_PRICE = ...,
QUANTITY = ...,
ATTRIBUTES = nullValue
}
],
ALTNAME = nullValue,
ALTADDRESS1 = nullValue,
ALTADDRESS2 = nullValue,
ALTCITY = nullValue,
ALTSTATE = nullValue,
ALTZIP = nullValue,
ALTCOUNTRY = nullValue
};
ws = CreateObject("webservice","https://stageccp.dev.cdc.nicusa.com/CCPWebService/ServiceWeb.wsdl");
ws.PreparePaymentv2(args);
response = getSOAPResponse(ws);
</cfscript>
<cfinvoke webservice="https://stageccp.dev.cdc.nicusa.com/CCPWebService/ServiceWeb.wsdl" method="PreparePaymentv2" request="#args#" returnvariable="response">
这两种策略return错误信息:
Cannot perform web service invocation PreparePaymentv2.
查看详细信息会发现一个扩展的堆栈跟踪,我认为它来自远程服务器,在跟踪顶部附近包含以下消息:
Object reference not set to an instance of an object.
编辑:完整错误详情如下:
The fault returned when invoking the web service operation is: org.apache.axis2.AxisFault: Object reference not set to an instance of an object. at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:531
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:375
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:421
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165
at com.nicusa.cdc.checkout.common.ServiceWebStub.preparePaymentv2(ServiceWebStub.java:217
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source
at java.lang.reflect.Method.invoke(Unknown Source
at coldfusion.xml.rpc.Axis2ServiceProxy.getResult(Axis2ServiceProxy.java:112
at coldfusion.xml.rpc.ServiceProxy.invokeImpl(ServiceProx...
以及完整的堆栈跟踪:
coldfusion.xml.rpc.ServiceProxy$ServiceInvocationException: Cannot perform web service invocation PreparePaymentv2. at coldfusion.xml.rpc.Axis2ServiceProxy.getResult(Axis2ServiceProxy.java:122
at coldfusion.xml.rpc.ServiceProxy.invokeImpl(ServiceProxy.java:469
at coldfusion.xml.rpc.ServiceProxy.invoke(ServiceProxy.java:413
at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2489
at cfpayport_redirect2ek2648755446._factor4(C:\websites\preceptorStudent\test\payport_redirect.k2:312
at cfpayport_redirect2ek2648755446._factor5(C:\websites\preceptorStudent\test\payport_redirect.k2:120
at cfpayport_redirect2ek2648755446.runPage(C:\websites\preceptorStudent\test\payport_redirect.k2:1
at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:247
at coldfusion.tagext.lang.IncludeTag.handlePageInvoke(IncludeTag.java:736
at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:572
at coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65
at coldfusion.filter.IpFilter.invoke(IpFilter.java:45
at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:474
at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:42
at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40
at coldfusion.filter.PathFilter.invoke(PathFilter.java:153
at coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:30
at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:94
at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28
at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38
at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:58
at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38
at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22
at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62
at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:151
at coldfusion.CfmServlet.service(CfmServlet.java:219
at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208
at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42
at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:458
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:196
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61
at java.lang.Thread.run(Unknown Source)
我最好的猜测是这与传入的数据有关。我还尝试省略 args 中设置为 nullValue 的任何参数。这会导致相同的错误消息。我意识到为 nullValue 使用空字符串并不是最佳选择;我还没有找到 ColdFusion 11 的更好替代品。
the return value (delivered in a SOAP message) is a bit difficult to work with.
您是否遇到了具体问题?通常您只需将响应解析为 XML 并使用结构符号来访问所需的节点:
<cfset root = xmlParse(httpResponse.fileContent)>
<cfdump var="#root#" label="HttpResponse">
<cfoutput>FaultCode = #root.Envelope.Body.Fault.FaultCode.xmlText#</cfoutput>
通常这比使用 createObject("webservice") 更容易。您已经遇到了最大的问题,即排除 Web 服务错误可能是一个痛苦的过程;-)。错误消息往往含糊不清,最常见的是 "Web service operation SomeMethod with parameters {...some params...} cannot be found."。不是特别有用。它只是说参数有问题,但没有提供任何关于哪个参数、有什么问题或如何修复它的线索。
当然,您通常可以让事情正常进行……最终。但是,如果它是一个复杂的 Web 服务,那么并不总是值得花费时间和精力,这就是为什么经常推荐使用 cfhttp 的原因。
Looking at the details reveals an extended stack trace, which I reason is from the remote server, containing this message near the top of the trace:
Cannot perform web service invocation PreparePaymentv2.
无论如何,如果您还想尝试 cfinvoke,参数至少存在三个问题:
并非所有元素都是字符串。因此,当空字符串无法转换为正确的 type
时,使用 nullValue = "" 会导致错误。 ORDERATTRIBUTES
就是这样。由于它是可选的,如果您不想为该键传递值,只需将其从 args
结构中完全省略即可。
LINEITEMS
不是数组。它是一个 结构 ,包含一个名为 "lineitem" 的键,它是一个数组。所以这个值应该这样构造:
LINEITEMS.LINEITEM = [ {... lineitem data ... } ]
ORDERATTRIBUTES
也是如此。它是一个包含名为 "field" 的键的结构,这是一个结构数组:
ORDERATTRIBUTES.FIELD = [ {...field data ... } ]
如果您有兴趣了解更多有关 Web 服务内部工作方式的信息,CF 的功能是基于 Axis which uses a tool called wsdl2java 将 WSDL 转换为 java 类。通过保存和查看它生成的文件,您可以发现很多关于参数应该如何构建的信息。这就是我如何弄清楚上面的问题。保存的文件将位于 cfusion/stubs
子目录中。
// Only need to do this once. DON'T use in Prod as it's very time consuming
ws = CreateObject("webservice","https://example.com/ServiceWeb.wsdl"
, {saveJava=true, refreshWSDL=true});
我有一个 ColdFusion 11 站点,需要使用 SOAP 请求与支付处理器进行通信。我已经让它可以很好地处理 CFHTTP 请求,但是 return 值(在 SOAP 消息中传递)有点难以处理。
为了寻找更好的东西,我遇到了 CFINVOKE 和 webservice 属性。看来我正确地调用了 webservice 方法,但我认为我传递给服务的数据格式不正确。
这是有效的 SOAP/CFHTTP 请求(“...”替换了敏感的实施细节):
<!--- build SOAP data --->
<cfsavecontent variable="soapBody">
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<PreparePaymentv2 xmlns="https://common.checkout.cdc.nicusa.com">
<request xmlns:a="http://schemas.datacontract.org/2004/07/Common.Payment.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:STATECD>...</a:STATECD>
<a:HASHVALUE i:nil="true"/>
<a:AMOUNT i:nil="true"/>
<a:CID i:nil="true"/>
<a:SERVICECODE>...</a:SERVICECODE>
<a:UNIQUETRANSID>...</a:UNIQUETRANSID>
<a:DESCRIPTION>...</a:DESCRIPTION>
<a:LOCALREFID>...</a:LOCALREFID>
<a:MERCHANTID>...</a:MERCHANTID>
<a:MERCHANTKEY>...</a:MERCHANTKEY>
<a:PAYTYPE i:nil="true"/>
<a:NAME>...</a:NAME>
<a:COMPANYNAME i:nil="true"/>
<a:COUNTRY>...</a:COUNTRY>
<a:FAX i:nil="true"/>
<a:ADDRESS1 >...</a:ADDRESS1>
<a:ADDRESS2 i:nil="true"/>
<a:CITY>...</a:CITY>
<a:STATE>...</a:STATE>
<a:ZIP>...</a:ZIP>
<a:PHONE>...</a:PHONE>
<a:EMAIL>...</a:EMAIL>
<a:EMAIL1 i:nil="true"/>
<a:EMAIL2 i:nil="true"/>
<a:EMAIL3 i:nil="true"/>
<a:HREFSUCCESS>...</a:HREFSUCCESS>
<a:HREFFAILURE>...</a:HREFFAILURE>
<a:HREFDUPLICATE>...</a:HREFDUPLICATE>
<a:HREFCANCEL>...</a:HREFCANCEL>
<a:ORDERATTRIBUTES i:nil="true"/>
<a:LINEITEMS>
<a:LINEITEM>
<a:ITEM_ID>...</a:ITEM_ID
<a:SKU>...</a:SKU>
<a:DESCRIPTION>...</a:DESCRIPTION>
<a:UNIT_PRICE>...</a:UNIT_PRICE>
<a:QUANTITY>....</a:QUANTITY>
<a:ATTRIBUTES/>
</a:LINEITEM>
</a:LINEITEMS>
<a:ALTNAME i:nil="true"/>
<a:ALTADDRESS1 i:nil="true"/>
<a:ALTADDRESS2 i:nil="true"/>
<a:ALTCITY i:nil="true"/>
<a:ALTSTATE i:nil="true"/>
<a:ALTZIP i:nil="true"/>
<a:ALTCOUNTRY i:nil="true"/>
</request>
</PreparePaymentv2>
</s:Body>
</s:Envelope>
</cfsavecontent>
<!--- submit info to SOAP endpoint --->
<cfhttp url="https://stageccp.dev.cdc.nicusa.com/CommonCheckout/CCPWebService/ServiceWeb.svc" method="post" result="httpResponse">
<cfhttpparam type="header" name="content-type" value="text/xml">
<cfhttpparam type="header" name="SOAPAction" value="https://common.checkout.cdc.nicusa.com/IServiceWeb/PreparePaymentv2">
<cfhttpparam type="header" name="content-length" value="#len(soapBody)#">
<cfhttpparam type="header" name="charset" value="utf-8">
<cfhttpparam type="header" name="Accept-Encoding" value="*">
<cfhttpparam type="Header" name="TE" value="deflate;q=0">
<cfhttpparam type="xml" value="#soapBody#">
</cfhttp>
这是我要开始工作的 CreateObject / CFINVOKE 请求:
<cfscript>
nullValue = "";
args = {
STATECD = ...,
HASHVALUE = nullValue,
AMOUNT = nullValue,
CID = nullValue,
SERVICECODE = ...,
UNIQUETRANSID = ...,
DESCRIPTION = ...,
LOCALREFID = ...,
MERCHANTID = ...,
MERCHANTKEY = ...,
PAYTYPE = nullValue,
NAME = ...,
COMPANYNAME = nullValue,
COUNTRY = ...,
FAX = nullValue,
ADDRESS1 = ...,
ADDRESS2 = ...,
CITY = ...,
STATE = ...,
ZIP = ...,
PHONE = ...,
EMAIL = ...,
EMAIL1 = nullValue,
EMAIL2 = nullValue,
EMAIL3 = nullValue,
HREFSUCCESS = ...,
HREFFAILURE = ...,
HREFDUPLICATE = ...,
HREFCANCEL = ...,
ORDERATTRIBUTES = nullValue,
LINEITEMS = [
{
ITEM_ID = ...,
SKU = ...,
DESCRIPTION = ...,
UNIT_PRICE = ...,
QUANTITY = ...,
ATTRIBUTES = nullValue
}
],
ALTNAME = nullValue,
ALTADDRESS1 = nullValue,
ALTADDRESS2 = nullValue,
ALTCITY = nullValue,
ALTSTATE = nullValue,
ALTZIP = nullValue,
ALTCOUNTRY = nullValue
};
ws = CreateObject("webservice","https://stageccp.dev.cdc.nicusa.com/CCPWebService/ServiceWeb.wsdl");
ws.PreparePaymentv2(args);
response = getSOAPResponse(ws);
</cfscript>
<cfinvoke webservice="https://stageccp.dev.cdc.nicusa.com/CCPWebService/ServiceWeb.wsdl" method="PreparePaymentv2" request="#args#" returnvariable="response">
这两种策略return错误信息:
Cannot perform web service invocation PreparePaymentv2.
查看详细信息会发现一个扩展的堆栈跟踪,我认为它来自远程服务器,在跟踪顶部附近包含以下消息:
Object reference not set to an instance of an object.
编辑:完整错误详情如下:
The fault returned when invoking the web service operation is: org.apache.axis2.AxisFault: Object reference not set to an instance of an object. at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:531
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:375
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:421
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165
at com.nicusa.cdc.checkout.common.ServiceWebStub.preparePaymentv2(ServiceWebStub.java:217
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source
at java.lang.reflect.Method.invoke(Unknown Source
at coldfusion.xml.rpc.Axis2ServiceProxy.getResult(Axis2ServiceProxy.java:112
at coldfusion.xml.rpc.ServiceProxy.invokeImpl(ServiceProx...
以及完整的堆栈跟踪:
coldfusion.xml.rpc.ServiceProxy$ServiceInvocationException: Cannot perform web service invocation PreparePaymentv2. at coldfusion.xml.rpc.Axis2ServiceProxy.getResult(Axis2ServiceProxy.java:122
at coldfusion.xml.rpc.ServiceProxy.invokeImpl(ServiceProxy.java:469
at coldfusion.xml.rpc.ServiceProxy.invoke(ServiceProxy.java:413
at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2489
at cfpayport_redirect2ek2648755446._factor4(C:\websites\preceptorStudent\test\payport_redirect.k2:312
at cfpayport_redirect2ek2648755446._factor5(C:\websites\preceptorStudent\test\payport_redirect.k2:120
at cfpayport_redirect2ek2648755446.runPage(C:\websites\preceptorStudent\test\payport_redirect.k2:1
at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:247
at coldfusion.tagext.lang.IncludeTag.handlePageInvoke(IncludeTag.java:736
at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:572
at coldfusion.filter.CfincludeFilter.invoke(CfincludeFilter.java:65
at coldfusion.filter.IpFilter.invoke(IpFilter.java:45
at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:474
at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:42
at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40
at coldfusion.filter.PathFilter.invoke(PathFilter.java:153
at coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:30
at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:94
at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28
at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38
at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:58
at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38
at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22
at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62
at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:151
at coldfusion.CfmServlet.service(CfmServlet.java:219
at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208
at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42
at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:458
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:196
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61
at java.lang.Thread.run(Unknown Source)
我最好的猜测是这与传入的数据有关。我还尝试省略 args 中设置为 nullValue 的任何参数。这会导致相同的错误消息。我意识到为 nullValue 使用空字符串并不是最佳选择;我还没有找到 ColdFusion 11 的更好替代品。
the return value (delivered in a SOAP message) is a bit difficult to work with.
您是否遇到了具体问题?通常您只需将响应解析为 XML 并使用结构符号来访问所需的节点:
<cfset root = xmlParse(httpResponse.fileContent)>
<cfdump var="#root#" label="HttpResponse">
<cfoutput>FaultCode = #root.Envelope.Body.Fault.FaultCode.xmlText#</cfoutput>
通常这比使用 createObject("webservice") 更容易。您已经遇到了最大的问题,即排除 Web 服务错误可能是一个痛苦的过程;-)。错误消息往往含糊不清,最常见的是 "Web service operation SomeMethod with parameters {...some params...} cannot be found."。不是特别有用。它只是说参数有问题,但没有提供任何关于哪个参数、有什么问题或如何修复它的线索。
当然,您通常可以让事情正常进行……最终。但是,如果它是一个复杂的 Web 服务,那么并不总是值得花费时间和精力,这就是为什么经常推荐使用 cfhttp 的原因。
Looking at the details reveals an extended stack trace, which I reason is from the remote server, containing this message near the top of the trace:
Cannot perform web service invocation PreparePaymentv2.
无论如何,如果您还想尝试 cfinvoke,参数至少存在三个问题:
并非所有元素都是字符串。因此,当空字符串无法转换为正确的
type
时,使用 nullValue = "" 会导致错误。ORDERATTRIBUTES
就是这样。由于它是可选的,如果您不想为该键传递值,只需将其从args
结构中完全省略即可。LINEITEMS
不是数组。它是一个 结构 ,包含一个名为 "lineitem" 的键,它是一个数组。所以这个值应该这样构造:LINEITEMS.LINEITEM = [ {... lineitem data ... } ]
ORDERATTRIBUTES
也是如此。它是一个包含名为 "field" 的键的结构,这是一个结构数组:ORDERATTRIBUTES.FIELD = [ {...field data ... } ]
如果您有兴趣了解更多有关 Web 服务内部工作方式的信息,CF 的功能是基于 Axis which uses a tool called wsdl2java 将 WSDL 转换为 java 类。通过保存和查看它生成的文件,您可以发现很多关于参数应该如何构建的信息。这就是我如何弄清楚上面的问题。保存的文件将位于 cfusion/stubs
子目录中。
// Only need to do this once. DON'T use in Prod as it's very time consuming
ws = CreateObject("webservice","https://example.com/ServiceWeb.wsdl"
, {saveJava=true, refreshWSDL=true});