Signature

Requests to Mercuryo and callbacks from Mercuryo are signed with the same algorithm:

  1. Take your Sign Key from the Mercuryo Dashboard under Widgets → select your widget. Use the Sign Key of the widget associated with your Sdk-Partner-Token, and make sure the key is stored securely on your backend and never exposed on the frontend.
  2. Take the JSON body string:
    • request — the body serialized to compact JSON: no whitespace, / and non-ASCII characters not escaped;
    • callback — the raw body exactly as received.
  3. Compute HMAC-SHA256 of this string with the Sign Key and hex-encode the result.
  4. Use the signature:
    • request — send it in the X-Signature header, and send exactly the same string as the body;
    • callback — compare it with the X-Signature header and reject the callback if they differ.

Code Examples

JavaScript

const crypto = require('crypto');

const sign = (body, signKey) => crypto.createHmac('sha256', signKey).update(body, 'utf8').digest('hex');

// Request: send `body` as the request body and `sign(body, SIGN_KEY)` in X-Signature
const body = JSON.stringify(payload);

// Callback: compare with the X-Signature header
const isValid = sign(rawBody, SIGN_KEY) === signatureHeader;

Python

import hashlib
import hmac
import json

def sign(body: str, sign_key: str) -> str:
    return hmac.new(sign_key.encode(), body.encode('utf-8'), hashlib.sha256).hexdigest()

# Request: send body.encode('utf-8') as the request body and sign(body, SIGN_KEY) in X-Signature
body = json.dumps(payload, separators=(',', ':'), ensure_ascii=False)

# Callback: compare with the X-Signature header
is_valid = hmac.compare_digest(sign(raw_body, SIGN_KEY), signature_header)

Go

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
)

func sign(body []byte, signKey string) string {
    h := hmac.New(sha256.New, []byte(signKey))
    h.Write(body)
    return hex.EncodeToString(h.Sum(nil))
}

// Request: compact JSON without escaping, send body and sign(body, signKey) in X-Signature
func requestBody(payload any) ([]byte, error) {
    var buf bytes.Buffer
    enc := json.NewEncoder(&buf)
    enc.SetEscapeHTML(false)
    if err := enc.Encode(payload); err != nil {
        return nil, err
    }
    return bytes.TrimRight(buf.Bytes(), "\n"), nil
}

// Callback: hmac.Equal([]byte(sign(rawBody, signKey)), []byte(signatureHeader))

PHP

$sign = fn(string $body, string $signKey): string => hash_hmac('sha256', $body, $signKey);

// Request: send $body as the request body and $sign($body, $signKey) in X-Signature
$body = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

// Callback: compare with the X-Signature header
$isValid = hash_equals($sign($rawBody, $signKey), $signatureHeader);

Try It: Signature Calculator

Paste a JSON body and your Sign Key to check your implementation:

  • Request — paste the exact compact JSON string you send as the request body, and compare the result with the X-Signature you send.
  • Callback — paste the raw callback body exactly as received, and compare the result with the X-Signature header of the callback.

Note: The hash is computed locally using your browser.