Connection Between PHP And MS CRM

This time we will learn how to connect Microsoft Dynamics CRM using PHP code. Microsoft dynamics CRM soap service can be a way to make calls from PHP source code. A valid soap header is required to execute soap request. Let’s see how to create a valid header using PHP code:

To get a valid soap request, first need to create token1, token2, and keyIdentifer which can be created using online user name and password.

Soap envelope for getting token1, token2, ekyidentifer:

$xml = "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">";
$xml .= "<s:Header>";
$xml .= "<a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>";
$xml .= "<a:MessageID>urn:uuid:" . $this->newGUID () . "</a:MessageID>";
$xml .= "<a:ReplyTo>";
$xml .= "<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>";
$xml .= "</a:ReplyTo>";
$xml .= "<a:To s:mustUnderstand=\"1\">https://login.microsoftonline.com/RST2.srf</a:To>";
$xml .= "<o:Security s:mustUnderstand=\"1\" xmlns:o=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">";
$xml .= "<u:Timestamp u:Id=\"_0\">";
$xml .= "<u:Created>" . gmdate ( 'Y-m-d\TH:i:s.u\Z', $now ) . "</u:Created>";
$xml .= "<u:Expires>" . gmdate ( 'Y-m-d\TH:i:s.u\Z', strtotime ( '+60 minute', $now ) ) . "</u:Expires>";
$xml .= "</u:Timestamp>";
$xml .= "<o:UsernameToken u:Id=\"uuid-" . $this->newGUID () . "-1\">";
$xml .= "<o:Username>" . $username . "</o:Username>";
$xml .= "<o:Password>" . $password . "</o:Password>";
$xml .= "</o:UsernameToken>";
$xml .= "</o:Security>";
$xml .= "</s:Header>";
$xml .= "<s:Body>";
$xml .= "<trust:RequestSecurityToken xmlns:trust=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">";
$xml .= "<wsp:AppliesTo xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">";
$xml .= "<a:EndpointReference>";
$xml .= "<a:Address>urn:" . $urnAddress . "</a:Address>";
$xml .= "</a:EndpointReference>";
$xml .= "</wsp:AppliesTo>";
$xml .= "<trust:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</trust:RequestType>";
$xml .= "</trust:RequestSecurityToken>";
$xml .= "</s:Body>";
$xml .= "</s:Envelope>";

In response, you will get element “CipherValue” which has both tokens which you can fetch from response. See sample code:

$response = curl_exec($ch);
curl_close($ch);
$responsedom = new DomDocument();
$responsedom - > loadXML($response);
$cipherValues = $responsedom - > getElementsbyTagName("CipherValue");
$token1 = $cipherValues - > item(0) - > textContent;
$token2 = $cipherValues - > item(1) - > textContent;

Next is to get KeyIdentifier value which you can get using “KeyIdentifier” element name from response.

$keyIdentiferValues = $responsedom->getElementsbyTagName ( "KeyIdentifier" );

Now need to get online header using token1, token2, and KeyIdentifier. Below you can see example of header XML for Soap request:

$xml = "<s:Header>";
$xml .= "<a:Action s:mustUnderstand=\"1\">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute</a:Action>";
$xml .= "<Security xmlns=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">";
$xml .= "<EncryptedData Id=\"Assertion0\" Type=\"http://www.w3.org/2001/04/xmlenc#Element\" xmlns=\"http://www.w3.org/2001/04/xmlenc#\">";
$xml .= "<EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#tripledes-cbc\"/>";
$xml .= "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">";
$xml .= "<EncryptedKey>";
$xml .= "<EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p\"/>";
$xml .= "<ds:KeyInfo Id=\"keyinfo\">";
$xml .= "<wsse:SecurityTokenReference xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">";
$xml .= "<wsse:KeyIdentifier EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\" ValueType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier\">" . $keyIdentifer . "</wsse:KeyIdentifier>";
$xml .= "</wsse:SecurityTokenReference>";
$xml .= "</ds:KeyInfo>";
$xml .= "<CipherData>";
$xml .= "<CipherValue>" . $token1 . "</CipherValue>";
$xml .= "</CipherData>";
$xml .= "</EncryptedKey>";
$xml .= "</ds:KeyInfo>";
$xml .= "<CipherData>";
$xml .= "<CipherValue>" . $token2 . "</CipherValue>";
$xml .= "</CipherData>";
$xml .= "</EncryptedData>";
$xml .= "</Security>";
$xml .= "<a:MessageID>urn:uuid:" . $this->newGUID () . "</a:MessageID>";
$xml .= "<a:ReplyTo>";
$xml .= "<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>";
$xml .= "</a:ReplyTo>";
$xml .= "<a:To s:mustUnderstand=\"1\">" . $url . "XRMServices/2011/Organization.svc</a:To>";
$xml .= "</s:Header>";

