Problem in calling RemObjects SOAP services from PHP

Hello there,

I need to develop a web service that will be called from a website developed using PHP.
For testing purposes I created a SOAP based Server, added a test method, but when I call my service from php, it seems that parameters aren’t passed to the server. This is my code in PHP (I don’t know php too much :frowning: ).

<?php
$client = new SoapClient('http://127.0.0.1:8099/SOAP/NewService');
$response = $client->Echo('Test');
print_r($response);
?>

This is my method on the server:

function TNewService.Echo(const pEchoString: AnsiString): AnsiString;
begin
  Result := 'This is a test: ' + pEchoString;  //pEchoString is always equal to '' 
end;

I read that you can call SOAP services developed with RemObjects SDK, like any other SOAP webservices. I tried also doing the same server with the Delphi’s own webservices and the testcase works. I also know that you can generate the interface for php, but the thing is that I don’t know who to call it.
If you guys have a Sample on how to call my SOAP webservice, or if you could tell where a I doing something wrong. I would really appreciate it.

Using Delphi XE2, Remobjects 7.0.71.1093

Best regards,
Cristian Vasuica

Hello,
Try to use PHP code like this:

<?php
  $client = new SoapClient('http://127.0.0.1:8099/SOAP/NewService');
  $params = new stdClass;
  $params->pEchoString = "test";
  $response = $client->Echo($params);
  print_r($response);
?>

vovanl, thank you very much…you saved my day. It works like a charm.

Best regards,
Cristian Vasuica

hello again, I have downloaded a working example of SOAP and SSL from here ( HTTPS Server) and I can see that is working fine, but again I need to test it with a php client, but I always get this error.
This is my php:

  <?php
    try {
       $soapclient_options = array(); 
       $soapclient_options['local_cert'] = "sample.crt"; 
        $client = new SoapClient("https://192.168.10.6:8099/soap", $soapclient_options);	
    	$params = new stdClass;
    	  $params->A = 1;
    	  $params->B = 3;
    	$response = $client->GetServerTime($params);
        print_r($response);
    }
    catch (SoapFault $exception) {
        echo $exception->getMessage();
    }
    ?>

and I get this error: > SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘https://192.168.10.6:8099/soap’ : failed to load external entity "https://192.168.10.6:8099/soap"
I have enabled openssl in php.ini, do you have any idea of how to ge rid of this error (or a working example with a SOAP Remobjects service and a php client), because I tried all sorts of non-working solutions for the past two days.
Best regards,
Cristian

Ok, after another day of searching I realised the mistake I made, I used the same certificate for server and for client.
After that I generated a new certificate for my php client, and also it didn’t work, the problem was the “local_cert” needs to contain
also the private and the public key of the phpclient. After that I tried again and it didn’t worked. I received this error:

Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers in C:\xampp\htdocs\test\test2.php:19 Stack trace: #0 [internal function]: SoapClient->__doRequest(‘<?xml version="…’, ‘http://localhos…’, ‘urn:NewLibrary-…’, 1, 0) #1 C:\xampp\htdocs\test\test2.php(19): SoapClient->__call(‘Sum’, Array) #2 C:\xampp\htdocs\test\test2.php(19): SoapClient->Sum(Object(stdClass)) #3 {main} thrown in C:\xampp\htdocs\test\test2.php on line 19

After that I began inspecting the wsdl for errors: I noticed at this line of the RODL generated wsdl:
<soap:address location=“http://localhost:8099/SOAP?service=NewService”/> that it doesn’t has https, and I think that this is the problem.

In the next step I built a new project of indy ssl (without rem sdk), and looked in the wsdl at the same line and it has “https” at the address tag. I tried my
php code and with this new address it works, and that’s why I presume that the problem with RemObjects SSL server might be at that address tag.

Finnaly my php looks like this right now:

    <?php
    $cert = 'D:\\certificate\ClientKeyAndCer.pem';        # file with client's certificate
    $wsdlurl = 'https://localhost:8099/SOAP?service=NewService';
    # SOAP settings
    ini_set("soap.wsdl_cache_enabled", "0");
    # Initializing SOAP object
    $client = new SoapClient($wsdlurl, array( 'local_cert' => $cert));
    $params = new stdClass;
    	  $params->A = 1;
    	  $params->B = 3;
    $result = $client->Sum($params);
    # on debug
    # print request
    # echo $client->__getLastRequest()."\n\n";
    # print response
    # echo $client->__getLastResponse()."\n\n";
    if (is_soap_fault($result)) {
        trigger_error("SOAP Fault: (faultcode: {$result->faultcode}, faultstring: {$result->faultstring}, detail: {$result->detail})", E_USER_ERROR);
    } else {
        print_r($result);
    }
?>

I am waiting for directions from you now. It would be nice if we could have a better integration of Remobjects and SSL. I know that you have your own crypting mechanism, but I can’t use it because I don’t know in which programming language the clients will be built with; I am sure that one will be in php, but I am not sure for the other(s).
Best regards,
Cristian Vasuica

