If life gives you lemons, you make lemonade. If you don't have lemons, you plant the damn tree!
In this case, if a supplier doesn't have a solution all ready for you to import into your CRM Dynamics, then you implement the integration on your own using their API.
In most cases, they want you to validate your actions and in this article I'll try to explain how to do this when it requires Bearer Tokens.
This has been written with usage with CRM Dynamics in mind, but because this is Javascript, it can also be applied in any other web application.
Why Javascript and not C#?
I find both languages have their advantages and disadvantages.
C# plugins don't tend to play well with real-time changes in my experience and when you need things to happen the moment someone changes a field value then Javascript is your man.
I tend to use C# for mostly plugins that have to do something on Create, Delete or Update, so mostly work that can be done in the background while the user does other stuff.
What are bearer tokens and why are they needed?
Tokens are needed to validate your identity, most companies don't want everyone to take advantage of their services for free.
To keep it simple, a bearer token looks like a huge line with random gibberish in it. like this:
lasjdfasoidfj0)(@1lkajdflkasjdfla/dsfasdf12903)!alsdfjaslfkja0120(!)91023912ladlfasldfsaldfj
These tokens are designed to last a certain amount of time before they expire. After that, you will be required to request a new Token.
In almost every case, the token response is returned in a JSON format.
How do I generate one?
First, you need a couple of things
- The Weburl to the API to request authentication
Either the company that sold you the service provides this or they have API documentation showing you this - Username
- Password
Next you need to create a function that specifically requests a token, here's an example:
async function requesttoken() {
var url = "https://somewebsite/v1/authenticate";
var req = new XMLHttpRequest();
req.open("POST", url, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json");
return new Promise(function(resolve, reject) {
req.onreadystatechange = function () {
if (req.readyState === 4) {
var resp = JSON.parse(req.responseText);
resolve(resp.token);
}};
var data = `{
"username": "username here",
"password": "password here"
}`;
req.send(data);
})
}
Most of it is self explanatory. As you can see we are using XMLHttpRequest to make these calls.
Mayby you can already tell, it's a async function. This means the function will be run asynchronous and is a requirement for "Promises" to work that I will explain a bit later.
Because we want to get a token, in the req.open
line we send a POST request with the url variable and make it asynchronous. I prefer these to wait in line because this function will be called upon by other functions to do work.
Next we set the headers, all we need to do, is tell it to accept the JSON format and the type of content we are sending to the server.
Because of the way Javascript works, it will wait for no-one when you call other functions. Therefore you need to tell functions to "wait".
If you do not, what will basically happen is this:
- You call a function to request data from the server
- You call the Requesttoken function in a previous function
- Requesttoken is busy getting the token
- Meanwhile your first function is still running through every line in your code and when you code asks for a Bearer Token, it's empty because the Requesttoken function is not done
And thus your whole script fails. To make it wait, we will use what is called "Promises" in Javascript. Just like the name says, you make other functions "promise" to call back with a response, this can either be a success or fail and you can then proceed to code different actions based on the results.
In our case, on success it will parse the JSON results into something readable, gets the token value and will pass it as an output when the function is called.
I have a token now, how do I use it to get data?
It isn't much different from getting the token really. Most API documentation explain what endpoint provides what data and what information you need to put in the URL like for a filter or search for example.
First off create a new function and make sure it's async too like this:async function getdata()
and in that function call your token request function like this:const token = await creditsafetokenreq();
Next you need to replace a few headers:req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Authorization", "Bearer" " + token);
With this, every request you make will have a valid generated token and will pass the authentication checks. As long your username/password checks out in the first function ;)
Ok, I got in. But how do I get my data?
Right below the header code, you can add this as a base
req.onreadystatechange = function () {
if (req.readyState === 4) {
var resp = JSON.parse(req.responseText);
if (req.status >= 200 && req.status <= 299) {
}
} else {
}
}
};
req.send();
This code checks if the request is has been sent and a proper response has been recieved, this response could be good or bad!
No matter what, it will contain a response and it needs to be parsed and that's what the JSON.parse is for.
Then it checks the status code of the response, 200 to 299 codes are always positive so I check for those.
If it doesn't match with a code between 200 to 299 then I assume it's an error and it will then go to the else block.
From this point on, it really depends on how the JSON data you need is formatted. But here's a easy way to parse through the data even if the JSON contains nested data.
Let's say your JSON looks like this{
"correlationId": "f242a4a0-e481-11eb-ba81-02cf8dfb73a1",
"totalSize": 1,
"companies": [
{
"id": "NL-X-141272930000",
"country": "NL",
"regNo": "141272930000",
"safeNo": "NL00724500",
"name": "TEST",
"tradingNames": [
"TEST"
],
"address": {
"simpleValue": "Vrijheidstraat, 21 D, 4902BC, OOSTERHOUT",
"street": "Vrijheidstraat",
"city": "OOSTERHOUT",
"postCode": "4902BC",
"houseNo": "21 D"
},
"status": "Active",
"officeType": "headOffice",
"dateOfLatestChange": "2020-08-08T01:25:00.000Z",
"phoneNumbers": [
"0844309888"
],
"activityCode": "86231",
"statusDescription": "Active"
}
]
}
for (var i = 0; i <resp.companies.length; i++) {
var company = resp.companies[i];
}
if you need the status for example, then use company.status
, this will contain only the status.
If you need the nested data like the address then you do it like this: company.address.street
.