Skip to main content

HMAC - Hash-based Message Authentication Code

HMACs are a way of ensuring that the payload sent to RaiseNow is not manually tampered with before it's processed by RaiseNow. HMACs are generated twice, once on your side, and once on RaiseNow side.

HMACs are computed by selecting specified set of field values from the request and a secret shared between you and RaiseNow. Then, these values are then signed with a secret. The resulting value is the HMAC and is sent together with the original request to RaiseNow. Based on the received values from the request & the shared secret, RaiseNow recomputes the HMAC. If the value from the request and the computed value match, the HMAC is valid. If not, the payload was tampered with and RaiseNow will reject the request.

Step-by-Step Guide

Follow these steps to generate the HMAC and send it to RaiseNow:

  1. Define a value for the shared secret. It can be up to 64 characters long and must match the regex [äöüa-zA-Z0-9$&+,:;=?@#|'<>.^*()%!-]{0,64}
  2. Define which parameters should be included in the HMAC calculation. E.g. amount.currency
  3. Define for how long you want each HMAC to be considered valid. Typically, you'd define 30 minutes as a starting point
  4. Send the values from 1-3 to RaiseNow
  5. Then, for creating a payment, payment source or payment agreement, generate the HMAC yourself, by
    1. Taking all the parameters from step 2 and sorting them by path in alphabetical ascending order (e.g. a.b comes before b.a)
    2. Taking your secret from step 1
    3. Take your HMAC library of your choice, and use sha256 as the algorithm to generate it
    4. Take the unix timestamp of when you generated the HMAC
  6. Pass the HMAC as a string hexit value and the unix timestamp as an integer in the request:
    {
    "hmac": {
    "timestamp: 1748936579,
    "value": "174bbd25de2bbf6e6bc82a406d4c6d29bb41a534616dca0b6869817d77e00f35"
    }
    }
  7. Send the request to RaiseNow

Examples

You can use the following example as a starting point to generate the HMAC on your side:

<?php

$secret = 'my top secret value';
$algo = 'sha256';

// the parameters to hash
$payload = [
'amount.value' => 1000,
'amount.currency' => 'EUR',
'test_mode' => true,
'custom_parameters.b_key' => 'b_value',
'custom_parameters.a_key' => 'a_value'
];

// sort by path: alphabetically, in ascending order
ksort($payload);

// properly serialise boolean values into their string equivalents
foreach ($payload as $key => $value) {
if (is_bool($value)) {
$payload[$key] = $value ? 'true' : 'false';
}
}

$payload = implode('', $payload);

echo "expected HMAC: 4df1cbf05c7a9c375127f466d6c54b7bdb64e94f46e6ae1975bb71d67a6fcf66\n";
echo "actual HMAC: " . hash_hmac($algo,$payload, $secret, false);