🔒Postback Security
You should verify the signature received in the postback to ensure that the call comes from our servers.
Signature parameter should match MD5 of user_id transaction_id payout secret_key. You can find your secret in your placement page.
Postback Examples (GET):
<?php
$secret = "SECRET_KEY"; // Get your secret from placement settings
$user_id = isset($_GET['user_id']) ? $_GET['user_id'] : null;
$transaction_id = isset($_GET['transaction_id']) ? $_GET['transaction_id'] : null;
$payout = isset($_GET['payout']) ? $_GET['payout'] : null;
$signature = isset($_GET['signature']) ? $_GET['signature'] : null;
// Validate Signature
if(md5($user_id . $transaction_id . $payout . $secret) != $signature)
{
echo "ERROR: Signature doesn't match";
return;
}
// Further processing can be done here
echo "Signature is valid. Process the postback.";
?>from flask import Flask, request, jsonify
import hashlib
app = Flask(__name__)
secret = "SECRET_KEY" # Get your secret from placement settings
@app.route('/postback', methods=['GET'])
def postback():
user_id = request.args.get('user_id')
transaction_id = request.args.get('transaction_id')
payout = request.args.get('payout')
signature = request.args.get('signature')
# Validate Signature
if hashlib.md5((user_id + transaction_id + payout + secret).encode()).hexdigest() != signature:
return "ERROR: Signature doesn't match", 400
# Further processing can be done here
return "Signature is valid. Process the postback."
if __name__ == '__main__':
app.run()const express = require('express');
const crypto = require('crypto');
const app = express();
const port = 3000;
const secret = "SECRET_KEY"; // Get your secret from placement settings
app.get('/postback', (req, res) => {
const { user_id, transaction_id, payout, signature } = req.query;
// Validate Signature
const hash = crypto.createHash('md5').update(user_id + transaction_id + payout + secret).digest('hex');
if (hash !== signature) {
res.status(400).send("ERROR: Signature doesn't match");
return;
}
// Further processing can be done here
res.send("Signature is valid. Process the postback.");
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});require 'sinatra'
require 'digest'
secret = "SECRET_KEY" # Get your secret from placement settings
get '/postback' do
user_id = params['user_id']
transaction_id = params['transaction_id']
payout = params['payout']
signature = params['signature']
# Validate Signature
if Digest::MD5.hexdigest(user_id + transaction_id + payout + secret) != signature
halt 400, "ERROR: Signature doesn't match"
end
# Further processing can be done here
"Signature is valid. Process the postback."
endimport org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@RestController
public class PostbackController {
private final String secret = "SECRET_KEY"; // Get your secret from placement settings
@GetMapping("/postback")
public String postback(@RequestParam String user_id, @RequestParam String transaction_id,
@RequestParam String payout, @RequestParam String signature) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
String data = user_id + transaction_id + payout + secret;
md.update(data.getBytes());
byte[] digest = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
if (!sb.toString().equals(signature)) {
return "ERROR: Signature doesn't match";
}
} catch (NoSuchAlgorithmException e) {
return "ERROR: Unable to process signature";
}
// Further processing can be done here
return "Signature is valid. Process the postback.";
}
}using Microsoft.AspNetCore.Mvc;
using System.Security.Cryptography;
using System.Text;
[ApiController]
[Route("postback")]
public class PostbackController : ControllerBase
{
private readonly string secret = "SECRET_KEY"; // Get your secret from placement settings
[HttpGet]
public IActionResult Postback(string user_id, string transaction_id, string payout, string signature)
{
using (var md5 = MD5.Create())
{
var input = Encoding.UTF8.GetBytes(user_id + transaction_id + payout + secret);
var hashBytes = md5.ComputeHash(input);
var hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
if (hash != signature)
{
return BadRequest("ERROR: Signature doesn't match");
}
}
// Further processing can be done here
return Ok("Signature is valid. Process the postback.");
}
}Don’t forget to check the transaction_id against your database to ensure it doesn’t already exist.
Status Code
Please return status code 200, if you have successfully processed the postback.
Whitelisting
In order to ensure the integrity of the postbacks, you can whitelist our server IP. Postbacks are exclusively sent from this IP address:
66.29.153.108Last updated