Can you retest with latest version of RO, pls?
looks like, we have already fixed this issue because wsdl contains:

<soap:address location="https://192.168.1.2:8099/SOAP?service=NewService"/>

Hello, It works with the latest RO, but how do I make it work with my version: 7.0.71.1093?

Best regards,

hello again, nobody answered my question, could you please tell what are the problems and if it works with my version. Please have a look into this because time is precious and I need to give feedback to my manager.
Kind regards,
Cristian Vasuica

you can apply following unified patch (it was created with git):

e12241fd1b18fa35378b3363af6a9d79304ee2c5
 .../Source/uROIndyHTTPServer.pas                    | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/RemObjects SDK for Delphi/Source/uROIndyHTTPServer.pas b/RemObjects SDK for Delphi/Source/uROIndyHTTPServer.pas
index 9a0427d..134e224 100644
--- a/RemObjects SDK for Delphi/Source/uROIndyHTTPServer.pas	
+++ b/RemObjects SDK for Delphi/Source/uROIndyHTTPServer.pas	
@@ -39,6 +39,7 @@ type
     fResponseInfo : TIdHTTPResponseInfo;
     fOverriddenPathInfo : string;
     FCanUseContentEncoding: Boolean;
+    fIsHTTPs: Boolean;
   protected
     { IROHTTPRequest }
     function GetMethod: string;
@@ -75,7 +76,7 @@ type
     function GetClientAddress : string;
 
   public
-    constructor Create(aRequestInfo: TIdHTTPRequestInfo; aResponseInfo : TIdHTTPResponseInfo);
+    constructor Create(aRequestInfo: TIdHTTPRequestInfo; aResponseInfo : TIdHTTPResponseInfo; aIsHTTPs: Boolean);
     property RequestInfo: TIdHTTPRequestInfo read fRequestInfo;
     property ResponseInfo : TIdHTTPResponseInfo read fResponseInfo;
   end;
@@ -134,7 +135,7 @@ implementation
 
 uses
   SysUtils,
-  IdGlobal,
+  IdGlobal, {$IFDEF RemObjects_INDY10}IdSSL,{$ENDIF}
   {$IFDEF RemObjects_INDY10A}IdStreamVCL, idURI,IdResourceStringsProtocols,
   IdGlobalProtocols,IdIOHandlerSocket,IdCoderMIME,idStack,IdStackConsts,IdExceptionCore,{$ENDIF}
   {$IFDEF RemObjects_INDY10B}IdSocketHandle,{$ENDIF}
@@ -215,6 +216,7 @@ var
   ltemp : IROHTTPTransportEx;
   i: integer;
   lname, lvalue, lContentType: string;
+  lIsHTTPs: Boolean;
 begin
   lRec:= TIPHTTPResponseHeaders.Create;
   try
@@ -241,8 +243,13 @@ begin
       aRequestStream := TROBinaryMemoryStream.Create({$IFDEF UNICODE}WideStringToAnsiString{$ENDIF}(reqdata));
     end;
     {$ENDIF}
+    {$IFDEF RemObjects_INDY10}
+    lIsHTTPs := AThread.Connection.IOHandler is TIdSSLIOHandlerSocketBase;
+    {$ELSE}
+    lIsHTTPs := False; // no way to detect SSL safely in Indy8/9
+    {$ENDIF}
     try
-      ltemp := TIndyHTTPTransport.Create(RequestInfo, ResponseInfo);
+      ltemp := TIndyHTTPTransport.Create(RequestInfo, ResponseInfo, lIsHTTPs);
       try
         ProcessRequest(
           ltemp,
@@ -930,11 +937,12 @@ end;
 { TIndyHTTPTransport }
 
 constructor TIndyHTTPTransport.Create(
-  aRequestInfo: TIdHTTPRequestInfo; aResponseInfo: TIdHTTPResponseInfo);
+  aRequestInfo: TIdHTTPRequestInfo; aResponseInfo: TIdHTTPResponseInfo; aIsHTTPs: Boolean);
 begin
   inherited Create;
   fRequestInfo := aRequestInfo;
   fResponseInfo := aResponseInfo;
+  fIsHTTPs := aIsHTTPs;
 end;
 
 function TIndyHTTPTransport.GetAuthPassword: string;
@@ -981,7 +989,10 @@ end;
 
 function TIndyHTTPTransport.GetLocation: string;
 begin
-  result := id_http+fRequestInfo.Host
+  if fIsHTTPs then
+    result := id_https+fRequestInfo.Host
+  else
+    result := id_http+fRequestInfo.Host
 end;
 
 function TIndyHTTPTransport.GetMethod: string;

@EvgenyK thanks a lot. it works now. I have read that you plan to support ssl in a easier way in the next release. If that is true I will do my best in convincing my manager to upgrade RemObjects to the last version.

in DA8 we have introduced a new WinHTTP server that uses HTTP Server API.
See more details at How to use SSL in Remobjects SDK? thread