How to make your webservice SOAP 1.2 in Yii

11,048

when i set up client to be v1.2 i always receive v1.2 response from server, and when i set up client to be v1.1 i always receive v1.1 response from server, maybe it auto-detects client version and overrides server version with it?

$client=new SoapClient('http://hys.local/ABFolio/folio',array('soap_version'=>SOAP_1_2,'trace'=>true));
var_dump($client);
echo $client->sendFolio();
echo $client->__getLastRequest();
echo $client->__getLastResponse();

response is 1.2

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"

and with 1.1 which default for client

$client=new SoapClient('http://hys.local/ABFolio/folio',array('soap_version'=>SOAP_1_1,'trace'=>true));

response is 1.1

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

EDIT:

lets look inside yii framework\web\services\CWebService.php

/**
 * @return array options for creating SoapServer instance
 * @see http://www.php.net/manual/en/function.soap-soapserver-construct.php
 */
protected function getOptions()
{
    $options=array();
    if($this->soapVersion==='1.1')
        $options['soap_version']=SOAP_1_1;
    else if($this->soapVersion==='1.2')
        $options['soap_version']=SOAP_1_2;
    if($this->actor!==null)
        $options['actor']=$this->actor;
    $options['encoding']=$this->encoding;
    foreach($this->classMap as $type=>$className)
    {
        $className=Yii::import($className,true);
        if(is_int($type))
            $type=$className;
        $options['classmap'][$type]=$className;
    }
    return $options;
}

i don't see any error in your code if i check this code

EDIT:

ok, how about this than? framework\web\services\CWsdlGenerator.php

/*
 * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
 */
private function addBindings($dom)
{
    $binding=$dom->createElement('wsdl:binding');
    $binding->setAttribute('name',$this->serviceName.'Binding');
    $binding->setAttribute('type','tns:'.$this->serviceName.'PortType');

    $soapBinding=$dom->createElement('soap:binding');
    $soapBinding->setAttribute('style','rpc');
    $soapBinding->setAttribute('transport','http://schemas.xmlsoap.org/soap/http');
    $binding->appendChild($soapBinding);

    $dom->documentElement->appendChild($binding);

    foreach($this->_operations as $name=>$doc)
        $binding->appendChild($this->createOperationElement($dom,$name));
}

as i can see transport is predefined (you can check and replace it to 12)

my wsdl becomes this after adding 12

<wsdl:binding name="ABFolioControllerBinding" type="tns:ABFolioControllerPortType">    
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap12/http"/>
</wsdl:binding>

maybe it's bug in yii - go ahead and report it then

but as from http://msdn.microsoft.com/en-us/library/ms995800.aspx i was checking not a transport but namespace

SOAP versioning is based on XML namespaces. SOAP 1.1 is identified by the http://schemas.xmlsoap.org/soap/envelope/ namespace while SOAP 1.2 is identified by the http://www.w3.org/2002/12/soap-envelope namespace (although this will change when it becomes a Recommendation). 

that's why i thought all is correct

EDIT:

here's decesion, you need to have

xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 

inside <definitions in your xml in addition to

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 

and instead of this:

<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

you must place

<soap12:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

now soapUI detects my wsdl as soap 1.2

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
xmlns="http://schemas.xmlsoap.org/wsdl/" 
xmlns:tns="urn:ABFolioControllerwsdl" 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" 
name="ABFolioController" 
targetNamespace="urn:ABFolioControllerwsdl">
    <wsdl:portType name="ABFolioControllerPortType"/>
    <wsdl:binding name="ABFolioControllerBinding" type="tns:ABFolioControllerPortType">
        <soap12:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
    </wsdl:binding>
    <wsdl:service name="ABFolioControllerService">
        <wsdl:port name="ABFolioControllerPort" binding="tns:ABFolioControllerBinding">
            <soap:address location="http://hys.local/uk/aBFolio/folio?ws=1"/>
        </wsdl:port>
    </wsdl:service>
</definitions>

all replacement you can do in same files in yii in addBindings and buildDOM functions

