Example Walkthrough
- Connecting to the Access MicrOpay Web API
- Doing your first GET
- Doing your first POST
- Error handling
-
Change Employee Request including
- Using a Lookup to get code and descriptions
- POST a Change Employee Request
- GET the Change Employee Status
- Reviewing an error
- Basic run through of other Access MicrOpay Web API calls
Connecting to the Access MicrOpay Web API
To continue you will need to have setup an account for the sandbox to the Access MicrOpay Web API (see Getting Started). This will give you access to a DB using an ApiKey, and a username password combination for use as a Software & Service Organisation provider.
The Access MicrOpay Web API uses SSL, meaning you will need to be able to connect to SSL for your use. This means if you are connecting from a web page that web site also needs to use SSL, and if you are connecting from backend code, you will need to be able to accept the Access MicrOpay SSL certificate.
Another potential hurdle for web site use of the Access MicrOpay Web API will be to enable CORS. This is something your program will need to implement to say it’s OK to access our Access MicrOpay Web API from within your site. Otherwise you will find browsers will often block access to our site. We will give some examples of this shortly.
The following will describe the steps involved for using your credentials to connect up. We will complete an entire API call from start to finish using jQuery, and explain the various steps along the way. Note this is purely for example, and not to be seen as production code.
The Access MicrOpay Web API implements a basic authentication, where the username and password is sent in the header of every request with the Authorization tag. Also added to the header is a custom tag called Api-Key. Both values are sent using Base 64 encoding.
Here is the raw message sent from a web page to the Access MicrOpay Web API where the username/password and Api-Key have been set to x’s:
GET https://tapi.micropay.com.au/api/Lookups?type=Location HTTP/1.1 Accept: application/json, text/json, */*; q=0.01 Content-Type: application/x-www-form-urlencoded Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Api-Key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx X-Requested-With: XMLHttpRequest Referer: https://TestServer/TestLookups.html Accept-Language: en-AU Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Host: tapi.micropay.com.au Connection: Keep-Alive
Let’s explain a few of the things above. Firstly, we are doing a GET here, where the API is Lookups, and we are passing a Type, to get all codes and descriptions for type Location. The 2nd line shows we are asking for JSON to be returned. XML can also be requested with Accept: application/xml, text/xml, */*; q=0.01. The Authorization line has the word Basic and then base 64 encodes username:password with the colon included, example code will follow. The next line has the custom header value Api-Key, which is base 64 encoded also. The rest is general connection information. You should be able to paste the above code with your base 64 encoded Authorization and Api-Key to get the following raw response:
HTTP/1.1 200 OK Content-Length: 570 Content-Type: application/json; charset=utf-8 Server: Microsoft-IIS/7.5 X-UA-Compatible: Edge Date: Fri, 12 Dec 2014 01:14:04 GMT [{"type":"Location","code":"Chatswood","description":"Chatswood","active":true},{"type":"Location","code":"George Street","description":"George Street","active":true},{"type":"Location","code":"Manly","description":"Manly","active":true},{"type":"Location","code":"Melbourne CBD","description":"Melbourne CBD","active":true},{"type":"Location","code":"Parramatta","description":"Parramatta","active":true},{"type":"Location","code":"St Kilda","description":"St Kilda","active":true},{"type":"Location","code":"Sydney Office","description":"Sydney Office","active":true}]
The above response returns a response code 200 OK and content type of JSON in the header, then the JSON data for Lookups with type Location.
Doing your first GET
Now we get to coding for the Access MicrOpay Web API. The following is purely for example purposes and should never be used in production code, as your username/password and API Key are fully visible by any user if they view page source in their browser.
This example is using jquery, so to start off we’ll put a reference to jquery, like this:
<script src="../Scripts/jquery-2.1.4.min.js"></script>
The following is the basic call using jquery, I’ll explain some of the code soon:
$.ajax( { url: 'https://tapi.micropay.com.au/api/Lookups?type=Location', type: 'GET', contentType: "application/x-www-form-urlencoded", dataType: 'text', cache: false, async: false, beforeSend: function (xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa("username:password")); // Basic authentication with supplied username and password xhr.setRequestHeader("Api-Key", btoa("{11111111-1111-1111-1111-111111111111}")); }, error: function(data) { if (data.status == 404) { message = data.statusText; alert(message); } else { var message = ""; if (data.responseText == undefined) { message = data.text; console.log(message); alert(message); } else if (data.responseText.length > 0) { var response = JSON.parse(data.responseText); if (response.exceptionMessage == undefined) { if (response.modelState == undefined) message += response.message; else { $.each(response.modelState, function (key, value) { $.each(value, function (i, msg) { message += ("\n" + msg); }); }); } } else { message = response.exceptionMessage; } if (response.Message == undefined) { console.log(message); alert(message); } else { console.log(response.Message + "\n" + message); alert(response.Message + "\n" + message); } } } }, success: function (data, status, response) { if (response.responseText != "") { var result = JSON.parse(response.responseText); $('<div> ', { text: JSON.stringify(result, null, 2) }).appendTo($('#results')); $('#response-info').show(); }; console.log(status, data, response); } });}
- The url here can be any of the API’s, where you can find a lot more information about the URL’s needed on the Access MicrOpay Web API Reference. An error of 404 Not Found would be a good indication you have mistyped something on the url.
- The type is a GET and could be a POST for many other calls you’ll be making
-
The setRequestHeader is used to add both the standard basic authentication and the custom Api-Key section. The basic authentication puts the username and password together separated by a colon. This string is Base64 encoded using the btoa function. The word “Basic“ is not encoded and added to the front with a space in between that and the password. For the Api-Key, the btoa function will Base64 encode the whole ApiKey you were given by Access MicrOpay Web API support. Without these, or with any mistyping or wrong setup, you will get Unauthorized.
- NOTE: This is a test example only to get you up and running quickly, you should NEVER put the username, password or Api-Key in plain javascript code.
- The error handler here will read the status code and responseText. responseText as seen here will be a JSON list of errors in a table called modelState. This may have more than one error row returned, so the example shows how you might add these multiple errors together to display all the errors the user got.
- The success handler gets back the JSON data expected which will obviously vary for the different API calls.
Doing your first POST
We’ll work through an example here where your Software & Service Organisation changes are posted to the Access MicrOpay database through our Access MicrOpay Web API. Again this is an example to demonstrate the POST, where thought hasn’t gone into the security or validation side of things.
We are going to do a Change Employee to an existing employee. We will provide the bare minimum information for this example, but will go into a lot more detail when looking to add a new employee.
Imagine this web page is a form. In this case, it’s implied you only have 2 inputs, but your real form would have name, address, whatever other details are likely to be edited here in your software. Note that you are allowed to pass through:
var employeeDetail = { 'EmpCode': $('#empCode').val(), 'ChangeType': 'Change', 'Location': $('#location').val() }
As you can see below, the POST is mostly similar to the GET above, but we’ll go through some of the differences. The URL simply points at the API again, and type this time is changed to POST. The data and content is the big difference here. We are posting this as JSON, but the same would work for XML. The JSON string is setup with the employeeDetail variable above, and the JSON.stringify to create this as a JSON string. Especially with a POST, it’s important to check the modelState if an error is returned, as it will often have important information, like missing fields for an Add, or incorrect type sent through. On success, this type of POST will give back a ChangeEmployeeStatus, which includes the newly created ChangeEmployeeId and the current ChangeEmployeeStatus, which will change as it makes it to the Micropay database, then again as it is processed by a payroll person.
$.ajax( { url: 'https://tapi.micropay.com.au/api/ChangeEmployee', type: 'POST', data: JSON.stringify(employeeDetail), contentType: "application/json", dataType: 'text', cache: false, async: false, beforeSend: function (xhr) { xhr.setRequestHeader("Authorization", "Basic " + btoa("username:password")); // Basic authentication with supplied username and password xhr.setRequestHeader("Api-Key", btoa("{11111111-1111-1111-1111-111111111111}")); }, error: function (data) { var message = ""; if (data.responseText == undefined) { message = data.text; console.log(message); alert(message); } else if (data.responseText.length > 0) { var response = JSON.parse(data.responseText); if (response.modelState != undefined) { $.each(response.modelState, function (key, value) { $.each(value, function (i, msg) { message += ("\n" + msg); }); }); } if (response.message == undefined) { alert(message); console.log(message); } else { console.log(response.message + "\n" + message); alert(response.message + "\n" + message); } } }, success: function (data, status2, response) { var result = JSON.parse(response.responseText); var id = result.ChangeEmployeeId; console.log(status2, data, response); alert("Success\n\nChangeEmployeeId = " + id); $('#Id').val(id); } });
Error handling
Posting to the Access MicrOpay Web API will require programmers to think about and understand the type of errors you will get and how you will get it. There are 3 main levels of error you will encounter:- General connection issues – this may include not resolving server or mistyped server or API name, internet down, server processing issues
- Authorization issues – this could be bad username/password, accessing the wrong ApiKey or trying to access an API you don’t have access to
- Model issues – this happens when you contact the API correctly, with correct authorization, but part of the data you send is bad, like POSTing without required information, wrong information or wrong formatting.
- Payroll database errors – The final error to cover is when the API returns success, but it fails with an error when trying to apply to the payroll database.
It’s also worth noting here there is one more error that may occur, where the POST request works perfectly through the WebAPI, but doesn’t match to important Micropay database data. We will get to this in the next section.
General connection issues
A lot of this section is going to cover basic connection issues to any Access MicrOpay Web API, but if you have problems the first time around, it’s still worth going through the following steps. That said, I’m going to run through these in minimal details, as the code to change should be fairly self-explanatory:- Wrong server name – Try changing tapi.micropay… to tap.micropay…, in other words mistyping the server name. You will get a return status 0 – Network Error.
- CORS not enabled – if your site isn’t correctly negotiating with CORS (cross origin resource sharing) your browser may return 0 – Access Is Denied when trying to access the Access MicrOpay Web API. Your project will need to enable CORS to work.
- Internet down – If you disconnect your network adapter, which will emulate the network being down, or in some way the server not being available. Again you’ll get 0 – Network Error.
- Wrong URL – Try doing a GET for ChangeEmployee, but instead mistype the name to ChangeEmploye. This will return status 404 – No HTTP Resource was found
Authorization issues
There can be various reasons you get unauthorized to an API. The bigger picture is you have a username password pair, an ApiKey and authorization to different parts of each ApiKey you have. So you’ll need to pass these three tests before contacting the API you are attempting to connect to. Here are some of the errors:- Bad username/password – Try mistyping your username/password with the request, you should get a 401
- Authorization header missing – Try removing the username/password entirely from code. You should get 401 – Unable to find user
- Api-Key header missing – Try removing the username/password entirely from code. You should get 401 – Unable to find user
- Call an API you don’t have authority to – in this example, you should have correct username/password and ApiKey, but try to access the Values API. You will get “User is not authorized to perform the requested action…”
- Call an API to the wrong DB – assuming your company has access to more than one payroll database, accessing one you don’t have the same authority to will also cause “User is not authorized to perform the requested action…”
Model issues
Once you are successfully connecting to the API, validation will happen on your requests which may also result in errors returning from API’s. The most common validation issues will be from making POST’s, and either missing required information or supplying a non-supported value. Required fields are mentioned in documentation and can be of two types, required for an add, or required for every POST.
We’ll start by looking at the format. If you get a validation error, you should get the response code of 400 – Bad request. The responseText in this case will be JSON with a message and a modelState array of errors. Here is the responseText where you try to POST to ChangeEmployee without setting the ChangeType at all:
{ "message":"The request is invalid.", "modelState": { "changeEmployeeView.ChangeType":["The ChangeType field is required"], "":["ChangeType must be one of: Add, Change, Delete, Edit, ImmediateUpdate or ImmediateInsert."] } }
In this case not entering ChangeType returns two errors in the modelState table. The first field may indicate the field the error references, and the 2nd field will show the actual error you are encountering. There may be 1, 2 or more error records returned, so your code should be able to cope for this. Our examples in jquery show a simple method to raise an alert where each error is given a new line:
var response = JSON.parse(data.responseText); $.each(response.modelState, function (key, value) { message += ("\n" + value); }); alert(message);
The responseText is converted to JSON, and the modelState table can be used row by row to log errors/alert the users what the errors were.
The above was the error returned when a required field was missing. The other likely scenario is one of the required fields has an unsupported value. In some cases this will be a value that isn’t one of the set list of values supported, or a value that doesn’t match the supported characters/length. The responseText format returned will still be the same as above for all errors, so we don’t need to go into that again, but I’ll just give an outline of the other errors you might get and how to handle them:- Value not in set list – there are some fields which will be from a set list of values. An example of this is ChangeType. If you send the value Insert, it will return an error, because Insert isn’t a valid value
- Value not in the correct format – an example of this might be putting characters in a numeric field, such as DaysTaken for the LeavePlanning API.
- Value is too long – many string fields have a maximum number of characters you can set, so a longer string will cause errors. An example of this is LeaveCode for LeavingPlanning, which is only 10 characters long, so trying ABCDE123456 will cause errors.
Payroll database errors
The last error doesn’t occur in the API, so you’ll get a 200 Success return back, as well as a change ID for you to check the status thereafter. In this case, the request makes it to the API OK, then gets pulled down to the payroll database, and has a problem applying the to the payroll database. For this scenario, the POST API’s allow you to check the record after it’s been posted, as it will update certain details, the most important being changeStatus and errorMessage.
As the request moves along, so does the changeStatus. If the POST works, it makes it to Received, which means it’s at the API, then moves onto PickedUp once it’s in the payroll database, if it’s not one of the immediate updates. When the payroll user tries to apply the change, or when an immediate update is picked up, then the payroll database will try to set the Employee details. A successful change means the status is changed to Implemented, and it’s then done with. Unsuccesful still might give them the chance to fix the issue, which might be a new code needing to be created in payroll, meaning it still may end up Implemented. However, once the payroll user decides it can’t be fixed, they will set it to Rejected, and the cause of the error will be stored into errorMessage.
So to handle all this, the first job is to store the ChangeEmployeeId given back after a POST. You can then periodically check the status to check if it has been implemented, and then if not rejected, look into why it was rejected. This can either be reported back to the person who made the change, or potentially checked by programmers to see if there is a problem with the logic of their POSTs.
Change Employee Request full example
Not yet finished. This will run you through all the components from a Software & Service Organisation web site through to checking the payroll actions or errors, with a downloadable project for jQuery and C#