CRM URN Address based on the Online region of customer. You can use this function to get correct URN:

function GetUrnOnline($url) {
    if (strpos(strtoupper($url), "CRM2.DYNAMICS.COM")) {
        return "crmsam:dynamics.com";
    }
    if (strpos(strtoupper($url), "CRM4.DYNAMICS.COM")) {
        return "crmemea:dynamics.com";
    }
    if (strpos(strtoupper($url), "CRM5.DYNAMICS.COM")) {
        return "crmapac:dynamics.com";
    }
    if (strpos(strtoupper($url), "CRM6.DYNAMICS.COM")) {
        return "crmoce:dynamics.com";
    }
    if (strpos(strtoupper($url), "CRM7.DYNAMICS.COM")) {
        return "crmjpn:dynamics.com";
    }
    if (strpos(strtoupper($url), "CRM9.DYNAMICS.COM")) {
        return "crmgcc:dynamics.com";
    }
    return "crmna:dynamics.com";
}

Using header you can connect Dynamics CRM from PHP code. See example code lines to get list data from PHP code:

// Get Dynamics CRM Online Header
$url = "https://org.crm.dynamics.com/";
$username = "user@dynamics.net";
$password = "password";

$dynamicsCrmHeader = new DynamicsCrmHeader ();
$authHeader = $dynamicsCrmHeader->GetHeaderOnline ( $username, $password, $url );
// Get Dynamics CRM Online Header

Soap request for getting list:

$xml .= "<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\">";
			$xml .= $authHeader->Header;
			$xml ="<s:Body>";
			$xml .="<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
			$xml .="<request i:type=\"a:RetrieveMultipleRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
			$xml .="<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
			$xml .="<a:KeyValuePairOfstringanyType>";
            $xml .="<b:key>Query</b:key>";
            $xml .="<b:value i:type=\"a:QueryExpression\">";
            $xml .="<a:ColumnSet>";
            $xml .="<a:AllColumns>true</a:AllColumns>";
            $xml .="<a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
            $xml .="</a:Columns>";                
            $xml .="</a:ColumnSet>";
			$xml .= "<a:Criteria>";
            $xml .= "<a:Conditions />";
            $xml .= "<a:FilterOperator>And</a:FilterOperator>";
            $xml .= "<a:Filters />";
            $xml .= "</a:Criteria>";
            $xml .="<a:Distinct>false</a:Distinct>";
            $xml .="<a:EntityName>list</a:EntityName>";
            $xml .="<a:LinkEntities />";
            $xml .="<a:Orders />";
            $xml .="<a:PageInfo>";
            $xml .="<a:Count>0</a:Count>";
            $xml .="<a:PageNumber>0</a:PageNumber>";
            $xml .="<a:PagingCookie i:nil=\"true\" />";
            $xml .="<a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>";
            $xml .="</a:PageInfo>";
            $xml .="<a:NoLock>false</a:NoLock>";
            $xml .="</b:value>";
			$xml .="</a:KeyValuePairOfstringanyType>";
			$xml .="</a:Parameters>";
			$xml .="<a:RequestId i:nil=\"true\" />";
			$xml .="<a:RequestName>RetrieveMultiple</a:RequestName>";
			$xml .="</request>";
			$xml .="</Execute>";
			$xml .="</s:Body>";
			$xml .= "</s:Envelope>";

You need to make soap call and convert response as DomDocument.

$client = new DynamicsCrmSoapClient();
$response = $client - > ExecuteSOAPRequest($xml, $url);
//echo $response;
$responsedom = new DomDocument();
$responsedom - > loadXML($response);

Please find code sample here: https://github.com/stw-services/Dynamics-CRM/tree/master/PHP-MSCRM

Thanks for reading :)