This project aims to illustrate the functionality required for a custom CRM to integrate with SocialSignIn.
Within the SocialSignIn application, head to https://app.socialsignin.net/#/settings/inbox and add a Custom CRM integration.
- Name - something of your choosing
- Search Endpoint URL - https://myserver.example.com/search
- Search Endpoint Secret - LongStringlyThingOfYourChoosing (aka SECRET)
- Iframe Endpoint URL - https://myserver.example.com/iframe
- Iframe Endpoint Secret - LongStringlyThingOfYourChoosing (aka SECRET)
( For this integration, the Search and Iframe Endpoint Secrets need to be the same, replace 'myserver.example.com' with a real hostname you have assigned to your deployment of this code ).
When SocialSignIn make requests on your integration, the requests are signed with a shared secret (SECRET) which you can check against, to ensure a third party isn't trying to access your pipedrive data.
You define this secret when adding the CRM integration within SocialSignIn. It can be a string of any length (although as with all passwords, longer is generally better).
docker build -t crm-integration-image .
docker run -e SECRET=changeme --rm --name crm-integration crm-integration-image
Code should work on a generic-ish PHP 7.1 Linux server if you wish to deploy it manually. Sufficient setup instructions should be within the Dockerfile
.
It requires a SECRET environment variable to be set.
The SECRET environment variable is used to verify that SocialSignIn made the CRM request, and for SocialSignIn to verify responses.
The signing works by adding a sha256 hash_hmac query parameter on all requests (see: http://php.net/hash\_hmac )
You can choose to ignore this parameter if you so wish.
Any third party / custom integration needs to support the following :
- GET request, with signed parameters (see SECRET above)
- Endpoint is specified by you when adding the integration
- Parameter 'q' contains the search string.
- Return json (application/json mimetype).
- e.g. https://my.integration.com/search?q=bob
Assuming a shared secret of 'changeme!'
A request from SocialSignIn searching for users matching 'red' might look like :
GET $CustomUrl?q=red&expires=1500472622&sig=7c9a0a55dc2d1542ec736b8021f048da114fcba11ca1fb0219c122dfd789e48c HTTP/1.1
Host: ....
Accept: application/json
Where :
- expires - unix timestamp with a small TTL value added.
- sig - sha256 hash of GET query (q=red&expires=12345678)
- q - search term
You should check that the expires value in the URL is greater or equal to your current system timestamp.
You should check that the signature is valid.
$our_timestamp = time();
// ... logic to check existance of expires/sig parameters in query string.
$url = parse_str($_SERVER['QUERY_STRING'], $params);
$actual_sig = $params['sig'];
$request_time = $params['expires'];
if($request_time < $our_timestamp) {
// request from too long ago?
}
unset($params['sig']);
// hash_hmac('sha256', 'q=red&expires=1500472622', 'changeme!');
$expected_sig = hash_hmac('sha256', http_build_query($params) , 'changeme!');
if($expected_sig != $actual_sig) {
// handle error
}
{
"results" : [
{ "id": 1, "name": "Susan Red"} ,
{ "id": 4, "name": "Frank Redford"}
]
}
- GET request, with signed parameters
- Endpoint is specified by you when adding the integration
- Returns HTML (iframe content).
GET $CustomUrl/iframe?id=12345&expires=1234567&sig=hashhashhash HTTP/1.1
Host: .....
- You should verify the 'sig' URL parameter is correct (see above)
- You should verify the 'expires' URL parameter is greater or equal to the current system time.
HTML to render the user, as determined by your internal requirements.
For example :
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Some user</title>
</head>
<body>
<h1>Fred Bloggs</h1>
<p>Fred <a href="https://internal.crm/employee?id=12345">crm</a></p>
<p>Email: [email protected]</p>
<p>Sales (2017): £390.46</p>
<p>Sales (2016): £39.42</p>
<h2>Notes</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce magna magna, convallis quis auctor bibendum, rutrum ut risus. Nulla dictum pulvinar turpis id sodales. Maecenas gravida quam nibh, accumsan egestas nisl mattis ut.</p>
</body>
</html>
This is rendered as an iframe within the SSI webapp.