简体   繁体   中英

How to make SOAP call using native SoapClient in PHP?

I want to make a call to web service, which is also under development, and which has one function defined within WSDL, PlaceInvoiceFromStream. Function defines one argument to be passed, Invoice. WSDL imports types defined within XSD shema.

WSDL looks like this:

<?xml version="1.0" encoding="utf-8"?>
<definitions name ="inService"
    xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsdl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
    xmlns:tns="http://localhost/ebiz/ws/"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    targetNamespace="http://localhost/ebiz/ws/">
    <import namespace="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
        location="http://localhost/ebiz/ws/Invoice.xsd"
    />
    <message name="getPlaceInvoiceInput">
        <part name="body" element="xsdl:Invoice"/>
    </message>
    <message name="getPlaceInvoiceOutput">
        <part name="body" type="xsd:string"/>
    </message>
    <portType name="inServicePortType">
        <operation name="PlaceInvoiceFromStream">
            <input message="tns:getPlaceInvoiceInput"/>
            <output message="tns:getPlaceInvoiceOutput"/>
        </operation>
    </portType>
    <binding name="inServiceBinding" type="tns:inServicePortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="PlaceInvoiceFromStream">
            <soap:operation soapAction="PlaceInvoiceFromStream"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="inService">
        <port name="inServicePort" binding="tns:inServiceBinding">
            <soap:address location="http://localhost/ebiz/ws/soapServer.php"/>
        </port>
    </service>
</definitions>

Schema looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDataTypes-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:udt="urn:oasis:names:specification:ubl:schema:xsd:UnqualifiedDataTypes-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" targetNamespace="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" elementFormDefault="qualified" attributeFormDefault="unqualified" version="2.1">
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" schemaLocation="../common/UBL-CommonAggregateComponents-2.1.xsd"/>
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" schemaLocation="../common/UBL-CommonBasicComponents-2.1.xsd"/>
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:UnqualifiedDataTypes-2" schemaLocation="../common/UBL-UnqualifiedDataTypes-2.1.xsd"/>
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" schemaLocation="../common/UBL-CommonExtensionComponents-2.1.xsd"/>
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDataTypes-2" schemaLocation="../common/UBL-QualifiedDataTypes-2.1.xsd"/>
<xsd:element name="Invoice" type="InvoiceType"/>
<xsd:complexType name="InvoiceType">
    <xsd:sequence>
        <xsd:element ref="ext:UBLExtensions"/>
        <xsd:element ref="cbc:UBLVersionID"/>
        <xsd:element ref="cbc:CustomizationID" minOccurs="0"/>
        <xsd:element ref="cbc:ProfileID" minOccurs="0"/>
        <xsd:element ref="cbc:ID"></xsd:element>
        <xsd:element ref="cbc:CopyIndicator" minOccurs="0"/>
        <xsd:element ref="cbc:IssueDate"/>
        <xsd:element ref="cbc:InvoiceTypeCode" minOccurs="0"/>
        <xsd:element ref="cbc:Note" minOccurs="0"/>
        <xsd:element ref="cbc:TaxPointDate" minOccurs="0"/>
        <xsd:element ref="cbc:DocumentCurrencyCode" minOccurs="0"/>
        <xsd:element ref="cbc:AccountingCost" minOccurs="0"/>
        <xsd:element ref="cbc:LineCountNumeric" minOccurs="0"/>
        <xsd:element ref="cac:InvoicePeriod" minOccurs="0"/>
        <xsd:element ref="cac:OrderReference" minOccurs="0"/>
        <xsd:element ref="cac:DespatchDocumentReference" minOccurs="0"/>
        <xsd:element ref="cac:ReceiptDocumentReference" minOccurs="0"/>
        <xsd:element ref="cac:ContractDocumentReference" minOccurs="0"/>
        <xsd:element ref="cac:AdditionalDocumentReference" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="cac:Signature" minOccurs="0"/>
        <xsd:element ref="cac:AccountingSupplierParty"/>
        <xsd:element ref="cac:AccountingCustomerParty"/>
        <xsd:element ref="cac:BuyerCustomerParty" minOccurs="0"/>
        <xsd:element ref="cac:SellerSupplierParty" minOccurs="0"/>
        <xsd:element ref="cac:TaxRepresentativeParty" minOccurs="0"/>
        <xsd:element ref="cac:Delivery" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="cac:DeliveryTerms" minOccurs="0"/>
        <xsd:element ref="cac:PaymentMeans" maxOccurs="unbounded"/>
        <xsd:element ref="cac:PaymentTerms" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="cac:PrepaidPayment" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="cac:AllowanceCharge" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="cac:TaxTotal" maxOccurs="unbounded"/>
        <xsd:element ref="cac:LegalMonetaryTotal"/>
        <xsd:element ref="cac:InvoiceLine" maxOccurs="unbounded"/>
    </xsd:sequence>
</xsd:complexType>

UBL 2.1 Schemas: http://docs.oasis-open.org/ubl/prd2-UBL-2.1/UBL-2.1.html#SCHEMAS

