JSON Authentication
Authentication
The authentication of this JSON API is based on a standard HMAC Authentication implementation. See this acticle for a basic explanation of HMAC.
Explanation
To authenticate your application to the API you need to set the correct Authorization Header. See below for an example for such a header.
Header example:
Authorization: hmac ABCD1234:WISKbwwMbWhMRSRJc0jFtg/LIvB9vM5VWPvfVa0JnMc=:134ee2ec5c9d43d7acfae9190ec7eb83:1434973589
We are now going to break this header up in pieces. All values are seperated by a colon ":".
hmac: The authentication scheme. Always "hmac".
ABCD1234: Website Key: this key can be found in the Buckaroo payment plaza at https://plaza.buckaroo.nl/. Click on your merchant name in the menu on the left side of the screen -> websites -> {yourwebsite}. Here you can find the website key in the table in the first row.
WISKbwwMbWhMRSRJc0jFtg/LIvB9vM5VWPvfVa0JnMc=: A Base64 hash using HMAC SHA256 signed with your Secret Key. See this article for implementations of HMAC SHA256 in multiple languages. The HMAC SHA256 is calculated over a concatenated string (as raw data/binary/bytes) of the following values: WebsiteKey, requestHttpMethod, requestUri, requestTimeStamp, nonce, requestContentBase64String. See the next table for more information about these values. Please note: the Base64 hash should be a string of 44 characters. If yours is longer, it is probably in hexadecimal format.
134ee2ec5c9d43d7acfae9190ec7eb83: Nonce: A random sequence of characters, this should differ from for each request. See this article for more information.
1434973589: Request TimeStamp: An integer of the total amount of seconds elapsed since 01-01-1970 (00:00:00:00) in UTC time.
See below for an explanation of the values used to generate the HMAC SHA256 hash. All these parameters (except the Secret Key) should be concatenated into one string for the generation of the HMAC SHA256 hash.
Website key: This key can be found in the Buckaroo payment plaza at https://plaza.buckaroo.nl/. Click on 'My Buckaroo' in the bottom left of the screen -> websites -> {yourwebsite}. Here you can find the website key in the table in the first row. If you have multiple websites, use the filter option in the top right to switch between websites.
Request method : Usually GET or POST, always uppercase.
Request URI: The request uri without the protocol. First uri encoded and then to lowercase. So, for example: "https://testcheckout.buckaroo.nl/json/Transaction/Specification/ideal" would become "testcheckout.buckaroo.nl%2fjson%2ftransaction%2fspecification%2fideal"
Request timestamp: An integer of the total amount of seconds elapsed since 01-01-1970 (00:00:00:00) in UTC time.
Nonce: A random sequence of characters, this should differ from for each request. See this article for more information.
Request content string : Create an MD5 hash (as raw data/binary/bytes) of the request content. Then convert this hash to a Base64 string. Please note: the Base64 string should be 24 characters. If yours is longer, the Base64 is probably calculated over the MD5 hash in hexadecimal format.
Secret Key: This key is used to generate the HMAC SHA256 hash. You can create a Secret Key in your Buckaroo account: https://plaza.buckaroo.nl/Configuration/Merchant/SecretKey
Additional Headers (not mandatory)
Culture: The user culture if applicable (for example: nl-NL). If not provided, a default of en-US will be used. This will be used in determining the language of both the checkout and the email templates.
Channel: The used channel, mostly 'Web' is used (which is default), but in some cases 'Backoffice' is required. Please see the payment method and services sections for the supported channel per service action.
Software: A definition of the software used to create the request, this needs be a JSON string in the following format:
{"PlatformName":"X","PlatformVersion":"1.0","ModuleSupplier":"X","ModuleName":"X","ModuleVersion":"1.0"}
Code Examples
Code Example in C#
See below an example of the HMAC authentication integration in C#.
NOTE: This solution depends on the "Json.NET" Library (https://www.newtonsoft.com/json).
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async void Main(string[] args)
{
string apiBaseAddress = "https://testcheckout.buckaroo.nl/";
CustomDelegatingHandler customDelegatingHandler = new CustomDelegatingHandler();
HttpClient client = HttpClientFactory.Create(customDelegatingHandler);
var bodyString = "{ \"Services\": [ { \"Name\": \"ideal\" } ] }";
object body = Newtonsoft.Json.JsonConvert.DeserializeObject<object>(bodyString);
HttpResponseMessage response = await client.PostAsJsonAsync(apiBaseAddress + "json/transactionrequestspecification", body);
var result = response.Content.ReadAsStringAsync().Result;
}
}
public class CustomDelegatingHandler : DelegatingHandler
{
//Obtained from the server earlier
private string WebsiteKey = "WEBSITEKEY";
private string SecretKey = "PRIVATEKEY";
protected async override Task<HttpResponseMessage>SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
string requestContentBase64String = string.Empty;
string requestUri = System.Web.HttpUtility.UrlEncode(request.RequestUri.Authority + request.RequestUri.PathAndQuery).ToLower();
string requestHttpMethod = request.Method.Method;
// calculate UNIX time
DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
TimeSpan timeSpan = DateTime.UtcNow - epochStart;
string requestTimeStamp = Convert.ToUInt64(timeSpan.TotalSeconds).ToString();
// create random nonce for each request
string nonce = Guid.NewGuid().ToString("N");
// checking if the request contains body, usually will be null with HTTP GET and DELETE
if (request.Content != null)
{
byte[] content = await request.Content.ReadAsByteArrayAsync();
MD5 md5 = MD5.Create();
// hashing the request body, any change in request body will result in different hash, we'll incure message integrity
byte[] requestContentHash = md5.ComputeHash(content);
requestContentBase64String = Convert.ToBase64String(requestContentHash);
}
// creating the raw signature string
string signatureRawData = String.Format("{0}{1}{2}{3}{4}{5}", WebsiteKey, requestHttpMethod, requestUri, requestTimeStamp, nonce, requestContentBase64String);
var secretKeyByteArray = Encoding.UTF8.GetBytes(SecretKey);
byte[] signature = Encoding.UTF8.GetBytes(signatureRawData);
using (HMACSHA256 hmac = new HMACSHA256(secretKeyByteArray))
{
byte[] signatureBytes = hmac.ComputeHash(signature);
string requestSignatureBase64String = Convert.ToBase64String(signatureBytes);
// setting the values in the Authorization header using custom scheme (hmac)
request.Headers.Authorization = new AuthenticationHeaderValue("hmac", string.Format("{0}:{1}:{2}:{3}", WebsiteKey, requestSignatureBase64String, nonce, requestTimeStamp));
}
// set other headers
request.Headers.Add("culture", "nl-NL");
request.Headers.Add("channel", "Web");
response = await base.SendAsync(request, cancellationToken);
return response;
}
}
Code Example in JavaScript
See below an example of the HMAC authentication integration in JavaScript.
NOTE: The Following scripts of the CryptoJs Library (https://code.google.com/p/crypto-js/) are required for this implementation of the HMAC authentication:
- enc-base64-min.js
- hmac-sha256.js
- md5-min.js
This module can be used like the following example:
var authHeader = BuckarooHmac.GetAuthHeader(requestUri, websiteKey, secretKey, postContent, httpMethod);
var BuckarooHmac = (function () {
var self = {};
function getEncodedContent(content) {
if (content) {
var md5 = CryptoJS.MD5(content);
var base64 = CryptoJS.enc.Base64.stringify(md5);
return base64;
}
return content;
}
function getHash(websiteKey, secretKey, httpMethod, nonce, timeStamp, requestUri, content) {
var encodedContent = getEncodedContent(content);
var rawData = websiteKey + httpMethod + requestUri + timeStamp + nonce + encodedContent;
var hash = CryptoJS.HmacSHA256(rawData, secretKey);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
return hashInBase64;
}
function getTimeStamp() {
return Math.floor((new Date).getTime() / 1000);
}
function getNonce() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 16; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
self.GetAuthHeader = function (requestUri, websiteKey, secretKey, content, httpMethod) {
var nonce = getNonce();
var timeStamp = getTimeStamp();
content = content ? content : "";
var url = encodeURIComponent(requestUri).toLowerCase();
return "hmac " + websiteKey + ":" + getHash(websiteKey, secretKey, httpMethod, nonce, timeStamp, url, content) + ":" + nonce + ":" + timeStamp;
}
return self;
}());
Code Example in PHP
This is just an example of how the Authorization Header could be calculated.
<?php
$postArray = array(
"Currency" => "EUR",
"AmountDebit" => 10.00,
"Invoice" => "testinvoice 123",
"Services" => array(
"ServiceList" => array(
array(
"Action" => "Pay",
"Name" => "ideal",
"Parameters" => array(
array(
"Name" => "issuer",
"Value" => "ABNANL2A"
)
)
)
)
)
);
$postJson = json_encode($postArray);
echo $postJson . '<br><br>';
$md5 = md5($postJson, true);
$post = base64_encode($md5);
echo '<b>MD5 from json</b> ' . $md5 . '<br><br>';
echo '<b>base64 from MD5</b> ' . $post . '<br><br>';
$websiteKey = 'WEBSITE_KEY';
$uri = strtolower(urlencode('testcheckout.buckaroo.nl/json/Transaction'));
$nonce = rand(0000000, 9999999); //Preferably unique ID
$time = time();
$hmac = $websiteKey . 'POST' . $uri . $time . $nonce . $post;
$s = hash_hmac('sha256', $hmac, 'Secret Key', true);
$hmac = base64_encode($s);
echo ("hmac " . $websiteKey . ':' . $hmac . ':' . $nonce . ':' . $time);