Code examples (PHP, JS, Python)
Minimal, dependency-light examples for creating a payment and verifying a webhook. Set GATEWAY_SECRET_KEY and GATEWAY_WEBHOOK_SECRET as environment variables on your server.
PHP
Create a payment
<?php
$orderId = 'order-1001';
$ch = curl_init('https://gatway.hunario.com/api/v1/payments');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('GATEWAY_SECRET_KEY'),
'Idempotency-Key: ' . $orderId,
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => '49.90',
'currency' => 'USDT',
'reference' => $orderId,
'success_url' => 'https://shop.example.com/orders/1001/thanks',
]),
]);
$body = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status !== 201) {
throw new RuntimeException($body['error']['code'] . ': ' . $body['error']['message']);
}
header('Location: ' . $body['data']['checkout_url']);Verify a webhook
<?php
function verifyGatewayWebhook(string $payload, string $header, string $secret, int $tolerance = 300): ?array
{
$parts = [];
foreach (explode(',', $header) as $pair) {
[$k, $v] = array_pad(explode('=', $pair, 2), 2, '');
$parts[trim($k)] = trim($v);
}
if (empty($parts['t']) || empty($parts['v1']) || abs(time() - (int) $parts['t']) > $tolerance) {
return null;
}
$expected = hash_hmac('sha256', $parts['t'] . '.' . $payload, $secret);
return hash_equals($expected, $parts['v1']) ? json_decode($payload, true) : null;
}
$event = verifyGatewayWebhook(file_get_contents('php://input'), $_SERVER['HTTP_X_GATEWAY_SIGNATURE'] ?? '', getenv('GATEWAY_WEBHOOK_SECRET'));
if ($event === null) { http_response_code(400); exit; }
if ($event['type'] === 'payment.completed') {
// markOrderPaid($event['data']['reference'], $event['data']['id']); // idempotent!
}
http_response_code(200);JavaScript (Node.js 18+)
Create a payment
const res = await fetch('https://gatway.hunario.com/api/v1/payments', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GATEWAY_SECRET_KEY}`,
'Idempotency-Key': 'order-1001',
'Content-Type': 'application/json',
},
body: JSON.stringify({ amount: '49.90', currency: 'USDT', reference: 'order-1001' }),
});
const body = await res.json();
if (res.status !== 201) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data.checkout_url);Verify a webhook (Express)
import crypto from 'node:crypto';
import express from 'express';
const app = express();
// Use the raw body: the signature is computed over the exact bytes we sent.
app.post('/webhooks/gateway', express.raw({ type: 'application/json' }), (req, res) => {
const header = req.get('X-Gateway-Signature') ?? '';
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=', 2).map((s) => s.trim())));
const t = Number(parts.t);
const expected = crypto.createHmac('sha256', process.env.GATEWAY_WEBHOOK_SECRET)
.update(`${parts.t}.${req.body}`).digest('hex');
const valid = parts.v1 && expected.length === parts.v1.length
&& crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1))
&& Math.abs(Date.now() / 1000 - t) <= 300;
if (!valid) return res.sendStatus(400);
const event = JSON.parse(req.body);
if (event.type === 'payment.completed') {
// await markOrderPaid(event.data.reference, event.data.id); // idempotent!
}
res.sendStatus(200);
});Python 3
Create a payment
import os, requests
resp = requests.post(
"https://gatway.hunario.com/api/v1/payments",
headers={
"Authorization": f"Bearer {os.environ['GATEWAY_SECRET_KEY']}",
"Idempotency-Key": "order-1001",
},
json={"amount": "49.90", "currency": "USDT", "reference": "order-1001"},
timeout=30,
)
body = resp.json()
if resp.status_code != 201:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"]["checkout_url"])Verify a webhook (Flask)
import hashlib, hmac, json, os, time
from flask import Flask, request, abort
app = Flask(__name__)
@app.post("/webhooks/gateway")
def gateway_webhook():
payload = request.get_data() # raw bytes
parts = dict(p.strip().split("=", 1) for p in request.headers.get("X-Gateway-Signature", "").split(",") if "=" in p)
t, v1 = parts.get("t", ""), parts.get("v1", "")
expected = hmac.new(os.environ["GATEWAY_WEBHOOK_SECRET"].encode(), f"{t}.".encode() + payload, hashlib.sha256).hexdigest()
if not t.isdigit() or abs(time.time() - int(t)) > 300 or not hmac.compare_digest(expected, v1):
abort(400)
event = json.loads(payload)
if event["type"] == "payment.completed":
pass # mark_order_paid(event["data"]["reference"], event["data"]["id"]) # idempotent!
return "", 200Request a payout
curl -X POST https://gatway.hunario.com/api/v1/payouts \
-H "Authorization: Bearer $GATEWAY_SECRET_KEY" \
-H "Idempotency-Key: withdrawal-778" \
-H "Content-Type: application/json" \
-d '{"amount":"250.00","currency":"USDT","network":"tron","reference":"withdrawal-778",
"destination":{"type":"crypto_address","value":"TQ5n...your-wallet"}}'