I would like to create new contacts and leads using php. I can't quite figure out how to call the methods of the mscrm 3 web service.
The php soap class seems quite simple to use. I am able to connect and authenticate to the crm web service and get a list of available functions however I am unsure how to go about calling them.
I have seen examples for mscrm 4.0 which seem to involve masses of XML including soap headers and envelopes.
I am under the impression that using a soap class bypasses this and will write all the extra xml for me so all I need to do is call a function with an array of parameters?
Am I completely wrong here ?
Has anyone done this with mscrm 3 that can provide some sample code, or perhaps give me a few pointers as how to correctly call the Create() method ?
I have been able to get this working by using Nusoap and after construction the XML message as a series of strings using the send method instead of call. This now works as expected. It seemed that using the call method was returning different XML than what was required by the ms crm 3 web service.
Any decent SOAP toolkit will automagically spit out the correct XML. Check out this guy:
http://us2.php.net/xmlrpc_encode_request
require_once ('/var/mtp/lib/vendor/nusoap/lib/nusoap.php');
$login ='domain\username';
$pass ='password';
$useCURL = true;
$client = new nusoap_client('http://server:5555/mscrmservices/2006/crmservice.asmx?wsdl', 'wsdl');
$client->setCredentials($login, $pass, 'ntlm');
$client->setUseCurl($useCURL);
$client->useHTTPPersistentConnection();
$client->soap_defencoding = 'UTF-8';
$err = $client->getError();
if ($err) {
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';
exit();
}
$soapHeader='<soap:Header>' .
'<CallerId xmlns="http://schemas.microsoft.com/crm/2006/WebServices">'.
'<CallerGuid xmlns="http://schemas.microsoft.com/crm/2006/CoreTypes">00000000-0000-0000-0000-000000000000</CallerGuid></CallerId>' .
'</soap:Header>';
$soapBody='<soap:Body>' .
'<entity xmlns="http://schemas.microsoft.com/crm/2006/WebServices" xsi:type="lead">' .
'<ownerid type="Owner">2408c7dc-c0a3-dd11-b3cd-001a4bd3009a</ownerid>' .
'<firstname>Fred</firstname>' .
'<lastname>Bloggs</lastname>' .
'</entity>' .
'</soap:Body>';
$xml = '<?xml version="1.0" encoding="utf-8"?>' .
'<soap:Envelope' .
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' .
' xmlns:xsd="http://www.w3.org/2001/XMLSchema"' .
' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' .
$soapHeader .
$soapBody .
'</soap:Envelope>';
//SOAP call
$result = $client->send($xml,'http://schemas.microsoft.com/crm/2006/WebServices/Create' );
//result
if ($client->fault) { //check for fault
echo '<p><b>Fault: ';
print_r($result);
echo '</b></p>';
}
else { //no fault
$err = $client->getError();
if ($err) { // error
echo 'Error: ' . $err . '';
echo "\n\n# # # # # # # Request # # # # # # #\n";
var_dump($client->request);
echo "\n\n# # # # # # Response # # # # # # #\n";
var_dump($client->response);
}
else { // display the result
print_r($result);
}
}
I was also struggling to get Dynamics CRM SOAP working with PHP but after a while I managed to get it working; http://www.ifc0nfig.com/working-with-microsoft-dynamics-crm-4-0-soap-interface-with-php-and-nusoap/ - You can download a small class I created which may be of use :)
Related
I might be asking the wrong question here, but I cant seem to figure out where this is coming form. I am using both the HTTP Request2 and NET URL2 libraries in order to send some GET request to the Vuforia web services. This all works fine, but everytime I send a request, it also shows said request on screen.
GET d41d8cd98f00b204e9800998ecf8427e Mon, 09 Dec 2019 22:49:52 GMT /summary/ba2246f8cd29466899c69b8d05af09a1
The code that I use to get the above text appear on screen is as follows.
Main code:
<?php if(sizeof($items) > 0){
foreach($items as $item){
echo '<tr>';
echo'<td>'.$item['itemid'].'</td>';
echo'<td>'.$item['name'].'</td>';
echo'<td>'.$item['surname'].'</td>';
echo'<td>'.$item['phone'].'</td>';
$recos = $targetdata = json_decode(CheckVuforiaTarget("ba2246f8cd29466899c69b8d05af09a1"), true);
echo'<td>'.$recos['current_month_recos'].'</td>';
}
} else echo '<tr><td>Geen kandidaten</td></tr>';?>
Script holding the CheckVuforiaTarget function:
function CheckVuforiaTarget($vuforiaid){
$vuforiaTargetTracker = new TargetTracker($vuforiaid);
$response = $vuforiaTargetTracker->TargetTracker();
return ($response);
//print_r($vuforiaResult);
}
TargetTracker class:
<?php
require_once 'HTTP/Request2.php';
require_once 'SignatureBuilder.php';
// See the Vuforia Web Services Developer API Specification - https://developer.vuforia.com/resources/dev-guide/retrieving-target-cloud-database
// The DeleteTarget sample demonstrates how to delete a target from its Cloud Database using the target's target id.
// * note that targets cannot be 'Processing' and must be inactive to be deleted.
class TargetTracker{
//Server Keys
private $access_key = "...";
private $secret_key = "...";
private $url = "https://vws.vuforia.com";
private $requestPath = "/summary/";
private $request;
private $targetId = "";
public function __construct($targetId) {
$this->targetId = $targetId;
}
function TargetTracker(){
$this->requestPath = $this->requestPath . $this->targetId;
return $this->execTargetTracker();
}
public function execTargetTracker(){
$this->request = new HTTP_Request2();
$this->request->setMethod( HTTP_Request2::METHOD_GET );
$this->request->setConfig(array('ssl_verify_peer' => false));
$this->request->setURL( $this->url . $this->requestPath );
$this->setHeaders();
try {
$response = $this->request->send();
if (200 == $response->getStatus()) {
return $response->getBody();
} else {
//echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
// $response->getReasonPhrase(). ' ' . $response->getBody();
return $response->getBody();
}
} catch (HTTP_Request2_Exception $e) {
return $e->getMessage();
}
}
private function setHeaders(){
$sb = new SignatureBuilder();
$date = new DateTime("now", new DateTimeZone("GMT"));
// Define the Date field using the proper GMT format
$this->request->setHeader('Date', $date->format("D, d M Y H:i:s") . " GMT" );
// Generate the Auth field value by concatenating the public server access key w/ the private query signature for this request
$this->request->setHeader("Authorization" , "VWS " . $this->access_key . ":" . $sb->tmsSignature( $this->request , $this->secret_key ));
}
}
?>
Both HTTP/Request2.php(and everything it came with) and SignatureBuilder.php are both default scripts/classes I've downloaded from the internet without altering them.
Now with my basic understanding of PHP, i've tried to find anything related to an echo or whatever command would show this on screen, but I can't seem to find it.
Does someone have some pointers for me, so I can figure out the source?
Thanks in advance!
The code you provided has no echo/print output that would explain the message you see. The echo/print statement must be somewhere else.
I am trying to develop an application that uses the ListMatchingProducts method.
The end result will be an application that searches for a given product which is already in an internal stock database and present the results to the user so they can select which Amazon product is a correct match for the one in their database.
The PHP Client Library I found is linked here.
I have edited Samples/.config.inc.php correctly (I have removed the comments and redacted the sensitive information):
define('AWS_ACCESS_KEY_ID', '/*REDACTED BUT SET CORRECTLY*/');
define('AWS_SECRET_ACCESS_KEY', '/*REDACTED BUT SET CORRECTLY*/');
define('APPLICATION_NAME', 'STES_MWS_STOCK_SYNC_APP');
define('APPLICATION_VERSION', '0.1');
define ('MERCHANT_ID', '/*REDACTED BUT SET CORRECTLY*/');
define ('MARKETPLACE_ID', 'A1F83G8C2ARO7P'); // Marketplace ID for the UK
I have also uncommented the appropriate line in Samples/ListMatchingProductsSample.php:
$serviceUrl = "https://mws-eu.amazonservices.com/Products/2011-10-01";
Executing this script, however, yeilds the following message (I've redacted some of the XML response):
Caught Exception: Required parameter MarketplaceId not found
Response Status Code: 400
Error Code: MissingParameter
Error Type: Sender
Request ID: /*REDACTED UUID-LIKE STRING*/
XML: <?xml version="1.0"?>
<ErrorResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01"><Error><Type>Sender</Type><Code>MissingParameter</Code><Message>Required parameter MarketplaceId not found</Message><Detail/></Error><RequestID>/*REDACTED UUID-LIKE STRING*/</RequestID></ErrorResponse>
ResponseHeaderMetadata: RequestId: /*REDACTED UUID-LIKE STRING*/, ResponseContext: /*REDACTED LONG STRING*/, Timestamp: 2017-04-24T13:25:33.533Z, Quota Max: 719.0, Quota Remaining: 719.0, Quota Resets At: 2017-04-24T14:03:00.000Z
As this client library has been around since 2011 I find it difficult to believe this is actually incorrect code in the sample, but I can't seem to find where I've gone wrong; scanning through the code I can't find a reference to the MARKETPLACE_ID constant defined in Samples/.config.inc.php
Before I write my own client library (which I had hoped to avoid for such a simple app) I wondered:
Has anyone else had come across this problem and fixed it (and if so, how)?
Is there a newer version of the library I'm not finding?
Can anyone suggest an alternate library if this one really is broken?
-- EDIT --
For completeness, here is the code I am trying to run - the sample code - minus comments:
require_once('.config.inc.php');
$serviceUrl = "https://mws-eu.amazonservices.com/Products/2011-10-01";
$config = array (
'ServiceURL' => $serviceUrl,
'ProxyHost' => null,
'ProxyPort' => -1,
'ProxyUsername' => null,
'ProxyPassword' => null,
'MaxErrorRetry' => 3,
);
$service = new MarketplaceWebServiceProducts_Client(
AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
APPLICATION_NAME,
APPLICATION_VERSION,
$config);
$request = new MarketplaceWebServiceProducts_Model_ListMatchingProductsRequest();
$request->setSellerId(MERCHANT_ID);
invokeListMatchingProducts($service, $request);
function invokeListMatchingProducts(MarketplaceWebServiceProducts_Interface $service, $request)
{
try {
$response = $service->ListMatchingProducts($request);
echo ("Service Response\n");
echo ("=============================================================================\n");
$dom = new DOMDocument();
$dom->loadXML($response->toXML());
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
echo $dom->saveXML();
echo("ResponseHeaderMetadata: " . $response->getResponseHeaderMetadata() . "\n");
} catch (MarketplaceWebServiceProducts_Exception $ex) {
echo("Caught Exception: " . $ex->getMessage() . "\n");
echo("Response Status Code: " . $ex->getStatusCode() . "\n");
echo("Error Code: " . $ex->getErrorCode() . "\n");
echo("Error Type: " . $ex->getErrorType() . "\n");
echo("Request ID: " . $ex->getRequestId() . "\n");
echo("XML: " . $ex->getXML() . "\n");
echo("ResponseHeaderMetadata: " . $ex->getResponseHeaderMetadata() . "\n");
}
}
Frankly it seems like the "samples" are a bit naff.
Looking at the code, it seems likely you need to set the marketplaceId manually, either in the constructor via an associative array or as a setter method call.
e.g.
$request->setMarketplaceId(MARKETPLACE_ID)
I am new to Web Services and am struggling to access/read the XML data using PHP (my website that will be using the data is in PHP).
The WSDL Url: http://services.mywheels.co.za/BWAVehicleStockService.svc?wsdl
I need to get access and read the Vehicle stock information but cant see to access anything.
the Array vehicle are stored under: http://services.mywheels.co.za/BWAVehicleStockService.svc?xsd=xsd2 .
i am using this code but it doesnt give my any data. I also have a GUID that i need to pass but have no idea how to add it to the header.
<?PHP
define('NEWLINE', "<br />\n");
// SOAP client
$wsdl = 'http://services.mywheels.co.za/BWAVehicleStockService.svc?wsdl';
$soapClient = new SoapClient($wsdl, array('cache_wsdl' => 0));
// SOAP call
$parameters->ArrayOfVehicle->Vehicle;
try
{
$result = $soapClient->GetVehicleStock($parameters);
}
catch (SoapFault $fault)
{
echo "Fault code: {$fault->faultcode}" . NEWLINE;
echo "Fault string: {$fault->faultstring}" . NEWLINE;
if ($soapClient != null)
{
$soapClient = null;
}
exit();
}
$soapClient = null;
echo "<pre>\n";
print_r($result);
echo "</pre>\n";
echo "Return value: {$result->GetDataResult}" . NEWLINE;
?>
if someone can help or point me in the right direction with this that would be great.
Thanks
You can add headers using __setSoapHeaders():
$h = new SoapHeader('http://tempuri.org/', 'Guid', '123');
$soapClient->__setSoapHeaders($h);
I had to read the WSDL itself to find out what namespace I should use; in this case they refer to Guid as tns:Guid and from the top you can read what URI is used to express that, hence http://tempuri.org.
Ok my .net 4.0 client works fine. People using java all have no issues. But when it comes to php our php developer cant get anything to work.
Now keep in mind i did not create a Wcflibray project, i created a regular asp 4.0 website and then added a WCF Service so i do not have a app.config, i have a web.config.
We have went down to the bare essentials of creating two methods
string HelloWorld()
{
return "Hello!";
}
and
string HellowTomorrow(string sret)
{
return sret;
}
In debug mode i will see him enter my method but only with null. If i packet sniff with wireshark, he is not passing the paramater envelope.
I have googled endlessly but all examples are from a WCF service project, not a website that has added a WCF Service too it. (rememember, everyone else is having no problems, java, .net 2.0, etc)
Here is his php 5.3
error_reporting(E_ALL);
ini_set('display_errors','On');
$client = new SoapClient("http://99-mxl9461k9f:6062/DynamicWCFService.svc?wsdl", array('soap_version' => SOAP_1_1));
$client->soap_defencoding = 'UTF-8';
//$args = array('john');
$args = array('param1'=>'john');
$webService = $client->__soapCall('HelloTomorrow',$args);
//$webService = $client->HelloTomorrow($args);
var_dumpp($webService);
?>
While working with WCF service .net as Server and PHP-soap as client you need to follow guideline strictly. The documentation of PHP-soap is not enough to debug and not that clear either. PHP nusoap is little better on documentation but still not enough on example and not a great choice for the beginners. There are a few examples for nusoap but most of them don’t work.
I would suggest following debug checklist:
Check the binding in your web.config file. It has to be “basicHttpBinding” for PHP
PHP, $client->__soapCall() function sends all arguments as an array so if your web-service function require input parameters as an array then arguments has to be in an extra array. Example#3 is given below to clear.
If required then pass “array('soap_version' => SOAP_1_1)” or “array('soap_version' => SOAP_1_2)” to SoapClient() object to explicitly declare soap version.
Always try declaring “array( "trace" => 1 )” to SoapClient Object to read the Request & Response strings.
Use “__getLastResponse();” function to read Response String.
Use “__getLastRequest();” function to read Request String.
IMPORTANT:If you are getting NULL return for any value passed as
parameter then check your .cs(.net) file that look like this:
[ServiceContract]
public interface IDynamicWCFService
{
[OperationContract]
string HelloYesterday(string test);
}
The variable name passes here, have to match with when you call it in PHP. I am taking it as “test” for my examples below.
Example #1: using php-soap with single parameter for HelloYesterday function
<?php
$url="http://99-mxl9461k9f:6062/DynamicWCFService.svc?WSDL";
$client = new SoapClient($url, array( "trace" => 1 ));
$result = $client->HelloYesterday(array('test' => 'this is a string'));
var_dump($result);
$respXML = $client->__getLastResponse();
$requXML = $client->__getLastRequest();
echo "Request: <br>";
var_dump($requXML);
echo "Response: <br>";
var_dump($respXML);
?>
Example #2 : using nusoap with single parameter for HelloYesterday function
<?php
require_once('../lib/nusoap.php');
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
$proxyusername = isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
$proxypassword = isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
$url="http://99-mxl9461k9f:6062/DynamicWCFService.svc?WSDL";
$client = new nusoap_client($url, 'wsdl', $proxyhost, $proxyport, $proxyusername, $proxypassword); $client->soap_defencoding = 'UTF-8'; // this is only if you get error of soap encoding mismatch.
$err = $client->getError();
if ($err) {
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
}
// Doc/lit parameters get wrapped
$param = array('test' => ' This is a string for nusoap');
$result = $client->call('HelloYesterday', array('parameters' => $param), '', '', false, true);
// Check for a fault
if ($client->fault) {
echo '<h2>Fault</h2><pre>';
print_r($result);
echo '</pre>';
} else {
// Check for errors
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
// Display the result
echo '<h2>Result</h2><pre>';
print_r($result);
echo '</pre>';
}
}
echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
?>
One more example… passing array as a parameter or pass mixed type parameter then check the following example:
Example #3: passing mixed type parameter including array parameter to Soap function.
Example of .net operation file
[ServiceContract]
public interface IDynamicWCFService
{
[OperationContract]
string[] HelloYesterday (string[] testA, string testB, int testC );
}
PHP code
<?php
$url="http://99-mxl9461k9f:6062/DynamicWCFService.svc?WSDL";
$client = new SoapClient($url, array( "trace" => 1 ));
$params = array(
"testA" => array(0=>"Value1",1=>"Value2",2=>"Value3"),
"testB" => “this is string abc”,
"testC" =>123
); // consider the first parameter is an array, and other parameters are string & int type.
$result = $client->GetData($params);
var_dump($result);
$respXML = $client->__getLastResponse();
$requXML = $client->__getLastRequest();
echo "Request: <br>";
var_dump($requXML);
echo "Response: <br>";
var_dump($respXML);
?>
Hope the above examples will help.
Since you're passing the wsdl location into the SoapClient constructor, you should be able to call $client->HelloTomorrow($args). There seem to be a few typos, though, can you verify that they are all correct in your actual code? In your web service code, you name the function HellowTomorrow but you're calling HelloTomorrow in your PHP code. Also, the parameter is named sret in your web service, but it's being passed as param1 in the $args associative array. Does it work calling HelloWorld() which doesn't expect any parameters?
Update:
See NuSOAP and content type
Try using the built-in PHP SoapClient instead of the NuSOAP version. PHP's SoapClient looks like it defaults to UTF-8, where NuSOAP seems to be hard-coded to ISO-8859-1
Just to be clear before continuing: using PHP's built-in SOAP class is unfortunately not an option here (production server's PHP is not built with it, and won't be).
I'm trying to use EWS to allow me to authenticate users for a completely external server application. LDAP authentication has been disallowed. I have verified my EWS wsdl is correct via http://www.testexchangeconnectivity.com/, a Microsoft autodiscover tool. The contents of the WSDL can be found here: http://pastebin.org/214070
The server is using SSL, and is using the default authentication method for EWS of "NTLM".
I've tried various code examples around the web, unfortunately I'm not well-versed in XML, SOAP, or cURL (which is pretty much all of the technology being used here). The current iteration of my code is found below:
<?php
include_once('./lib/nusoap.php');
$username = 'username#example.com';
$password = 'password';
$ews_url = 'https://owa.example.com/EWS/Exchange.asmx';
$soapclient = new nusoap_client($service, true);
$soapclient->setCredentials($username, $password, 'ntlm');
$soapclient->setUseCurl(true);
$soapclient->useHTTPPersistentConnection();
$soapclient->setCurlOption(CURLOPT_USERPWD, $username.':'.$password);
$soapclient->soap_defencoding = 'UTF-8';
$params = '<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"';
$params += ' xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" Traversal="Shallow">';
$params += ' <ItemShape>';
$params += ' <t:BaseShape>IdOnly</t:BaseShape>';
$params += ' <t:AdditionalProperties>';
$params += ' <t:FieldURI FieldURI="message:From"/>';
$params += ' <t:FieldURI FieldURI="item:Subject"/>';
$params += ' <t:FieldURI FieldURI="message:IsRead"/>';
$params += ' <t:FieldURI FieldURI="item:DateTimeReceived"/>';
$params += ' <t:FieldURI FieldURI="calendar:Start"/>';
$params += ' <t:FieldURI FieldURI="calendar:End"/>';
$params += ' <t:FieldURI FieldURI="calendar:Location"/>';
$params += ' <t:FieldURI FieldURI="task:Status"/>';
$params += ' <t:FieldURI FieldURI="task:DueDate"/>';
$params += ' </t:AdditionalProperties>';
$params += ' </ItemShape>';
$params += ' <IndexedPageItemView Offset="0" MaxEntriesReturned="5" BasePoint="Beginning"/>';
$params += ' <ParentFolderIds>';
$params += ' <t:DistinguishedFolderId Id="inbox"/>';
$params += ' </ParentFolderIds>';
$params += '</FindItem>';
$operation = 'FindItem';
$namespace = '';
$soapAction = '';
$headers = false;
$result = $soapclient->call($operation, $params, $namespace, $soapAction, $headers);
echo '<pre>'; print_r($result); echo '</pre>';
if($soapclient->fault){
echo 'FAULT: ';
echo '<pre>'; print_r($result); echo '</pre>';
}else{
$err = $soapclient->getError();
if ($err) {
echo '<p><b><u>Error</u>:</b><br />' . $err . '</p>';
}else{
echo 'Connection succeeded.';
}
}
?>
The actual issue I am having is that NuSOAP is returning a generic error message of: "no operations defined in the WSDL document!". From the looks of the WSDL, this seems incorrect and makes me believe I'm missing something in code. If I remove the actual client call in the code ($soapclient->call(...)), the code prints out "Connection succeeded.", but it does this with or without the attempted NTLM authentication code.
I've also tried using the "php-ews" project on my development machine (even though the same code would not work on the production server) and was also unable to access anything without receiving an error.
If anyone has any experience with any of these technologies and might be able to point out some clarification (or possible errors) I would greatly appreciate it. If any further clarification is needed on my part, please let me know.
UPDATE 1:
It seems one error in loading the WSDL is the NTLM Authentication. Using cURL alone (no NuSOAP) I was able to access the WSDL file and find out the server is redirecting to a different endpoint location (.../EWS/Services.wsdl).
Unfortunately, I've tried using the NuSOAP library's cURL ability and setting the same options through NuSOAP, and I am still getting the same generic error message as if NuSOAP is just unable to see/view/access the WSDL file. I believe it may still be NTLM Authentication as the cURL version takes a few moments to return (NTLM it a multi-step handshake process), whereas the NuSOAP client code is immediately returning the error message.
There's a few things you'll want to look at here.
There's an error in your call to the actual soap_client. You defined the endpoint in a variable called $ews_url, but then called the constructor with $service.
Why are you adding a string to a string in your $xml variable - perhaps in your haste you meant to concatenate instead? (operators: + vs .)
Using the following Wiki information directed to working with EWS in Java, it seems that Microsoft has yet again blundered in their implementation of a common protocol. The modification of types.xsd in this Wiki actually causes a problem, so ignore that change, but downloading a local copy of Services.wsdl and modifying it to point to your own server seems to work properly. http://www.bedework.org/trac/bedework/wiki/ExchangeWSlink text
The following code should work, so long as you have downloaded a local copy of your types.xsd, messages.xsd, and Services.wsdl - and modified the Services.wsdl file to add the required information relevant to your server. Make sure the local copies of those files are in the same folder on your server.
<?php
include_once('./lib/nusoap.php');
$username = 'username#example.com';
$password = 'password';
$endpoint = 'http://your.local.version/of/Services.wsdl';
$wsdl = true;
$soapclient = new nusoap_client($endpoint, $wsdl);
$soapclient->setCredentials($username, $password, 'ntlm');
$xml = '<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"';
$xml .= ' xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" Traversal="Shallow">';
$xml .= ' <ItemShape>';
$xml .= ' <t:BaseShape>IdOnly</t:BaseShape>';
$xml .= ' <t:AdditionalProperties>';
$xml .= ' <t:FieldURI FieldURI="message:From"/>';
$xml .= ' <t:FieldURI FieldURI="item:Subject"/>';
$xml .= ' <t:FieldURI FieldURI="message:IsRead"/>';
$xml .= ' <t:FieldURI FieldURI="item:DateTimeReceived"/>';
$xml .= ' <t:FieldURI FieldURI="calendar:Start"/>';
$xml .= ' <t:FieldURI FieldURI="calendar:End"/>';
$xml .= ' <t:FieldURI FieldURI="calendar:Location"/>';
$xml .= ' <t:FieldURI FieldURI="task:Status"/>';
$xml .= ' <t:FieldURI FieldURI="task:DueDate"/>';
$xml .= ' </t:AdditionalProperties>';
$xml .= ' </ItemShape>';
$xml .= ' <IndexedPageItemView Offset="0" MaxEntriesReturned="5" BasePoint="Beginning"/>';
$xml .= ' <ParentFolderIds>';
$xml .= ' <t:DistinguishedFolderId Id="inbox"/>';
$xml .= ' </ParentFolderIds>';
$xml .= '</FindItem>';
$operation = 'FindItem';
$result = $soapclient->call($operation, $xml);
echo '<pre>'; print_r($result); echo '</pre>';
?>
The solution all seems to stem from having a local copy of the main SOAP reference files, and fixing the Services.wsdl file. If you had access to the Exchange server, you might be able to modify the Services.wsdl file and everything could have worked as expected without all of this hassle. I cannot verify this, unfortunately.