HOW : PHP SoapClinet WSDL Request Parmeter Structure

I’m a newbie on SOAP webservice. It has a soapserver with test.wsdl provided. I want to get data response from server and write the following PHP script in order to get the result. However, there is an error occurred on script and the error is followings.

Cannot process the message because the content type ‘application/soap+xml; charset=utf-8; action=“ELevy.Service/IELevyService/LevyEFrank”’ was not the expected type 'multipart/related; type=“application/xop+xml”.

Could anyone help me (or give me hints) to solve the problem?

Thanks in advanced!

Here is the PHP script index.php :

<?php
// initialize soap client
$soapOption = array(
    'soap_version' => SOAP_1_2,
    'location' => 'https://www.elevy-ticf-train.org.hk:8443/ELevyService.svc'
);

$client = new SoapClient('test.wsdl', $soapOption);
$error  = 0;

// request parameters
$soapCallParameters = new stdClass();
$soapCallParameters->API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$soapCallParameters->RECEIPT_NUMBER = '201800001';
$soapCallParameters->OUT_BOUND_FARE_PAID = '105.65';
$soapCallParameters->NAME_OF_TRAVELER_PAYER = "Anonymous";
$soapCallParameters->DEPARTURE_DATE = "2018-12-31";
$soapCallParameters->LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER = '3775';

// for debugging
$functions = $client->__getFunctions();
$types = $client->__getTypes();

// debugging status
var_dump($functions);
var_dump($types);
var_dump($client);

try {
    $result = $client->LevyEFrank($soapCallParameters);

} catch (SoapFault $fault) {
    $error = 1;
}

if ($error == 1) {
    var_dump($fault->faultcode);
    var_dump($fault->faultstring);
} else {
    var_dump($result);
}

Here is the test.wsdl :

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="ELevyService" targetNamespace="ELevy.Service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 

xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:tns="ELevy.Service" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsp:Policy wsu:Id="BasicHttpsBinding_IELevyService_policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <wsoma:OptimizedMimeSerialization xmlns:wsoma="http://schemas.xmlsoap.org/ws/2004/09/policy/optimizedmimeserialization"/>
                <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                    <wsp:Policy>
                        <sp:TransportToken>
                            <wsp:Policy>
                                <sp:HttpsToken RequireClientCertificate="false"/>
                            </wsp:Policy>
                        </sp:TransportToken>
                        <sp:AlgorithmSuite>
                            <wsp:Policy>
                                <sp:Basic256/>
                            </wsp:Policy>
                        </sp:AlgorithmSuite>
                        <sp:Layout>
                            <wsp:Policy>
                                <sp:Strict/>
                            </wsp:Policy>
                        </sp:Layout>
                    </wsp:Policy>
                </sp:TransportBinding>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
    <wsdl:types>
        <xs:schema elementFormDefault="qualified" targetNamespace="ELevy.Service" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:import namespace="ELevy.Schema"/>
            <xs:element name="LevyEFrank">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="request" nillable="true" type="q1:LevyEFrankRequest" xmlns:q1="ELevy.Schema"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="LevyEFrankResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="LevyEFrankResult" nillable="true" type="q2:LevyEFrankResponse" xmlns:q2="ELevy.Schema"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:schema>
        <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/"> 
            <xs:element name="anyType" nillable="true" type="xs:anyType"/>
            <xs:element name="anyURI" nillable="true" type="xs:anyURI"/>
            <xs:element name="base64Binary" nillable="true" type="xs:base64Binary"/>
            <xs:element name="boolean" nillable="true" type="xs:boolean"/>
            <xs:element name="byte" nillable="true" type="xs:byte"/>
            <xs:element name="dateTime" nillable="true" type="xs:dateTime"/>
            <xs:element name="decimal" nillable="true" type="xs:decimal"/>
            <xs:element name="double" nillable="true" type="xs:double"/>
            <xs:element name="float" nillable="true" type="xs:float"/>
            <xs:element name="int" nillable="true" type="xs:int"/>
            <xs:element name="long" nillable="true" type="xs:long"/>
            <xs:element name="QName" nillable="true" type="xs:QName"/>
            <xs:element name="short" nillable="true" type="xs:short"/>
            <xs:element name="string" nillable="true" type="xs:string"/>
            <xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte"/>
            <xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt"/>
            <xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong"/>
            <xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort"/>
            <xs:element name="char" nillable="true" type="tns:char"/>
            <xs:simpleType name="char">
                <xs:restriction base="xs:int"/>
            </xs:simpleType>
            <xs:element name="duration" nillable="true" type="tns:duration"/>
            <xs:simpleType name="duration">
                <xs:restriction base="xs:duration">
                    <xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?"/>
                    <xs:minInclusive value="-P10675199DT2H48M5.4775808S"/>
                    <xs:maxInclusive value="P10675199DT2H48M5.4775807S"/>
                </xs:restriction>
            </xs:simpleType>
            <xs:element name="guid" nillable="true" type="tns:guid"/>
            <xs:simpleType name="guid">
                <xs:restriction base="xs:string">
                    <xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}"/>
                </xs:restriction>
            </xs:simpleType>
            <xs:attribute name="FactoryType" type="xs:QName"/>
            <xs:attribute name="Id" type="xs:ID"/>
            <xs:attribute name="Ref" type="xs:IDREF"/>
        </xs:schema>
        <xs:schema elementFormDefault="qualified" targetNamespace="ELevy.Schema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="ELevy.Schema">
            <xs:complexType name="LevyEFrankRequest">
                <xs:sequence>
                    <xs:element name="API_KEY" nillable="true" type="xs:string"/>
                    <xs:element name="RECEIPT_NUMBER" nillable="true" type="xs:string"/>
                    <xs:element name="OUT_BOUND_FARE_PAID" nillable="true" type="xs:string"/>
                    <xs:element name="NAME_OF_TRAVELER_PAYER" nillable="true" type="xs:string"/>
                    <xs:element name="DEPARTURE_DATE" nillable="true" type="xs:string"/>
                    <xs:element name="LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER" nillable="true" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
            <xs:element name="LevyEFrankRequest" nillable="true" type="tns:LevyEFrankRequest"/>
            <xs:complexType name="LevyEFrankResponse">
                <xs:sequence>
                    <xs:element name="ACK_CODE" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="ACK_MESSAGE" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="RECEIPT_NUMBER" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="OUT_BOUND_FARE_PAID" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="NAME_OF_TRAVELER_PAYER" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="DEPARTURE_DATE" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="FRANK_DATE_TIME" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="LEVY_COLLECTION_NUMBER" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="LEVY_AMOUNT" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="LOW_ACCOUNT_BALANCE_INDICATOR" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="LEVY_STAMP" nillable="true" type="xs:base64Binary"/>
                </xs:sequence>
            </xs:complexType>
            <xs:element name="LevyEFrankResponse" nillable="true" type="tns:LevyEFrankResponse"/>
        </xs:schema>
    </wsdl:types>
    <wsdl:message name="IELevyService_LevyEFrank_InputMessage">
        <wsdl:part name="parameters" element="tns:LevyEFrank"/>
    </wsdl:message>
    <wsdl:message name="IELevyService_LevyEFrank_OutputMessage">
        <wsdl:part name="parameters" element="tns:LevyEFrankResponse"/>
    </wsdl:message>
    <wsdl:portType name="IELevyService">
        <wsdl:operation name="LevyEFrank">
            <wsdl:input wsaw:Action="ELevy.Service/IELevyService/LevyEFrank" message="tns:IELevyService_LevyEFrank_InputMessage"/>
            <wsdl:output wsaw:Action="ELevy.Service/IELevyService/LevyEFrankResponse" message="tns:IELevyService_LevyEFrank_OutputMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="BasicHttpBinding_IELevyService" type="tns:IELevyService">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="LevyEFrank">
            <soap:operation soapAction="ELevy.Service/IELevyService/LevyEFrank" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="BasicHttpsBinding_IELevyService" type="tns:IELevyService">
        <wsp:PolicyReference URI="#BasicHttpsBinding_IELevyService_policy"/>
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="LevyEFrank">
            <soap:operation soapAction="ELevy.Service/IELevyService/LevyEFrank" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="ELevyService">
        <wsdl:port name="BasicHttpBinding_IELevyService" binding="tns:BasicHttpBinding_IELevyService">
            <soap:address location="http://localhost/ELevyService.svc"/>
        </wsdl:port>
        <wsdl:port name="BasicHttpsBinding_IELevyService" binding="tns:BasicHttpsBinding_IELevyService">
            <soap:address location="https://localhost/ELevyService.svc"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