Invoice is complex data, saved in XML file, and which contains namespaces and attributes. It starts like this:

<?xml version="1.0" encoding="UTF-8"?>
<Invoice
 xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
 xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
 xmlns:sac="urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2"
 xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 http://localhost/ebiz/ws/Invoice.xsd"
 xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
 xmlns:sig="urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2">
    <ext:UBLExtensions>
        <ext:UBLExtension>
            <cbc:ID>INVOICE1</cbc:ID>
            <cbc:Name>InvoiceIssuePlaceData</cbc:Name>
            <ext:ExtensionAgencyURI>urn:invoice:issueplace</ext:ExtensionAgencyURI>
            <ext:ExtensionContent>
                <ext:InvoiceIssuePlace>MyCity</ext:InvoiceIssuePlace>
            </ext:ExtensionContent>
        </ext:UBLExtension>
    </ext:UBLExtensions>
    <cbc:UBLVersionID>2.1</cbc:UBLVersionID>
    <cbc:ID>01 1206-2406-568</cbc:ID>`

etc...

I have tried this approach:

// LOAD XML and TRANSFORM FOR SoapClient 
$xmlfile = "Invoice123.xml";
$xslfile = "xsltForSoapClientRequest.xsl";
$xmlDOM = new DOMDocument();
$xmlDOM->load($xmlfile);
$xslDOM = new DOMDocument();
$xslDOM->load($xslfile);
$proc = new XSLTProcessor;
$proc->importStyleSheet($xslDOM);
$transformedXML = $proc->transformToDoc($xmlDOM);
$xmldoc = simplexml_load_string($transformedXML);

// CREATE ARRAY
$xmlarr = xml2array($xmldoc->asXML());

$client = new SoapClient($wsdl,array('trace'=>1));
$result=$client->PlaceInvoiceFromStream($xmlarr);

but with no success.

XSL transformation changes are:

  • node attribute becomes node element
  • complex node value becomes "_" element

xml2array changes are:

  • attributes becomes separate array

So, $xmlarr to be sent to web service function is in the following form:

array(2) {
  ["Invoice"]=>
  array(15) {
    ["ext:UBLExtensions"]=>
    array(1) {
      ["ext:UBLExtension"]=>
      array(4) {
        ["cbc:ID"]=>
        string(10) "INVOICE1"
        ["cbc:Name"]=>
        string(21) "InvoiceIssuePlaceData"
        ["ext:ExtensionAgencyURI"]=>
        string(25) "urn:invoice:issueplace"
        ["ext:ExtensionContent"]=>
        array(1) {
          ["ext:InvoiceIssuePlace"]=>
          string(7) "MyCity"
        }
      }
    }
    ["cbc:UBLVersionID"]=>
    string(3) "2.1"
    ["cbc:ID"]=>
    string(16) "01 1206-2406-568"
...

  ["Invoice_attr"]=>
  array(8) {
    ["xmlns"]=>
    string(54) "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
    ["xmlns:xsi"]=>
    string(41) "http://www.w3.org/2001/XMLSchema-instance"
    ["xmlns:cac"]=>
    string(72) "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
    ["xmlns:cbc"]=>
    string(68) "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
    ["xmlns:sac"]=>
    string(75) "urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2"
    ["xmlns:ext"]=>
    string(72) "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
    ["xmlns:sig"]=>
    string(72) "urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2"
    ["xsi:schemaLocation"]=>
    string(93) "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 http://localhost/ebiz/ws/Invoice.xsd"
  }
}

The result of the web service call is:

SOAP-ERROR: Encoding: object has no 'UBLExtensions' property

What should be the form for the correct SOAP request? What form of the array is expected for SOAP request? Does SOAP understands, based on WSDL and XSD, that "_" element? Or attributes in the separate array?

Thanks in advance for any help in fixing this issue...

UPDATE:

changed wsdl:

<message name="getPlaceInvoiceInput">
    <part name="Invoice" element="xsdl:InvoiceType"/>

SoapClient accepts following request:

$xmlarr = array(
    "UBLExtensions"=>
    array(
      "UBLExtension"=>
      array(
        "ID"=>"INVOICE1",
        "Name"=>"InvoiceIssuePlaceData",
        "ExtensionAgencyURI"=>"urn:invoice:issueplace",
        "ExtensionContent"=>
        array(
          "InvoiceIssuePlace"=>"MyCity"
        )
      )
    ),
    "UBLVersionID"=>"2.1",
    "ID"=>"01 1206-2406-568",
    ...

which is not what I want. I need namespaces in keys. What should be changed/added to make SoapClient able to accepts namespaces within keys in the request array, like ie "ext:UBLExtensions"?

I believe that you need to start your array at the UBLExtensions level, not the Invoice level. It sees your top element as Invoice where it expects UBLExtensions and complains when it doesn't find it:

SOAP-ERROR: Encoding: object has no 'UBLExtensions' property

It does not require the second Invoice_attr array, the names of the array elements go by the element names in the schema, not the ref values. Look what the ref points to in your schema (you don't seem to list it), that element should have a name .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM