简体   繁体   中英

PHP SOAP server + Javascript client

I have to communicate a Javascript application (NodeJS) with a PHP SOAP server. Right now, I'm using the soap package, which I've used in another projects (Java SOAP servers) successfully. However, I'm having some troubles this time trying to make both parts understand each other. I'll show you an example of a request (I've simplified the code a bit):

import * as soap from 'soap';

const soapClient = await soap.createClientAsync(wsdlUrl);

async getUserByUsername(username: string) {
  const secret_key = await buildSecretKey();

  const response = await soapClient['WSGetUserFromUsernameAsync']({
    secret_key,
    username
  }, { timeout: 5000 });

  return response;
}

const user = await getUserByUsername('admin');

This doesn't work because, when I see the logs on the PHP backend, these are the arguments it's receiving, as shown in the log file:

$params: SECRET_KEY

As you can see, it's receiving only the secret key parameter instead of the full object. However, if I call the SOAP method using PHP it works fine. I use the following (simplified) code:

$soap = new SoapClient($wsdlUrl);

$secret_key = buildSecretKey();

$result = $soap->WSGetUserFromUsername(array(
  'secret_key' => $secret_key,
  'username' => 'admin'
));

In this case, the log file shows the following parameters:

$params: Array\n(\n    [username] => admin\n    [secret_key] => SECRET_KEY\n)\n

I think that the problem is that the data sent by the Javascript client (JSON) is not converted to the expected format by the server (a PHP associative array), but I'm not sure as I still didn't have time to trace the request on the server and see what it's receiving.

EDIT I've used tcpdump to see the requests made by the PHP and JS SOAP clients and I think I found the problem. This is the JS SOAP request:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:tns="urn:WSRegistration">
  <soap:Body>
    <tns:WSGetUserFromUsername>
      <secret_key>SECRET_KEY</secret_key>
      <username>admin</username>
    </tns:WSGetUserFromUsername>
  </soap:Body>
</soap:Envelope>

And this is from the PHP client:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:WSRegistration" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:WSGetUserFromUsername>
      <GetUserFromUsername xsi:type="ns1:GetUserArgUsername">
        <username xsi:type="xsd:string">admin</username>
        <secret_key xsi:type="xsd:string">SECRET_KEY</secret_key>
      </GetUserFromUsername>
    </ns1:WSGetUserFromUsername>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

As you can see, the envelope generated by the PHP client has one extra node ( GetUserFromUsername ) and I think it could cause the wrong parameters assignment in the server.

Anyway, any clue of what I could try? Thanks!

The problem was that the SOAP server expects the parameters to be wrapped in an extra node.

So, instead of this call:

const response = await soapClient['WSGetUserFromUsernameAsync']({
    secret_key,
    username
  }, { timeout: 5000 });

The right one is:

const response = await soapClient['WSGetUserFromUsernameAsync']({
  WSGetUserFromUsername: {
    secret_key,
    username
  }
}, { timeout: 5000 });

Now everything works as expected, cheers!

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