Search code examples
phpsoapsoap-client

**SOAP-ERROR:** Encoding: Cannot find encoding


I gotta consume a SOAP service from PHP but I keep failing to get the response. Maybe it's a problem with the format or the call or idk. I can for example get all the functions names from the server with the __getFunctions() method. But when I try to invoke any function I keep getting:

SOAP-ERROR: Encoding: Cannot find encoding

Below is the code.

$wsdl = "https://testing.memoryefactura.com/Memory.FEManager/WebService/CFEService.svc?wsdl";


$parameters = array('Rut' => 'XXXXX',
    'CommerceCode' => 'XXXXX',
    'TerminalCode' => 'XXXXX',
    'Timeout' => 5000);


$options = array(
    'style' => SOAP_RPC,
    'use' => SOAP_ENCODED,
    'soap_version' => SOAP_1_1,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'connection_timeout' => 15,
    'trace' => true,
    'exceptions' => true,
);
try {
    $soap = new SoapClient($wsdl, $options);
    $HeaderSecurity = array(
        'stream_context' => stream_context_create(array(
            'http' => array(
                'header' => array('username' => 'XXXXX',
                    'password' => 'XXXXX'
                )
            ),
        )),
    );
    $header[] = new SoapHeader("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", $HeaderSecurity);

    $soap->__setSoapHeaders($header);
    $data = $soap->Ping($parameters);
} catch (Exception $e) {
    die($e->getMessage());
}

var_dump($data);

Solution

  • Based on the wsdl, the ping method takes only 3 parameters.

    class Ping {
        /** @var BaseMessage */ public $message;
    }
    class BaseMessage {
        /** @var string */  public $CommerceCode;
        /** @var string */  public $TerminalCode;
        /** @var int */ public $Timeout;
    }
    

    Also, you incorrectly set the authorization header. The correct way to do this:

    $wsdl = "https://testing.memoryefactura.com/Memory.FEManager/WebService/CFEService.svc?wsdl";
    
    $opts = [
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false
        ],
        'http' => [
            'user_agent' => 'PHPSoapClient'
        ]
    ];
    
    $params = [
        'encoding' => 'UTF-8',
        'verifypeer' => false,
        'verifyhost' => false,
        'soap_version' => SOAP_1_1,
        'trace' => 1,
        'exceptions' => 1,
        'connection_timeout' => 180,
        'stream_context' => stream_context_create($opts)
    ];
    
    try {
        $client = new \SoapClient($wsdl, $params);
    
        $nameSpace = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
    
        $soapUsername = new \SoapVar(
            'XXXXX',
            XSD_STRING,
            null,
            $nameSpace,
            null,
            $nameSpace
        );
    
        $soapPassword = new \SoapVar(
            'XXXXX',
            XSD_STRING,
            null,
            $nameSpace,
            null,
            $nameSpace
        );
    
        $auth = new \stdClass();
        $auth->Username = $soapUsername;
        $auth->Password = $soapPassword;
    
        $soapAuth = new \SoapVar(
            $auth,
            SOAP_ENC_OBJECT,
            null,
            $nameSpace,
            'UsernameToken',
            $nameSpace
        );
    
        $token = new \stdClass();
        $token->UsernameToken = $soapAuth;
    
        $soapToken = new \SoapVar(
            $token,
            SOAP_ENC_OBJECT,
            null,
            $nameSpace,
            'UsernameToken',
            $nameSpace
        );
    
        $security = new \SoapVar(
            $soapToken,
            SOAP_ENC_OBJECT,
            null,
            $nameSpace,
            'Security',
            $nameSpace
        );
    
        $header = new \SoapHeader($nameSpace, 'Security', $security, true);
    
        $client->__setSoapHeaders([$header]);
    
        $parameters = array(
            'CommerceCode' => 'XXXXX',
            'TerminalCode' => 'XXXXX',
            'Timeout' => 5000
        );
    
        $data = $client->Ping($parameters);
    } catch (SoapFault $fault) {
        echo "REQUEST:\n" . $client->__getLastRequest();
        die("\nFaultcode: " . $fault->faultcode . "\nFaultstring: " . $fault->faultstring);
    } catch (Exception $e) {
        die($e->getMessage());
    }