MS NAV Web Services to/from PHP, receiving and sending data
Some time ago I came across a project where I had to connect MS’NAV and Drupal, two completely different systems one is proprietary (hello MS) and another is PHP & MySql (welcome, open source!)
There where few options how both systems could communicate automatically, but unfortunately REST was not available as an option on the MS’NAV version I had to connect to, so I was left with only option – SOAP.
Don’t get me wrong – I’ve developed multiple SOAP services in Java and PHP, used different libraries, so I am not new to the technology. I do have my own opinion about it and consider it slightly “redundant”, but… in this case I didn’t have much choice.
So… connecting MS’NAV and PHP via SOAP, with NTLM authentication on NAV side:
First of all I came across this really nice article http://blogs.msdn.com/b/freddyk/archive/2010/01/19/connecting-to-nav-web-services-from-php.aspx – we’ve set-up authentication in NAV, had few services exposed and everything seemed to work as expected (unfortunately only for receiving data from NAV).
Biggest problem, when I tried to insert data into NAV – was following error message:
Start tag expected, '<' not found
or this one:
The Element is expected by Min Occurs value: Once. Element received: .
It cost me at least a day and a half, not mentioning the time spend on the “other side of things”, but I have finally found my solution. Main problem is – MS have it’s own “vision” of how SOAP should look like, so don’t be surprised too much, with a “strange” parameter names 😉
You can download class I’ve modified/developed here.
Basic usage sample here (please note that you have to configure NAV to accept NTLM and so on, as described in the article from FreddyK above and also have soap module enabled in PHP):
require('nav_soap_client.php'); // or... die it's not gonna work without it anyway
class commerce_nav_crons{
function __construct() {
$this->service_url_main = 'http://192.168.1.111:7047/DynamicsNAV/WS'; // just a sample - i read it from db
// we unregister the current HTTP wrapper
stream_wrapper_unregister('http');
// we register the new HTTP wrapper
stream_wrapper_register('http', 'NTLMStream') or die("Failed to register protocol");
define('USERPWD', 'your_domain\your_username:your_password'); // put your own values - mine are actually taken from db
}
function __destruct() {
// restore the original http protocole
stream_wrapper_restore('http');
}
/**
*
* this is a main run function to send Order Returns to NAV, very basic, just to illustrate sample
*
* @return bool
*/
function sample_run(){
$ret = FALSE;
$service_url = $this->service_url_main.'/Codeunit/Drupal_CreateSalesReturnOrder';
$service_params = array(
'trace' => TRUE,
'cache_wsdl' => WSDL_CACHE_NONE,
);
$service = new NTLMSoapClient($service_url, $service_params);
$service->fuck_you_ms = TRUE; // because fuck you, that's why!
$params['drupalSRO']['ReturnOrderDetails']['OrderNo'] = 'W0000111';
$params['drupalSRO']['ReturnOrderDetails']['CustNo'] = 'C0000142';
$params['drupalSRO']['ReturnOrderDetails']['ContactNo'] = 'CC000023';
$params['drupalSRO']['ReturnOrderDetails']['OrderType'] = 'WEB';
// @start: ************* RUN LOLA RUN !!!! **************************
try{
$result = $service->CreateSRO($params);
if($result->return_value == 1){ // this is actually defined on NAV side
$ret = TRUE;
}
}catch(Exception $e){
// here should be some nice debugging if you want
echo "<hr><b>ERROR: SoapException:</b> [".$e."]<hr>";
echo "<pre>".htmlentities(print_r($service->__getLastRequest(),1))."</pre>";
}
// @end: ************* RUN LOLA RUN !!!! **************************
return $ret;
}
}
Right, what you have to do is to instantiate my class commerce_nav_crons and run function sample_run, something like that:
$cl = new commerce_nav_crons();
if($cl->sample_run()){
echo 'OK';
}else{
echo 'SHIT';
}
Please note of the parameter – it can be omitted as soon as you sure your soap service on NAV side is not going to change:
'cache_wsdl' => WSDL_CACHE_NONE,
And most important one here, that actually run extra processing BEFORE SOAP envelope and everything is being send to MS’NAV (it’s hacking in it’s core – but I found that this actually solves the problems and believe me – I spend LOTS OF TIME figuring out best solution:
$service->fuck_you_ms = TRUE; // because fuck you, that's why!
That’s all folks! THE END
In: Drupal, English, Fighting the system · Tagged with: microsoft, MS'NAV, SOAP
on May 7, 2013 at 07:09