Documentation Index
Fetch the complete documentation index at: https://docs.txncheck.com/llms.txt
Use this file to discover all available pages before exploring further.
PHP Integration
This guide shows how to integrate TxnCheck API into your PHP application.Installation
Using Guzzle (Recommended)
composer require guzzlehttp/guzzle
Using cURL
cURL is built into PHP, no installation needed.Basic Client Setup (Guzzle)
<?php
namespace App\Services;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
class TxnCheckClient
{
private Client $client;
private string $apiKey;
private ?string $secretKey;
public function __construct(
string $apiKey,
?string $secretKey = null,
string $baseUrl = 'https://api.txncheck.in/api/v1'
) {
$this->apiKey = $apiKey;
$this->secretKey = $secretKey;
$this->client = new Client([
'base_uri' => $baseUrl,
'timeout' => 30,
'headers' => [
'X-API-Key' => $apiKey,
'Content-Type' => 'application/json',
],
]);
}
/**
* Sign request with HMAC-SHA256
*/
private function signRequest(string $method, string $path, string $body): array
{
if (!$this->secretKey) {
return [];
}
$timestamp = (string) round(microtime(true) * 1000);
$message = "{$timestamp}.{$method}.{$path}.{$body}";
$signature = hash_hmac('sha256', $message, $this->secretKey);
return [
'X-Timestamp' => $timestamp,
'X-Signature' => $signature,
];
}
/**
* Make API request
*/
private function request(string $method, string $endpoint, ?array $data = null, bool $sync = false): array
{
if ($data !== null && $sync) {
$data['async'] = false;
}
$body = $data ? json_encode($data) : '';
$headers = $this->signRequest(strtoupper($method), $endpoint, $body);
try {
$response = $this->client->request($method, $endpoint, [
'headers' => $headers,
'json' => $data,
]);
return json_decode($response->getBody()->getContents(), true);
} catch (RequestException $e) {
if ($e->hasResponse()) {
$error = json_decode($e->getResponse()->getBody()->getContents(), true);
throw new TxnCheckException(
$error['message'] ?? 'Unknown error',
$e->getResponse()->getStatusCode(),
$error['error'] ?? 'Error'
);
}
throw $e;
}
}
/**
* Get UPI VPAs linked to a mobile number
*/
public function upiByMobile(string $mobile, bool $sync = false): array
{
return $this->request('POST', '/upi-by-mobile', ['mobile' => $mobile], $sync);
}
/**
* Get KYC data by mobile number
*/
public function kycByMobile(string $mobile, bool $sync = false): array
{
return $this->request('POST', '/kyc-by-mobile', ['mobile' => $mobile], $sync);
}
/**
* Check VPAs against blocklist
*/
public function vpaChargebackCheck(array $vpas, bool $sync = false): array
{
return $this->request('POST', '/vpa-chargeback-check', ['vpas' => $vpas], $sync);
}
/**
* Full verification: UPI + KYC + Chargeback check
*/
public function fullCheck(string $mobile, bool $sync = false): array
{
return $this->request('POST', '/full-check', ['mobile' => $mobile], $sync);
}
/**
* Bulk check VPAs against blocklist
*/
public function bulkVpaCheck(array $vpas, bool $sync = false): array
{
return $this->request('POST', '/bulk/vpa-chargeback-check', ['vpas' => $vpas], $sync);
}
/**
* Get request status and results
*/
public function getRequestStatus(string $requestId): array
{
return $this->request('GET', "/requests/{$requestId}");
}
/**
* Poll for request completion
*/
public function waitForResult(string $requestId, int $pollInterval = 2, int $maxWait = 60): array
{
$terminalStatuses = ['COMPLETED', 'FAILED', 'PARTIAL'];
$startTime = time();
while (time() - $startTime < $maxWait) {
$result = $this->getRequestStatus($requestId);
if (in_array($result['status'], $terminalStatuses)) {
return $result;
}
sleep($pollInterval);
}
throw new \RuntimeException("Request {$requestId} did not complete within {$maxWait}s");
}
}
class TxnCheckException extends \Exception
{
public string $errorType;
public function __construct(string $message, int $code, string $errorType)
{
parent::__construct($message, $code);
$this->errorType = $errorType;
}
}
Basic Client Setup (cURL)
<?php
class TxnCheckCurlClient
{
private string $apiKey;
private string $baseUrl;
private ?string $secretKey;
public function __construct(
string $apiKey,
?string $secretKey = null,
string $baseUrl = 'https://api.txncheck.in/api/v1'
) {
$this->apiKey = $apiKey;
$this->secretKey = $secretKey;
$this->baseUrl = rtrim($baseUrl, '/');
}
private function request(string $method, string $endpoint, ?array $data = null, bool $sync = false): array
{
if ($data !== null && $sync) {
$data['async'] = false;
}
$url = $this->baseUrl . $endpoint;
$body = $data ? json_encode($data) : '';
$headers = [
"X-API-Key: {$this->apiKey}",
'Content-Type: application/json',
];
// Sign request if secret key is configured
if ($this->secretKey) {
$timestamp = (string) round(microtime(true) * 1000);
$message = "{$timestamp}." . strtoupper($method) . ".{$endpoint}.{$body}";
$signature = hash_hmac('sha256', $message, $this->secretKey);
$headers[] = "X-Timestamp: {$timestamp}";
$headers[] = "X-Signature: {$signature}";
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 30,
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new \RuntimeException("cURL error: {$error}");
}
$result = json_decode($response, true);
if ($httpCode >= 400) {
throw new TxnCheckException(
$result['message'] ?? 'Unknown error',
$httpCode,
$result['error'] ?? 'Error'
);
}
return $result;
}
public function upiByMobile(string $mobile, bool $sync = false): array
{
return $this->request('POST', '/upi-by-mobile', ['mobile' => $mobile], $sync);
}
public function kycByMobile(string $mobile, bool $sync = false): array
{
return $this->request('POST', '/kyc-by-mobile', ['mobile' => $mobile], $sync);
}
public function vpaChargebackCheck(array $vpas, bool $sync = false): array
{
return $this->request('POST', '/vpa-chargeback-check', ['vpas' => $vpas], $sync);
}
public function fullCheck(string $mobile, bool $sync = false): array
{
return $this->request('POST', '/full-check', ['mobile' => $mobile], $sync);
}
public function getRequestStatus(string $requestId): array
{
return $this->request('GET', "/requests/{$requestId}");
}
}
Usage Examples
Async Mode (Default)
<?php
$client = new TxnCheckClient('fb_your_api_key_here');
// Submit request
$response = $client->upiByMobile('+919876543210');
echo "Request ID: {$response['requestId']}\n";
// Poll for result
$result = $client->waitForResult($response['requestId']);
echo "Status: {$result['status']}\n";
echo "UPI addresses: " . implode(', ', $result['result']['upi']) . "\n";
Sync Mode
<?php
// Get result immediately (waits up to 30 seconds)
$result = $client->upiByMobile('+919876543210', sync: true);
if ($result['status'] === 'COMPLETED') {
echo "Name: {$result['result']['name']}\n";
echo "UPI addresses: " . implode(', ', $result['result']['upi']) . "\n";
}
Full Check
<?php
$result = $client->fullCheck('+919876543210', sync: true);
if ($result['status'] === 'COMPLETED') {
// UPI data
$upiData = $result['result']['upiByMobile'];
echo "Name: {$upiData['name']}\n";
echo "VPAs: " . implode(', ', $upiData['upi']) . "\n";
// KYC data
$kycData = $result['result']['kycByMobile'];
echo "PAN: {$kycData['pan']}\n";
echo "DOB: {$kycData['dob']}\n";
// Blocklist status
$blocklist = $result['result']['vpaChargebackCheck'];
echo "Blocklisted: {$blocklist['summary']['blocklisted']}\n";
}
VPA Blocklist Check
<?php
$vpas = ['user1@upi', 'user2@paytm', 'suspicious@ybl'];
$result = $client->vpaChargebackCheck($vpas, sync: true);
if ($result['status'] === 'COMPLETED') {
// Blocklisted VPAs
foreach ($result['result']['blocklisted'] as $vpa) {
echo "⚠️ BLOCKED: {$vpa['vpa']}\n";
}
// Clean VPAs
foreach ($result['result']['clean'] as $vpa) {
echo "✓ Clean: {$vpa['vpa']}\n";
}
}
Error Handling
<?php
class TxnCheckException extends \Exception
{
public string $errorType;
public function __construct(string $message, int $code, string $errorType)
{
parent::__construct($message, $code);
$this->errorType = $errorType;
}
}
// Usage with retry logic
function verifyWithRetry(TxnCheckClient $client, string $mobile, int $maxRetries = 3): array
{
$lastError = null;
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
try {
return $client->upiByMobile($mobile, sync: true);
} catch (TxnCheckException $e) {
$lastError = $e;
// Don't retry client errors (except rate limit)
if ($e->getCode() >= 400 && $e->getCode() < 500 && $e->getCode() !== 429) {
throw $e;
}
// Exponential backoff
$delay = min(pow(2, $attempt - 1), 10);
echo "Retry {$attempt}/{$maxRetries} in {$delay}s...\n";
sleep($delay);
}
}
throw $lastError;
}
// Usage
try {
$result = verifyWithRetry($client, '+919876543210');
echo "Verified: {$result['result']['name']}\n";
} catch (TxnCheckException $e) {
echo "Error ({$e->getCode()}): {$e->getMessage()}\n";
}
Webhook Signature Verification
<?php
function verifyWebhookSignature(
string $payload,
string $signature,
string $timestamp,
string $secretKey,
int $maxAgeSeconds = 300
): bool {
// Check timestamp freshness
$webhookTime = (int) $timestamp;
$currentTime = (int) (microtime(true) * 1000);
$ageMs = $currentTime - $webhookTime;
if ($ageMs > $maxAgeSeconds * 1000) {
return false; // Webhook too old
}
// Compute expected signature
$message = "{$timestamp}.{$payload}";
$expected = hash_hmac('sha256', $message, $secretKey);
// Constant-time comparison
return hash_equals($expected, $signature);
}
// Laravel example
Route::post('/webhook/fraud-buster', function (Request $request) {
$signature = $request->header('X-Webhook-Signature');
$timestamp = $request->header('X-Webhook-Timestamp');
$secretKey = config('services.txncheck.webhook_secret');
if (!verifyWebhookSignature(
$request->getContent(),
$signature,
$timestamp,
$secretKey
)) {
return response()->json(['error' => 'Invalid signature'], 401);
}
$data = $request->json();
$event = $data['event'];
switch ($event) {
case 'request.completed':
// Handle completed request
$requestId = $data['data']['requestId'];
Log::info("Request completed: {$requestId}");
break;
case 'request.failed':
// Handle failed request
Log::error("Request failed: {$data['data']['requestId']}");
break;
}
return response()->json(['status' => 'ok']);
});
Laravel Service Provider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\TxnCheckClient;
class TxnCheckServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(TxnCheckClient::class, function ($app) {
return new TxnCheckClient(
apiKey: config('services.txncheck.api_key'),
secretKey: config('services.txncheck.secret_key'),
baseUrl: config('services.txncheck.base_url', 'https://api.txncheck.in/api/v1')
);
});
}
}
// config/services.php
return [
'txncheck' => [
'api_key' => env('FRAUD_BUSTER_API_KEY'),
'secret_key' => env('FRAUD_BUSTER_SECRET_KEY'),
'webhook_secret' => env('FRAUD_BUSTER_WEBHOOK_SECRET'),
'base_url' => env('FRAUD_BUSTER_BASE_URL', 'https://api.txncheck.in/api/v1'),
],
];
Complete Integration Example
<?php
/**
* Complete example: E-commerce checkout verification
*/
class CheckoutVerificationService
{
private TxnCheckClient $client;
public function __construct(TxnCheckClient $client)
{
$this->client = $client;
}
public function verifyCustomerForCheckout(string $mobile, string $paymentVpa): array
{
$outcome = [
'verified' => false,
'riskScore' => 0,
'details' => [
'name' => null,
'panVerified' => false,
'vpaLinked' => false,
'vpaCount' => 0,
'blocklisted' => false,
],
'error' => null,
];
try {
// Step 1: Full verification
error_log("Starting verification for {$mobile}");
$verification = $this->client->fullCheck($mobile, sync: true);
if ($verification['status'] !== 'COMPLETED') {
error_log("Verification incomplete: {$verification['status']}");
$outcome['riskScore'] = 100;
return $outcome;
}
// Step 2: Extract data
$upiData = $verification['result']['upiByMobile'] ?? [];
$kycData = $verification['result']['kycByMobile'] ?? [];
$blocklist = $verification['result']['vpaChargebackCheck'] ?? [];
// Step 3: Check if payment VPA belongs to user
$userVpas = array_map('strtolower', $upiData['upi'] ?? []);
$vpaLinked = in_array(strtolower($paymentVpa), $userVpas);
if (!$vpaLinked) {
error_log("Payment VPA {$paymentVpa} not linked to {$mobile}");
$outcome['riskScore'] += 50;
}
// Step 4: Check blocklist
$blocklistedVpas = array_map(
fn($v) => strtolower($v['vpa']),
$blocklist['blocklisted'] ?? []
);
if (in_array(strtolower($paymentVpa), $blocklistedVpas)) {
error_log("Payment VPA {$paymentVpa} is BLOCKLISTED!");
$outcome['riskScore'] = 100;
$outcome['details']['blocklisted'] = true;
return $outcome;
}
// Step 5: Build result
$outcome['verified'] = $outcome['riskScore'] < 50;
$outcome['details'] = [
'name' => $kycData['fullName'] ?? $upiData['name'] ?? null,
'panVerified' => !empty($kycData['pan']),
'vpaLinked' => $vpaLinked,
'vpaCount' => count($userVpas),
'blocklisted' => false,
];
error_log("Verification complete. Risk score: {$outcome['riskScore']}");
return $outcome;
} catch (\Exception $e) {
error_log("Verification failed: {$e->getMessage()}");
$outcome['riskScore'] = 100;
$outcome['error'] = $e->getMessage();
return $outcome;
}
}
}
// Usage
$client = new TxnCheckClient('fb_your_api_key_here');
$service = new CheckoutVerificationService($client);
$result = $service->verifyCustomerForCheckout(
'+919876543210',
'user@upi'
);
if ($result['verified']) {
echo "✓ Customer verified, proceed with payment\n";
echo " Name: {$result['details']['name']}\n";
} else {
echo "⚠️ Verification failed. Risk score: {$result['riskScore']}\n";
if ($result['details']['blocklisted']) {
echo " Reason: VPA is blocklisted\n";
}
}
Next Steps
Webhooks Guide
Set up webhooks for async notifications
Error Handling
Handle API errors properly
Security Best Practices
Secure your integration
Use Cases
See real-world examples