Here is the PHP var_dump result :

D:\Wamp64\www\a\index.php:24:
array (size=2)
  0 => string 'LevyEFrankResponse LevyEFrank(LevyEFrank $parameters)' 
(length=53)
  1 => string 'LevyEFrankResponse LevyEFrank(LevyEFrank $parameters)' 
(length=53)
D:\Wamp64\www\a\index.php:25:
array (size=7)
  0 => string 'struct LevyEFrank {
 LevyEFrankRequest request;
}' (length=49)
  1 => string 'struct LevyEFrankResponse {
 LevyEFrankResponse LevyEFrankResult;
}' (length=67)
  2 => string 'int char' (length=8)
  3 => string 'duration duration' (length=17)
  4 => string 'string guid' (length=11)
  5 => string 'struct LevyEFrankRequest {
 string API_KEY;
 string RECEIPT_NUMBER;
 string OUT_BOUND_FARE_PAID;
 string NAME_OF_TRAVELER_PAYER;
 string DEPARTURE_DATE;
 string LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER;
}' (length=200)
  6 => string 'struct LevyEFrankResponse {
 string ACK_CODE;
 string ACK_MESSAGE;
 string RECEIPT_NUMBER;
 string OUT_BOUND_FARE_PAID;
 string NAME_OF_TRAVELER_PAYER;
 string DEPARTURE_DATE;
 string LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER;
 string FRANK_DATE_TIME;
 string LEVY_COLLECTION_NUMBER;
 string LEVY_AMOUNT;
 string LOW_ACCOUNT_BALANCE_INDICATOR;
 base64Binary LEVY_STAMP;
}' (length=366)

D:\Wamp64\www\a\index.php:26:
object(SoapClient)[1]
  public 'location' => string 'https://www.elevy-ticf-train.org.hk:8443/ELevyService.svc' (length=57)
  public '_stream_context' => resource(2, stream-context)
  public '_soap_version' => int 2
  public 'sdl' => resource(4, SOAP SDL)

D:\Wamp64\www\a\index.php:36:string 'HTTP' (length=4)

D:\Wamp64\www\a\index.php:37:string 'Cannot process the message because 
the content type 'application/soap+xml; charset=utf-8; 
action="ELevy.Service/IELevyService/LevyEFrank"' was not the expected 
type 'multipart/related; type="application/xop+xml"'.' (length=213)

In order for the request to work correctly with the SOAP client you must created classes with the names they expect.

So in your case that would be request would be:

class LevyEFrank
{
    public $request;
}

class LevyEFrankRequest
{
    public $API_KEY;
    public $RECEIPT_NUMBER;
    public $OUT_BOUND_FARE_PAID;
    public $NAME_OF_TRAVELER_PAYER;
    public $DEPARTURE_DATE;
    public $LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER;
}

$request = new LevyEFrankRequest();
$request->API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$request->RECEIPT_NUMBER = '201800001';
$request->OUT_BOUND_FARE_PAID = '105.65';
$request->NAME_OF_TRAVELER_PAYER = "Anonymous";
$request->DEPARTURE_DATE = "2018-12-31";
$request->LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER = '3775';

$levyEFrank = new LevyEFrank();
$levyEFrank->request = $request;

$client->LevyEFrank($levyEFrank);

Thanks for your instructions for me to prepare the request parameters structure. You are my sunshine. I have followed your hints to execute once again. The result still cannot come out and the error is shown as below.

Cannot process the message because the content type ‘application/soap+xml; charset=utf-8; action=“ELevy.Service/IELevyService/LevyEFrank”’ was not the expected type ‘multipart/related; type=“application/xop+xml”’.

Does it seem that the server side is just accepted “application/xop+xml”? And my script in SOAP 1.2 is just generate type of “application/soap+xml”? The server side cannot be modified because of it is service provider in public sector. If the problem is that, how can I solve it? (I am really a newbie in SOAP, forgive me there are so many questions)

Existing PHP Script :

