Print
Parent Category: Datorer
Category: Programmering
Hits: 775

I don't do much programming anymore but sometimes it's nice to see how things work in the environment I work. So....my worksituation is that we use a remote WMS (warehouse management system). And there are a bunch of clients that need to communicate with that system. Most people/clients (if they are not too cheap) would want to make an integration to that system. The server I believe is a windows-server that uses a SOAP-server that clients can connect to. Old interface.... but it works. The programming language(script-) i wanted to test this on, is PHP. This is the scripting language I remember best. I'm not going to go into the details of this because I do not know the details. I just found something that works.

Using the PHP SoapClient object

There's also a python library called SUDS that pretty much works the samme way. See here.

1. Getting Order-information
First of all I want to get information from the server. I want to get information about an order. The first thing we havee to do is to create a SoapClient object, that can verify and connect to the WSDL - adresse. This adresse/path will be given by an administrator of the server. The SoapClient - initializer takes 2 parameters:

1. Adresse/path to the WSDL
2. array containing SOAP options

See code below:

$post_adr='https://path_to_wsdl/service.asmx?WSDL';
$soap_options = array('soap_version' => SOAP_1_2, 'trace' => TRUE);
$Ongoing = new SoapClient($post_adr, $soap_options);

Using the trace-option is very usefull when there are errors, I found out. All errors are printed in my servers error-log. If the call is valid the next thing is to tell the SOAP-server what you want to do. All functions/services are (in my case) listed in https://path_to_wsdl/service.asmx.

Or yoiu might want to call/Use the function __getFunctions(), like this $Ongoing->__getFunctions();

Either way, I know what I want. I want to get information about an order. The name of the function/service is called 'GetOrderByOrderNumber'. I'm going to use th member-function __soapCall. This function needs at least 2 parameters.
1. Function/service name
2. Parameters to server(An array containing login-information and other params to send with (1).

 See code below for example:

$parameters = array("GoodsOwnerCode" => "goodsowner_name",
			"UserName" => "username",
			"Password" => "password",
			"OrderNumber" => "Goodsowners_ordernumber",
);
$GetOrderByOrderNumber='GetOrderByOrderNumber';
$res = $Ongoing->__soapCall($GetOrderByOrderNumber, array($parameters));

The reource that's returned is an object that contains all data. And it's really easy to navigate, because it has the same structure as the xml-data that is returned. If you call 

$Ongoing->__getLastResponse();

you will get the whole xml-document. But we're not going to do that. We just want to test by getting some rudimentary information. We're going to use the $res object. Below is the code:

echo "Get Consignee->Id: <br />\n";
$r = $res->GetOrderByOrderNumberResult;
echo $r->Consignee->Id;
echo "<br />\n";
echo  "Get Goodsinfo->number of items: <br />\n";
echo $r->GoodsInfo->NumberOfGoodsItems;
echo "<br />\n";
echo "The WayBill is: <br />\n";
echo $r->OrderInfo->WayBill;

The result of this is the following:

Get Consignee->Id: 
18404
Get Goodsinfo->number of items: 
1
The WayBill is: 
73325389902538911

As you can see it's actuallly very easy to get the information using PHP's SoapClient. The next I'm going to do is to create an order.

1. Creating an order

We're going to connect to the WSDL the same way as explained over using the SoapClient class. And like the last time we're using the member-function __soapCall, that takes at least 2 params. This time we're going to use the service/function "ProcessOrder". The parameters I'm sending to the SOAP-server this time is a little bit more complex, but in general it's the same thing except that the I'm sending alot more data, The data I'm sending is actually from an xml-document that I have to convert to an array. See code below:

$xml = simplexml_load_file("create_order.xml");
$xarray = json_decode(json_encode($xml), TRUE);
$parameters = array("GoodsOwnerCode" => "goodsowner_code",
			"UserName" => "username",
			"Password" => "password",
			"co" => $xarray,
);
$res = $Ongoing->__soapCall($processOrder, array($parameters));

1. Load the xml file by using the php-function simplexml_load_file

2. Encode the xml-data to a JSON encoded value, and then decode that JSON value to a PHP array.

3. Send the data.

The order is created and we get a result sent from the server. We check:

$p = $res->ProcessOrderResult;
if($p->Success == 1)
{
	echo "Processing the order was a success..<br />\n";
	echo "GoodsOwnerOrderNumber: ".$p->GoodsOwnerOrderNumber."<br />\n";
	echo "InorderId: ".$p->InOrderId."<br />\n";
	echo "ArticleDefId: ".$p->ArticleDefId."<br />\n";
	echo "Message: ".$p->Message."<br />\n";
}

The result of this is the following

GoodsOwnerOrderNumber: 888sdfsdf
InorderId: 0
ArticleDefId: 
Message: Customer with customer number '31750' and ID '27475' created. 

Order number 888sdfsdf created/updated

 

Using the SUDS library (python)

1. Getting the order
I'm not going to explain this. It works the same way as the PHP methods. See code below

#!python
from suds.client import Client
url = 'https://url_to_wsdl/service.asmx?WSDL'
client = Client(url)
res = client.service.GetOrderByOrderNumber('goods_owner', 'username', 'password', 'goodsowner_ordernumber')
print 'Consignee-Id is:'
print res.Consignee.Id
print '\n'
print 'Waybill is:'
print res.OrderInfo.WayBill

The only difference as I can see it is that (line 5) is that there's allready a servicename/function implemented after a successfull creation of the client-object.

The result of that code is the following:

Consignee-Id is:
18404

Waybill is:
73325389902538911

2. Creating an order using SUDS

As with the PHP example I'm getting my data fropm an xml-file. This file has to be parsed and made into an object that represents the xml-data which SOAP-server understands. For python I found a a library called lxml. It has a class that can "objectify" xml-data. So we have to add the these libraries to our script. See code below:

#!python
from suds.client import Client

from lxml import etree
from lxml import objectify

url = 'https://url_to_wsdl/service.asmx?WSDL'
client = Client(url)

Then we create the object that we're going to send to the server:

xml_obj = objectify.parse(open('create_order.xml', 'r')).getroot()

We then send the data that we've created using the service 'ProcessOrder' which is defined by the SOAP-server(and created locally in the object "client" of class-type Client):

res = client.service.ProcessOrder('goodsowner_code', 'username', 'password', 'xml_obj')

To verify the data I print out some data:

print 'The returned message is saved in a class called \"FileResultClass\"'
print 'Printing \"res\" results in this:'
print res
print"OrderId: ", res.OrderId
print 'Message of resource is this: ',res.Message

The last code results in this:

vxdwbsrvr:~/tests # python create_order.py
The returned message is saved in a class called "FileResultClass"
Printing "res" results in this:
(FileResultClass){
   ErrorMessage = None
   OrderId = 21329
   InOrderId = 0
   ArticleDefId = None
   Success = False
   Message = "Order already exists and is not allowed to be updated because of its order status. OrderId: 21329"
 }
OrderId:  21329
Message of resource is this:  Order already exists and is not allowed to be updated because of its order status. OrderId: 21329

As we can see the methods are the same in both PHP and Python, and when the SOAP-server is well-documented it's actually quite easy to both get and create data on the remote server.