Request Signature
All server-to-server API requests to Kukuruku must include an HMAC-SHA512 signature in the HTTP headers. This ensures request authenticity and integrity.
Credentials
You will receive these after registering your project:
| Credential | Example | Description |
|---|---|---|
secret_key | rmQXpjQyAtzS65oVhRLwY9s669UyDKJl | Secret key for HMAC signing |
merchant_id | 1 | Your merchant identifier |
Manage your credentials in the merchant dashboard.
Signing Requests
Every request to the Kukuruku API must include:
merchant_idfield in the request bodysignatureheader in the HTTP headers
Algorithm
- Serialize the request body as a JSON string
- Compute HMAC-SHA512 of the JSON string using your
secret_key - Set the resulting hex string as the
signatureheader
Node.js Example
const axios = require('axios');
const sha512 = require('js-sha512').sha512;
const SECRET_KEY = 'rmQXpjQyAtzS65oVhRLwY9s669UyDKJl';
const data = {
merchant_id: "1",
amount: 50000,
currency: "RUB",
callback_url: "https://your-site.com/callback",
order_number: "order-123",
redirect_success_url: "https://your-site.com/success",
redirect_fail_url: "https://your-site.com/fail",
customer: {
client_id: "user@example.com"
}
};
const signature = sha512.hmac(SECRET_KEY, JSON.stringify(data));
await axios({
method: 'POST',
url: 'https://api.kukuruku.win/api/v1/orders/payins',
data,
headers: {
'Content-Type': 'application/json',
signature
}
});
Python Example
import hmac
import hashlib
import json
import requests
SECRET_KEY = 'rmQXpjQyAtzS65oVhRLwY9s669UyDKJl'
data = {
"merchant_id": "1",
"amount": 50000,
"currency": "RUB",
"callback_url": "https://your-site.com/callback",
"order_number": "order-123",
"redirect_success_url": "https://your-site.com/success",
"redirect_fail_url": "https://your-site.com/fail",
"customer": {
"client_id": "user@example.com"
}
}
body = json.dumps(data, separators=(',', ':'))
signature = hmac.new(
SECRET_KEY.encode(), body.encode(), hashlib.sha512
).hexdigest()
response = requests.post(
'https://api.kukuruku.win/api/v1/orders/payins',
json=data,
headers={'signature': signature}
)
PHP Example
$secretKey = 'rmQXpjQyAtzS65oVhRLwY9s669UyDKJl';
$data = [
'merchant_id' => '1',
'amount' => 50000,
'currency' => 'RUB',
'callback_url' => 'https://your-site.com/callback',
'order_number' => 'order-123',
'redirect_success_url' => 'https://your-site.com/success',
'redirect_fail_url' => 'https://your-site.com/fail',
'customer' => [
'client_id' => 'user@example.com'
]
];
$body = json_encode($data);
$signature = hash_hmac('sha512', $body, $secretKey);
$ch = curl_init('https://api.kukuruku.win/api/v1/orders/payins');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'signature: ' . $signature,
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
Signature Verification
Requests from Kukuruku to your server (callbacks, order status responses) include a signature header. Always verify it to ensure the request is genuine.
Algorithm
- Read the raw request body as a string
- Compute HMAC-SHA512 of the body using your
secret_key - Compare the result with the
signatureheader value
Node.js Example
const sha512 = require('js-sha512').sha512;
function verifySignature(body, signatureHeader, secretKey) {
const expected = sha512.hmac(secretKey, JSON.stringify(body));
return expected === signatureHeader;
}
// In your callback handler:
app.post('/callback', (req, res) => {
if (!verifySignature(req.body, req.headers.signature, SECRET_KEY)) {
return res.status(401).json({ success: false, err: 'Invalid signature' });
}
// Process the callback...
res.json({ success: true });
});
Python Example
import hmac
import hashlib
def verify_signature(body: bytes, signature_header: str, secret_key: str) -> bool:
expected = hmac.new(
secret_key.encode(), body, hashlib.sha512
).hexdigest()
return hmac.compare_digest(expected, signature_header)
PHP Example
function verifySignature(string $body, string $signatureHeader, string $secretKey): bool {
$expected = hash_hmac('sha512', $body, $secretKey);
return hash_equals($expected, $signatureHeader);
}
Security
Always use constant-time comparison (like hmac.compare_digest in Python or hash_equals in PHP) to prevent timing attacks.