Message Signature
When calling our APIs you will often find you need to create a Message-Signature
. This is a combination of your API Key
, a ClientRequestId
, the time
and the body
of your request. We recommend you follow the linked recipe below to get a feel for how it is used. The rest of this page goes into more detail about it.
Example
A standard API call to execute a Primary Transaction
in our Payments API might look like this:
{
method: "POST",
url: "https://prod.emea.api.fiservapps.com/sandbox/ipp/payments-gateway/v2/payments/",
headers: {
"Content-Type": "application/json",
"Client-Request-Id": "Client request ID goes here",
"Api-Key": "API Key goes here",
"Timestamp": "Date().getTime() goes here",
"Message-Signature": "Message Signature goes here"
},
body: JSON.stringify({
requestType: "PaymentCardSaleTransaction",
transactionAmount: { total: "13", currency: "GBP" },
paymentMethod: {
paymentCard: {
number: "4012000000000001",
securityCode: "123",
expiryDate: { month: "01", year: "29" }
},
},
authenticationRequest: {
authenticationType: "Secure3D21AuthenticationRequest",
termURL: "http://localhost:3124/api/v1/payments/3ds",
challengeIndicator: "04"
},
})
}
Variables
API-Key
You can retrieve this key from the Developer Portal
Client-Request-Id
This is generated by you the client of our API. It is a unique ID that is returned to you as part of the response. You can generate it like this:
var ClientRequestId = uuidv4();
Time
The getTime() method returns the number of milliseconds since the Unix Epoch. The Unix epoch is the time 00:00:00 UTC on 1 January 1970.
var time = new Date().getTime();
Request body
The request body must be stringified.
var requestBody = JSON.stringify(body);
Message-Signature
All of the variables above need to be available for the Message-Signature
to be generated.
Generate the rawSignature
first:
var rawSignature = apiKey + ClientRequestId + time + requestBody;
Create a HMAC using CryptoJS
var computedHash = CryptoJS.algo.HMAC.create(
CryptoJS.algo.SHA256,
secret.toString()
);
Secret Key
You can retrieve this secret key from the Developer Portal Apps screen. It must be the from the same application as your API Key.
Update your computedHash
with your rawSignature
computedHash.update(rawSignature);
computedHash = computedHash.finalize();
var messageSignature = CryptoJS.enc.Base64.stringify(computedHash);
That's it, add the messageSignature
into your header.
Demo app
We have a demo app available here which has the above code.
Example of code
//These libraries are for the running of this API.
const express = require("express");
const router = express.Router();
var request = require("request");
var CryptoJS = require("crypto-js");
const {v4: uuidv4} = require("uuid");
//These are the API keys and token for generating an encrypted message
const key = "API Key goes here";
const secret = "Secret goes here";
const url = "https://prod.emea.api.fiservapps.com/sandbox/ipp/payments-gateway/v2/payments/"
//When ever you communicate with IPG you need to encrypt the body of the message. This function modifies the API call to include the correct message signatures.
function fiservEncode(method, url, body, callback) {
var ClientRequestId = uuidv4();
var time = new Date().getTime();
var requestBody = JSON.stringify(body);
if(method === 'GET') {
requestBody = '';
}
var rawSignature = key + ClientRequestId + time + requestBody;
var computedHash = CryptoJS.algo.HMAC.create(
CryptoJS.algo.SHA256,
secret.toString()
);
computedHash.update(rawSignature);
computedHash = computedHash.finalize();
var computedHmac = CryptoJS.enc.Base64.stringify(computedHash);
var options = {
method: method,
url,
headers: {
"Content-Type": "application/json",
"Client-Request-Id": ClientRequestId,
"Api-Key": key,
Timestamp: time,
"Message-Signature": computedHmac
},
body: JSON.stringify(body),
};
callback(options);
}
//Step 2: Create Primary Transaction (Only performs a standard payment that requests 3DSecure!)
router.post("/payments", async (req, res) => {
//Start by encoding the message.
fiservEncode(
"POST",
url,
{
requestType: "PaymentCardSaleTransaction",
transactionAmount: { total: "13", currency: "GBP" },
paymentMethod: {
paymentCard: {
number: req.body.cardNumber,
securityCode: req.body.securityCode,
expiryDate: { month: req.body.expiryMonth, year: req.body.expiryYear },
},
},
authenticationRequest: {
authenticationType: "Secure3D21AuthenticationRequest",
termURL: "http://localhost:3124/api/v1/payments/3ds",
challengeIndicator: "04", // This indicates what type of transaction we would like.
},
},
(options) => {
//Submit the API call to Fiserv
request(options, function (error, paymentResponse) {
if (error) throw new Error(error);
let paymentData = JSON.parse(paymentResponse.body);
return res.status(200).json({
requestName: "Payment POST - Creating the payment request",
...paymentData
});
});
}
);
});
Updated about 1 year ago