<?php
// prepare the request parameters
class LevyEFrank
{
    public $request;
}

class LevyEFrankRequest
{
    public $API_KEY;
    public $RECEIPT_NUMBER;
    public $OUT_BOUND_FARE_PAID;
    public $NAME_OF_TRAVELER_PAYER;
    public $DEPARTURE_DATE;
    public $LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER;
}

$request = new LevyEFrankRequest();
$request->API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$request->RECEIPT_NUMBER = '201800001';
$request->OUT_BOUND_FARE_PAID = '105.65';
$request->NAME_OF_TRAVELER_PAYER = "Anonymous";
$request->DEPARTURE_DATE = "2018-12-31";
$request->LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER = '3775';

$data = new LevyEFrank();
$data->request = $request;

// initialize soap client
$soapOption = array(
    'location' => 'https://www.elevy-ticf-train.org.hk:8443/ELevyService.svc',
	'trace' => true,
	'exceptions' => true,
    'soap_version' => SOAP_1_2
);

$client = new SoapClient('test.wsdl', $soapOption);
$error  = 0;

// for debugging
var_dump($data);

try {
	$result = $client->LevyEFrank($data);
} catch (SoapFault $fault) {
	$error = 1;
}

if ($error == 1) {
    echo "Fault Code : " . $fault->faultcode . '<br>';
    echo "Error Message : " . '<br>' . $fault->faultstring;
} else {
	var_dump($result);
}

Execution Result :

D:\Wamp64\www\a\index.php:41:
object(LevyEFrank)[2]
  public 'request' => 
    object(LevyEFrankRequest)[1]
      public 'API_KEY' => string 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx' (length=32)
      public 'RECEIPT_NUMBER' => string '201800001' (length=9)
      public 'OUT_BOUND_FARE_PAID' => string '105.65' (length=6)
      public 'NAME_OF_TRAVELER_PAYER' => string 'Anonymous' (length=9)
      public 'DEPARTURE_DATE' => string '2018-12-31' (length=10)
      public 'LAST_4_DIGIT_OF_CONTACT_PHONE_NUMBER' => string '3775' (length=4)
Fault Code : HTTP
Error Message : 
Cannot process the message because the content type 'application/soap+xml; charset=utf-8; action="ELevy.Service/IELevyService/LevyEFrank"' was not the expected type 'multipart/related; type="application/xop+xml"'.

It does indeed seem like the API expects some non-standard content type. You could see if there is a way to override the content type of your soap client, but from what I’ve seen it’s not easy.

Maybe contact the vendor of the API and ask them for advise? You’re probably not the first one to run into this problem.

I get the request parameters structure as below. Is it correct?

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="ELevy.Schema" xmlns:ns2="ELevy.Service">
 <env:Body>
  <ns2:LevyEFrank>
  <ns2:request>
   <ns1:API_KEY>xxxxxxxxxxxxxxxxxxxxxxxxxx</ns1:API_KEY>
   <ns1:RECEIPT_NUMBER>201800001</ns1:RECEIPT_NUMBER>
   <ns1:OUT_BOUND_FARE_PAID>105.65</ns1:OUT_BOUND_FARE_PAID>
   <ns1:NAME_OF_TRAVELER_PAYER>Anonymous</ns1:NAME_OF_TRAVELER_PAYER>
   <ns1:DEPARTURE_DATE>2018-12-31</ns1:DEPARTURE_DATE>
   <ns1:LAST_4_DIGIT_OF_CONTACT_PHONE'... (length=625)

See my answer above yours

The request itself seems ok

Thanks for your kindly help!

Hi, my master.

At last, i success to request from the soap server. The problem is that I didn’t define right version of soap version. Now I got the response but still failed and got fault message is "looks like we got no XML document’. However, if I dump the value from __getLastResponse(). The return value “are” corrected. It returns multipart of response, first part is xml and 2nd part is binary (which is an png image). Because I am a newbie on SOAP. Could you give me hints to get all these things into array/object?

I’ve no idea. I’ve never seen a SOAP API respond like that. Normally they’d base64 any binary data and just send it as part of the XML…

Maybe wrapping that content in <![CDATA[ ..... ]]> inside of the .. IHDR> would work?

Thread continues here: How to handle PHP soapclient multipart response with binary attachment