also i think it much harder, i.e. you must have both soap and soap12 bindings if you want to support both, but at least it already recognized as soap12

EDIT:

yii hardcoded soap1.1 if you don't provide your own wsdl (you can provide it via $wsdlUrl as in run method of CWebService). it seems legit - becouse default soap version in php soap server is 1.1 too, if you changing your version to 1.2 you must provide your own wsdl for 1.2

Share:
11,048
k to the z
Author by

k to the z

A web developer that wears many hats.

Updated on June 04, 2022

Comments

  • k to the z
    k to the z over 1 year

    The Problem:

    I can't figure out how Yii expects me to change the soap version. I'm following this tutorial. The web service works, but it isn't SOAP 1.2

    The Class:

    <?php
    class ABFolioController extends CController
    {
        public function actions()
        {
            return array(
                'folio'=>array(
                    'class'=>'CWebServiceAction',
                    'serviceOptions'=>array('soapVersion'=>'1.2')
                ),
            );
    
        }
    
        /**
         * @param  string folioId
         * @param  string cNumber
         * @param  string oDRS
         * @param  string dlr
         * @param  string feeAmount
         * @param  string transactionStatus
         * @param  string captureId
         * @param  datetime captureTimestamp
         * @param  string prefix
         * @param  string oDEFRS
         * @return string the statement
         * @soap
         */
        public function sendFolio($folioId, $cNumber, $oDRS, $dlr,
                $feeAmount, $transactionStatus, $captureId, $captureTimestamp, 
                $prefix, $oDEFRS)
        {
        //
    
          $model = new Dlfolio();
          $model->folioId = $folioId;
          $model->cNumber = $cNumber;
          $model->oDRS = $oDRS;
          $model->dlr = $dlr;
          $model->feeAmount = $feeAmount;
          $model->transactionStatus = $transactionStatus;
          $model->captureId = $captureId;
          $model->captureTimestamp = $captureTimestamp;
          $model->prefix = $prefix;
          $model->oDEFRS = $oDEFRS;
          $yesno = $model->save();
    
          if ($yesno=TRUE)
          {
              //on success
              return 'Record Saved';
          }
          else
          {
              //on failure
              return $yesno;
          }
    
        }   
    }
    
  • k to the z
    k to the z over 11 years
    This is about how to call this in the Yii framework. Not regular php. Thank you for the response though.
  • llamerr
    llamerr over 11 years
    and how do you think what soap server yii use? not php default? i'm just saying that maybe php server version is always overrided by client version
  • k to the z
    k to the z over 11 years
    llamerr, this is a framework specific question. There is a class with a specific property for this. I'm obviously incorrectly calling the property and want to know the correct way to do it within the framework. I know how to use the php soapClient. That's not what my question is about. If I wanted to use it without the framework on top I would, but that's not my question.
  • llamerr
    llamerr over 11 years
    i understand that its a framework specific question, but how do you determine that your soap version is set incorrectly?
  • llamerr
    llamerr over 11 years
    i don't know if schemas.xmlsoap.org/soap12/http is correct transport, maybe it must be something else
  • llamerr
    llamerr over 11 years
    btw, are you sure that soap version is determined by <soap:binding style="rpc" transport=? schemas.xmlsoap.org/wsdl/soap12/soap12WSDL.htm here i can see that transport is the same, but namespace changed(it also predefined in same file in yii)
  • k to the z
    k to the z over 11 years
    There are probably a few thing that make something 1.1
  • k to the z
    k to the z over 11 years
    Alright it looks like you're right. I'll mark your question as correct and award the bounty in four days. That way someone else can comment if they think we are wrong. I can't believe yii hard coded the web service to 1.1
  • llamerr
    llamerr over 11 years
    no, yii hardcoded soap1.1 if you don't provide your own wsdl, you can provide it via $wsdlUrl as in run method of CWebService
  • llamerr
    llamerr over 11 years
    also it seems legit - becouse default soap version in php soap server is 1.1 too, if you changing your version to 1.2 you must provide your own wsdl for 1.2