Getting Started

Welcome to the Rabbit Payment Gateway API. This documentation will help you integrate our payment system into your applications.

Base URL

https://rabbitpay.in.net/api

Quick Start

  1. Create a merchant account at rabbitpay.in.net and generate API tokens
  2. Implement authentication using your API token and secret
  3. Create payment orders using the API
  4. Handle webhook notifications for payment status updates
Tip: Use our test page to validate your API implementation before going live.

Supported Languages

We provide integration examples for the following programming languages:

  • PHP
  • Python
  • Node.js
  • Java
  • Ruby
  • Go
  • C# / .NET
  • React
  • Vue.js
Need Help?

Contact our support team for integration assistance.

Test API

Authentication

Rabbit API uses API tokens for authentication. You need to include your API token in the request headers.

API Token Structure

  • API Token: pk_xxxxxxxxxxxxxxxxxxxxxxxxx (Public Key)
  • API Secret: sk_xxxxxxxxxxxxxxxxxxxxxxxxx (Secret Key)

Authentication Methods

Header Authentication

Include your API token in the request header:

X-API-Token: pk_your_api_token_here
Content-Type: application/json
Signature Authentication (Recommended)

For enhanced security, use HMAC signature authentication:

X-API-Token: pk_your_api_token_here
X-Signature: sha256_signature_here
Content-Type: application/json
Signature Generation
// PHP Example
$string_to_sign = $api_token . '|' . json_encode($request_data) . '|' . time();
$signature = hash_hmac('sha256', $string_to_sign, $api_secret);

Create Payment Order

POST /api/payment.php

Create a new payment order for processing.

Request Parameters
Parameter Type Required Description
action string Yes Must be "create_order"
amount decimal Yes Payment amount (e.g., 100.00)
order_id string Yes Your unique order identifier
customer_name string Optional Customer's full name
customer_email string Optional Customer's email address
customer_phone string Optional Customer's phone number
product_name string Optional Description of the product/service
redirect_url string Optional URL to redirect after payment
webhook_url string Optional URL for payment notifications
Example Request
// JavaScript/Node.js Example
const response = await fetch('https://yourdomain.com/api/payment.php', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-API-Token': 'pk_your_api_token_here'
    },
    body: JSON.stringify({
        action: 'create_order',
        amount: 100.00,
        order_id: 'ORDER_12345',
        customer_name: 'John Doe',
        customer_email: 'john@example.com',
        customer_phone: '+91 9876543210',
        product_name: 'Premium Subscription',
        redirect_url: 'https://yoursite.com/success',
        webhook_url: 'https://yoursite.com/webhook'
    })
});

const data = await response.json();
// PHP Example
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => 'https://yourdomain.com/api/payment.php',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json',
        'X-API-Token: pk_your_api_token_here'
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'action' => 'create_order',
        'amount' => 100.00,
        'order_id' => 'ORDER_12345',
        'customer_name' => 'John Doe',
        'customer_email' => 'john@example.com',
        'customer_phone' => '+91 9876543210',
        'product_name' => 'Premium Subscription',
        'redirect_url' => 'https://yoursite.com/success',
        'webhook_url' => 'https://yoursite.com/webhook'
    ])
]);

$response = curl_exec($curl);
$data = json_decode($response, true);
// Java Example (using HttpClient - Java 11+)
import java.net.http.*;
import java.net.URI;
import org.json.JSONObject;

HttpClient client = HttpClient.newHttpClient();

JSONObject requestData = new JSONObject();
requestData.put("action", "create_order");
requestData.put("amount", 100.00);
requestData.put("order_id", "ORDER_12345");
requestData.put("customer_name", "John Doe");
requestData.put("customer_email", "john@example.com");
requestData.put("customer_phone", "+91 9876543210");
requestData.put("product_name", "Premium Subscription");
requestData.put("redirect_url", "https://yoursite.com/success");
requestData.put("webhook_url", "https://yoursite.com/webhook");

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://yourdomain.com/api/payment.php"))
    .header("Content-Type", "application/json")
    .header("X-API-Token", "pk_your_api_token_here")
    .POST(HttpRequest.BodyPublishers.ofString(requestData.toString()))
    .build();

HttpResponse<String> response = client.send(request, 
    HttpResponse.BodyHandlers.ofString());

JSONObject responseData = new JSONObject(response.body());
// Java Spring Boot Example (using RestTemplate)
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;

@Service
public class RabbitPayService {
    
    private final RestTemplate restTemplate = new RestTemplate();
    private final String API_URL = "https://yourdomain.com/api/payment.php";
    private final String API_TOKEN = "pk_your_api_token_here";
    
    public ResponseEntity<Map> createPaymentOrder(
        double amount, 
        String orderId,
        String customerName,
        String customerEmail,
        String customerPhone,
        String productName,
        String redirectUrl,
        String webhookUrl
    ) {
        // Prepare headers
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-API-Token", API_TOKEN);
        
        // Prepare request body
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("action", "create_order");
        requestBody.put("amount", amount);
        requestBody.put("order_id", orderId);
        requestBody.put("customer_name", customerName);
        requestBody.put("customer_email", customerEmail);
        requestBody.put("customer_phone", customerPhone);
        requestBody.put("product_name", productName);
        requestBody.put("redirect_url", redirectUrl);
        requestBody.put("webhook_url", webhookUrl);
        
        // Create request entity
        HttpEntity<Map<String, Object>> entity = 
            new HttpEntity<>(requestBody, headers);
        
        // Make API call
        return restTemplate.exchange(
            API_URL,
            HttpMethod.POST,
            entity,
            Map.class
        );
    }
}

// Usage in Controller
@RestController
@RequestMapping("/api/payments")
public class PaymentController {
    
    @Autowired
    private RabbitPayService rabbitPayService;
    
    @PostMapping("/create")
    public ResponseEntity<?> createPayment(@RequestBody PaymentRequest request) {
        ResponseEntity<Map> response = rabbitPayService.createPaymentOrder(
            request.getAmount(),
            request.getOrderId(),
            request.getCustomerName(),
            request.getCustomerEmail(),
            request.getCustomerPhone(),
            request.getProductName(),
            "https://yoursite.com/success",
            "https://yoursite.com/webhook"
        );
        return ResponseEntity.ok(response.getBody());
    }
}
Success Response
{
    "success": true,
    "message": "Payment order created successfully",
    "data": {
        "transaction_id": "TXN_1728655234_5678",
        "order_id": "ORDER_12345",
        "amount": 100.00,
        "currency": "INR",
        "payment_url": "https://yourdomain.com/checkout.php?transaction_id=TXN_1728655234_5678",
        "razorpay_order_id": "order_MkT6xhqPVeGpNl",
        "status": "pending",
        "created_at": "2025-10-11T10:30:00Z"
    }
}
Error Response
{
    "success": false,
    "message": "Invalid API token",
    "error_code": "AUTH_001"
}

Complete Integration Examples

Full working examples for integrating RabbitPay in different programming languages.

PHP Integration
1. Create Payment Order
<?php
// RabbitPay API Configuration
$apiUrl = 'https://rabbitpay.in.net/api/create-order.php';
$apiToken = 'pk_your_api_token_here';

// Payment Data
$paymentData = [
    'user_token' => $apiToken,
    'amount' => 100.00,
    'order_id' => 'ORDER_' . time(),
    'customer_mobile' => '9876543210',
    'redirect_url' => 'https://yoursite.com/payment-callback.php',
    'webhook_url' => 'https://yoursite.com/webhook.php',
    'remark1' => 'Product Purchase',
    'remark2' => 'customer@example.com'
];

// Make API Request
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query($paymentData),
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/x-www-form-urlencoded'
    ]
]);

$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

$result = json_decode($response, true);

if ($result && $result['status']) {
    // Success - redirect user to payment page
    $paymentUrl = $result['result']['payment_url'];
    header('Location: ' . $paymentUrl);
    exit;
} else {
    die('Error: ' . ($result['message'] ?? 'Payment creation failed'));
}
?>
2. Handle Webhook
<?php
// webhook.php - Handle RabbitPay webhooks
header('Content-Type: application/json');

// Get webhook data
$webhookData = json_decode(file_get_contents('php://input'), true);

// Log webhook for debugging
file_put_contents('webhook.log', date('Y-m-d H:i:s') . ': ' . json_encode($webhookData) . PHP_EOL, FILE_APPEND);

// Process webhook
if ($webhookData && isset($webhookData['status'])) {
    $orderId = $webhookData['merchant_order_id'] ?? $webhookData['order_id'];
    $status = $webhookData['status'];
    $transactionId = $webhookData['transaction_id'];
    
    if ($status === 'completed') {
        // Update order status in your database
        // updateOrderStatus($orderId, 'paid', $transactionId);
        
        echo json_encode(['success' => true, 'message' => 'Webhook processed']);
    }
} else {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Invalid webhook data']);
}
?>
3. Check Order Status
<?php
$apiUrl = 'https://rabbitpay.in.net/api/check-order-status.php';
$apiToken = 'pk_your_api_token_here';
$orderId = 'ORDER_12345';

$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'user_token' => $apiToken,
        'order_id' => $orderId
    ])
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

if ($result && $result['status'] !== 'ERROR') {
    $paymentStatus = $result['result']['status'];
    echo "Order Status: $paymentStatus";
}
?>
Python Integration
Installation
pip install requests
1. Create Payment Order
import requests
import time

class RabbitPayClient:
    def __init__(self, api_token):
        self.api_token = api_token
        self.base_url = 'https://rabbitpay.in.net/api'
    
    def create_order(self, amount, order_id, customer_mobile, 
                     redirect_url, webhook_url, remark1='', remark2=''):
        """Create a payment order"""
        url = f'{self.base_url}/create-order.php'
        
        data = {
            'user_token': self.api_token,
            'amount': amount,
            'order_id': order_id,
            'customer_mobile': customer_mobile,
            'redirect_url': redirect_url,
            'webhook_url': webhook_url,
            'remark1': remark1,
            'remark2': remark2
        }
        
        response = requests.post(url, data=data)
        return response.json()
    
    def check_order_status(self, order_id):
        """Check order payment status"""
        url = f'{self.base_url}/check-order-status.php'
        
        data = {
            'user_token': self.api_token,
            'order_id': order_id
        }
        
        response = requests.post(url, data=data)
        return response.json()

# Usage Example
client = RabbitPayClient('pk_your_api_token_here')

# Create payment order
order_id = f'ORDER_{int(time.time())}'
result = client.create_order(
    amount=100.00,
    order_id=order_id,
    customer_mobile='9876543210',
    redirect_url='https://yoursite.com/callback',
    webhook_url='https://yoursite.com/webhook',
    remark1='Product Purchase',
    remark2='customer@example.com'
)

if result.get('status'):
    payment_url = result['result']['payment_url']
    print(f'Payment URL: {payment_url}')
else:
    print(f'Error: {result.get("message")}')
2. Flask Webhook Handler
from flask import Flask, request, jsonify
import logging

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)

@app.route('/webhook', methods=['POST'])
def webhook_handler():
    """Handle RabbitPay webhook notifications"""
    try:
        webhook_data = request.get_json()
        logging.info(f'Webhook received: {webhook_data}')
        
        if webhook_data and webhook_data.get('status') == 'completed':
            order_id = webhook_data.get('merchant_order_id') or webhook_data.get('order_id')
            transaction_id = webhook_data.get('transaction_id')
            
            # Update order in your database
            # update_order_status(order_id, 'paid', transaction_id)
            
            return jsonify({'success': True, 'message': 'Webhook processed'})
        
        return jsonify({'success': False, 'message': 'Invalid data'}), 400
        
    except Exception as e:
        logging.error(f'Webhook error: {str(e)}')
        return jsonify({'success': False, 'message': str(e)}), 500

if __name__ == '__main__':
    app.run(port=5000)
Node.js Integration
Installation
npm install axios express
1. Create Payment Order
const axios = require('axios');

class RabbitPayClient {
    constructor(apiToken) {
        this.apiToken = apiToken;
        this.baseUrl = 'https://rabbitpay.in.net/api';
    }

    async createOrder({ amount, orderId, customerMobile, redirectUrl, webhookUrl, remark1 = '', remark2 = '' }) {
        try {
            const response = await axios.post(
                `${this.baseUrl}/create-order.php`,
                new URLSearchParams({
                    user_token: this.apiToken,
                    amount: amount,
                    order_id: orderId,
                    customer_mobile: customerMobile,
                    redirect_url: redirectUrl,
                    webhook_url: webhookUrl,
                    remark1: remark1,
                    remark2: remark2
                }),
                {
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    }
                }
            );
            return response.data;
        } catch (error) {
            throw new Error(`Payment creation failed: ${error.message}`);
        }
    }

    async checkOrderStatus(orderId) {
        try {
            const response = await axios.post(
                `${this.baseUrl}/check-order-status.php`,
                new URLSearchParams({
                    user_token: this.apiToken,
                    order_id: orderId
                })
            );
            return response.data;
        } catch (error) {
            throw new Error(`Status check failed: ${error.message}`);
        }
    }
}

// Usage Example
const client = new RabbitPayClient('pk_your_api_token_here');

async function processPayment() {
    const orderId = `ORDER_${Date.now()}`;
    
    try {
        const result = await client.createOrder({
            amount: 100.00,
            orderId: orderId,
            customerMobile: '9876543210',
            redirectUrl: 'https://yoursite.com/callback',
            webhookUrl: 'https://yoursite.com/webhook',
            remark1: 'Product Purchase',
            remark2: 'customer@example.com'
        });

        if (result.status) {
            console.log('Payment URL:', result.result.payment_url);
            // Redirect user to payment_url
        }
    } catch (error) {
        console.error('Error:', error.message);
    }
}

processPayment();
2. Express.js Webhook Handler
const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
    const webhookData = req.body;
    console.log('Webhook received:', webhookData);

    if (webhookData && webhookData.status === 'completed') {
        const orderId = webhookData.merchant_order_id || webhookData.order_id;
        const transactionId = webhookData.transaction_id;
        
        // Update order status in your database
        // updateOrderStatus(orderId, 'paid', transactionId);
        
        res.json({ success: true, message: 'Webhook processed' });
    } else {
        res.status(400).json({ success: false, message: 'Invalid webhook data' });
    }
});

app.listen(3000, () => {
    console.log('Webhook server running on port 3000');
});
Ruby Integration
Installation
gem install httparty
Ruby Client
require 'httparty'
require 'json'

class RabbitPayClient
  include HTTParty
  base_uri 'https://rabbitpay.in.net/api'

  def initialize(api_token)
    @api_token = api_token
  end

  def create_order(amount:, order_id:, customer_mobile:, redirect_url:, webhook_url:, remark1: '', remark2: '')
    response = self.class.post('/create-order.php',
      body: {
        user_token: @api_token,
        amount: amount,
        order_id: order_id,
        customer_mobile: customer_mobile,
        redirect_url: redirect_url,
        webhook_url: webhook_url,
        remark1: remark1,
        remark2: remark2
      }
    )
    JSON.parse(response.body)
  end

  def check_order_status(order_id)
    response = self.class.post('/check-order-status.php',
      body: {
        user_token: @api_token,
        order_id: order_id
      }
    )
    JSON.parse(response.body)
  end
end

# Usage
client = RabbitPayClient.new('pk_your_api_token_here')

result = client.create_order(
  amount: 100.00,
  order_id: "ORDER_#{Time.now.to_i}",
  customer_mobile: '9876543210',
  redirect_url: 'https://yoursite.com/callback',
  webhook_url: 'https://yoursite.com/webhook',
  remark1: 'Product Purchase',
  remark2: 'customer@example.com'
)

if result['status']
  puts "Payment URL: #{result['result']['payment_url']}"
else
  puts "Error: #{result['message']}"
end
Rails Webhook Handler
# config/routes.rb
post '/webhook', to: 'webhooks#rabbit_pay'

# app/controllers/webhooks_controller.rb
class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token

  def rabbit_pay
    webhook_data = JSON.parse(request.body.read)
    Rails.logger.info "Webhook received: #{webhook_data}"

    if webhook_data['status'] == 'completed'
      order_id = webhook_data['merchant_order_id'] || webhook_data['order_id']
      transaction_id = webhook_data['transaction_id']
      
      # Update order
      # Order.find_by(order_id: order_id)&.update(status: 'paid', transaction_id: transaction_id)
      
      render json: { success: true, message: 'Webhook processed' }
    else
      render json: { success: false, message: 'Invalid data' }, status: :bad_request
    end
  rescue JSON::ParserError => e
    render json: { success: false, message: 'Invalid JSON' }, status: :bad_request
  end
end
Go Integration
Go Client
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
    "time"
)

type RabbitPayClient struct {
    APIToken string
    BaseURL  string
}

type OrderRequest struct {
    UserToken      string  `json:"user_token"`
    Amount         float64 `json:"amount"`
    OrderID        string  `json:"order_id"`
    CustomerMobile string  `json:"customer_mobile"`
    RedirectURL    string  `json:"redirect_url"`
    WebhookURL     string  `json:"webhook_url"`
    Remark1        string  `json:"remark1"`
    Remark2        string  `json:"remark2"`
}

func NewRabbitPayClient(apiToken string) *RabbitPayClient {
    return &RabbitPayClient{
        APIToken: apiToken,
        BaseURL:  "https://rabbitpay.in.net/api",
    }
}

func (c *RabbitPayClient) CreateOrder(amount float64, orderID, customerMobile, redirectURL, webhookURL, remark1, remark2 string) (map[string]interface{}, error) {
    // Prepare form data
    data := url.Values{}
    data.Set("user_token", c.APIToken)
    data.Set("amount", fmt.Sprintf("%.2f", amount))
    data.Set("order_id", orderID)
    data.Set("customer_mobile", customerMobile)
    data.Set("redirect_url", redirectURL)
    data.Set("webhook_url", webhookURL)
    data.Set("remark1", remark1)
    data.Set("remark2", remark2)

    // Make request
    resp, err := http.PostForm(c.BaseURL+"/create-order.php", data)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    // Parse response
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    var result map[string]interface{}
    err = json.Unmarshal(body, &result)
    return result, err
}

func (c *RabbitPayClient) CheckOrderStatus(orderID string) (map[string]interface{}, error) {
    data := url.Values{}
    data.Set("user_token", c.APIToken)
    data.Set("order_id", orderID)

    resp, err := http.PostForm(c.BaseURL+"/check-order-status.php", data)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    var result map[string]interface{}
    err = json.Unmarshal(body, &result)
    return result, err
}

func main() {
    client := NewRabbitPayClient("pk_your_api_token_here")

    orderID := fmt.Sprintf("ORDER_%d", time.Now().Unix())
    result, err := client.CreateOrder(
        100.00,
        orderID,
        "9876543210",
        "https://yoursite.com/callback",
        "https://yoursite.com/webhook",
        "Product Purchase",
        "customer@example.com",
    )

    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    if result["status"].(bool) {
        paymentURL := result["result"].(map[string]interface{})["payment_url"]
        fmt.Printf("Payment URL: %s\n", paymentURL)
    }
}
Go Webhook Handler
package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type WebhookData struct {
    Event           string  `json:"event"`
    TransactionID   string  `json:"transaction_id"`
    OrderID         string  `json:"order_id"`
    MerchantOrderID string  `json:"merchant_order_id"`
    Status          string  `json:"status"`
    Amount          float64 `json:"amount"`
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }

    var webhookData WebhookData
    err := json.NewDecoder(r.Body).Decode(&webhookData)
    if err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }

    log.Printf("Webhook received: %+v", webhookData)

    if webhookData.Status == "completed" {
        orderID := webhookData.MerchantOrderID
        if orderID == "" {
            orderID = webhookData.OrderID
        }
        
        // Update order in database
        // updateOrderStatus(orderID, "paid", webhookData.TransactionID)
        
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(map[string]interface{}{
            "success": true,
            "message": "Webhook processed",
        })
    } else {
        http.Error(w, "Invalid webhook data", http.StatusBadRequest)
    }
}

func main() {
    http.HandleFunc("/webhook", webhookHandler)
    log.Println("Webhook server running on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}
C# / .NET Integration
Installation
dotnet add package Newtonsoft.Json
C# Client
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

public class RabbitPayClient
{
    private readonly string _apiToken;
    private readonly string _baseUrl = "https://rabbitpay.in.net/api";
    private readonly HttpClient _httpClient;

    public RabbitPayClient(string apiToken)
    {
        _apiToken = apiToken;
        _httpClient = new HttpClient();
    }

    public async Task CreateOrder(
        decimal amount, 
        string orderId, 
        string customerMobile,
        string redirectUrl, 
        string webhookUrl,
        string remark1 = "",
        string remark2 = "")
    {
        var data = new Dictionary
        {
            { "user_token", _apiToken },
            { "amount", amount.ToString("F2") },
            { "order_id", orderId },
            { "customer_mobile", customerMobile },
            { "redirect_url", redirectUrl },
            { "webhook_url", webhookUrl },
            { "remark1", remark1 },
            { "remark2", remark2 }
        };

        var content = new FormUrlEncodedContent(data);
        var response = await _httpClient.PostAsync($"{_baseUrl}/create-order.php", content);
        var responseString = await response.Content.ReadAsStringAsync();
        
        return JsonConvert.DeserializeObject(responseString);
    }

    public async Task CheckOrderStatus(string orderId)
    {
        var data = new Dictionary
        {
            { "user_token", _apiToken },
            { "order_id", orderId }
        };

        var content = new FormUrlEncodedContent(data);
        var response = await _httpClient.PostAsync($"{_baseUrl}/check-order-status.php", content);
        var responseString = await response.Content.ReadAsStringAsync();
        
        return JsonConvert.DeserializeObject(responseString);
    }
}

// Usage Example
class Program
{
    static async Task Main(string[] args)
    {
        var client = new RabbitPayClient("pk_your_api_token_here");
        
        var orderId = $"ORDER_{DateTimeOffset.Now.ToUnixTimeSeconds()}";
        
        var result = await client.CreateOrder(
            amount: 100.00m,
            orderId: orderId,
            customerMobile: "9876543210",
            redirectUrl: "https://yoursite.com/callback",
            webhookUrl: "https://yoursite.com/webhook",
            remark1: "Product Purchase",
            remark2: "customer@example.com"
        );

        if (result.status == true)
        {
            Console.WriteLine($"Payment URL: {result.result.payment_url}");
        }
        else
        {
            Console.WriteLine($"Error: {result.message}");
        }
    }
}
ASP.NET Core Webhook Handler
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

[ApiController]
[Route("api/[controller]")]
public class WebhookController : ControllerBase
{
    private readonly ILogger _logger;

    public WebhookController(ILogger logger)
    {
        _logger = logger;
    }

    [HttpPost]
    public async Task RabbitPayWebhook([FromBody] JsonElement webhookData)
    {
        _logger.LogInformation($"Webhook received: {webhookData}");

        try
        {
            var status = webhookData.GetProperty("status").GetString();
            
            if (status == "completed")
            {
                var orderId = webhookData.TryGetProperty("merchant_order_id", out var merchantOrderId) 
                    ? merchantOrderId.GetString() 
                    : webhookData.GetProperty("order_id").GetString();
                    
                var transactionId = webhookData.GetProperty("transaction_id").GetString();
                
                // Update order in database
                // await UpdateOrderStatusAsync(orderId, "paid", transactionId);
                
                return Ok(new { success = true, message = "Webhook processed" });
            }
            
            return BadRequest(new { success = false, message = "Invalid webhook data" });
        }
        catch (Exception ex)
        {
            _logger.LogError($"Webhook processing error: {ex.Message}");
            return StatusCode(500, new { success = false, message = ex.Message });
        }
    }
}

Verify Payment Status

POST /api/payment.php

Verify the status of a payment transaction.

Request Parameters
Parameter Type Required Description
action string Yes Must be "verify_payment"
transaction_id string Yes Transaction ID from create order response
order_id string Optional Your original order ID
Example Request
const response = await fetch('https://yourdomain.com/api/payment.php', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-API-Token': 'pk_your_api_token_here'
    },
    body: JSON.stringify({
        action: 'verify_payment',
        transaction_id: 'TXN_1728655234_5678'
    })
});

const data = await response.json();
// Java Example
import java.net.http.*;
import org.json.JSONObject;

HttpClient client = HttpClient.newHttpClient();

JSONObject requestData = new JSONObject();
requestData.put("action", "verify_payment");
requestData.put("transaction_id", "TXN_1728655234_5678");

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://yourdomain.com/api/payment.php"))
    .header("Content-Type", "application/json")
    .header("X-API-Token", "pk_your_api_token_here")
    .POST(HttpRequest.BodyPublishers.ofString(requestData.toString()))
    .build();

HttpResponse<String> response = client.send(request, 
    HttpResponse.BodyHandlers.ofString());
JSONObject data = new JSONObject(response.body());
// Java Spring Boot Example
@Service
public class RabbitPayService {
    
    private final RestTemplate restTemplate = new RestTemplate();
    private final String API_URL = "https://yourdomain.com/api/payment.php";
    private final String API_TOKEN = "pk_your_api_token_here";
    
    public ResponseEntity<Map> verifyPayment(String transactionId) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-API-Token", API_TOKEN);
        
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("action", "verify_payment");
        requestBody.put("transaction_id", transactionId);
        
        HttpEntity<Map<String, Object>> entity = 
            new HttpEntity<>(requestBody, headers);
        
        return restTemplate.exchange(
            API_URL,
            HttpMethod.POST,
            entity,
            Map.class
        );
    }
}

// Usage in Controller
@GetMapping("/verify/{transactionId}")
public ResponseEntity<?> verifyPayment(@PathVariable String transactionId) {
    ResponseEntity<Map> response = rabbitPayService.verifyPayment(transactionId);
    return ResponseEntity.ok(response.getBody());
}
Success Response
{
    "success": true,
    "data": {
        "transaction_id": "TXN_1728655234_5678",
        "order_id": "ORDER_12345",
        "amount": 100.00,
        "currency": "INR",
        "status": "completed",
        "payment_method": "razorpay",
        "razorpay_payment_id": "pay_MkT6xhqPVeGpNl",
        "created_at": "2025-10-11T10:30:00Z",
        "completed_at": "2025-10-11T10:32:15Z",
        "customer": {
            "name": "John Doe",
            "email": "john@example.com",
            "phone": "+91 9876543210"
        }
    }
}

Check Order Status

GET /api/check-order-status.php

Get the current status of an order by order ID or transaction ID.

Query Parameters
Parameter Type Required Description
order_id string Yes* Your order ID
transaction_id string Yes* Rabbit Pay transaction ID
* Either order_id or transaction_id is required
Example Request
GET https://yourdomain.com/api/check-order-status.php?order_id=ORDER_12345
X-API-Token: pk_your_api_token_here
Response
{
    "success": true,
    "status": "completed",
    "data": {
        "order_id": "ORDER_12345",
        "transaction_id": "TXN_1728655234_5678",
        "amount": 100.00,
        "currency": "INR",
        "status": "completed",
        "created_at": "2025-10-11T10:30:00Z",
        "updated_at": "2025-10-11T10:32:15Z"
    }
}

Webhooks

Webhooks allow you to receive real-time notifications when payment status changes.

Webhook Configuration

Configure webhook URLs in your merchant dashboard or include them in payment creation requests.

Webhook Payload
{
    "event": "payment.completed",
    "data": {
        "transaction_id": "TXN_1728655234_5678",
        "order_id": "ORDER_12345",
        "amount": 100.00,
        "currency": "INR",
        "status": "completed",
        "payment_method": "razorpay",
        "razorpay_payment_id": "pay_MkT6xhqPVeGpNl",
        "customer": {
            "name": "John Doe",
            "email": "john@example.com",
            "phone": "+91 9876543210"
        },
        "timestamp": "2025-10-11T10:32:15Z"
    },
    "signature": "sha256_signature_for_verification"
}
Webhook Verification
// PHP Webhook Verification
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';

$calculated_signature = hash_hmac('sha256', $payload, $your_api_secret);

if (hash_equals($calculated_signature, $signature)) {
    // Webhook is authentic
    $data = json_decode($payload, true);
    // Process the webhook data
} else {
    // Invalid webhook
    http_response_code(400);
    echo 'Invalid signature';
}
// Node.js Webhook Handler
const crypto = require('crypto');
const express = require('express');
const app = express();

app.use(express.json());

app.post('/webhook', (req, res) => {
    const payload = JSON.stringify(req.body);
    const signature = req.headers['x-signature'];
    const apiSecret = 'sk_your_api_secret_here';
    
    const calculatedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(payload)
        .digest('hex');
    
    if (signature === calculatedSignature) {
        // Webhook is authentic
        const data = req.body;
        
        // Process webhook based on event type
        switch(data.event) {
            case 'payment.completed':
                // Handle successful payment
                console.log('Payment completed:', data.data);
                break;
            case 'payment.failed':
                // Handle failed payment
                console.log('Payment failed:', data.data);
                break;
        }
        
        res.status(200).json({ success: true });
    } else {
        res.status(400).json({ error: 'Invalid signature' });
    }
});
// Java Webhook Handler (using Servlet)
import javax.servlet.http.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.util.Base64;
import org.json.JSONObject;

public class WebhookServlet extends HttpServlet {
    
    private static final String API_SECRET = "sk_your_api_secret_here";
    
    @Override
    protected void doPost(HttpServletRequest request, 
                         HttpServletResponse response) 
                         throws IOException {
        
        // Read the payload
        StringBuilder payload = new StringBuilder();
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            payload.append(line);
        }
        
        String payloadStr = payload.toString();
        String receivedSignature = request.getHeader("X-Signature");
        
        // Calculate signature
        String calculatedSignature = calculateHMAC(payloadStr, API_SECRET);
        
        // Verify signature
        if (calculatedSignature.equals(receivedSignature)) {
            // Webhook is authentic
            JSONObject data = new JSONObject(payloadStr);
            String event = data.getString("event");
            JSONObject eventData = data.getJSONObject("data");
            
            // Process webhook based on event type
            switch (event) {
                case "payment.completed":
                    handlePaymentCompleted(eventData);
                    break;
                case "payment.failed":
                    handlePaymentFailed(eventData);
                    break;
                case "payment.cancelled":
                    handlePaymentCancelled(eventData);
                    break;
            }
            
            response.setStatus(HttpServletResponse.SC_OK);
            response.getWriter().write("{\"success\": true}");
        } else {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write("{\"error\": \"Invalid signature\"}");
        }
    }
    
    private String calculateHMAC(String data, String secret) {
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(
                secret.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            
            byte[] hash = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException("Error calculating HMAC", e);
        }
    }
    
    private void handlePaymentCompleted(JSONObject data) {
        String transactionId = data.getString("transaction_id");
        String orderId = data.getString("order_id");
        double amount = data.getDouble("amount");
        
        // Update your database
        // Send confirmation email
        // Fulfill the order
        System.out.println("Payment completed for order: " + orderId);
    }
    
    private void handlePaymentFailed(JSONObject data) {
        String transactionId = data.getString("transaction_id");
        String orderId = data.getString("order_id");
        
        // Update order status
        // Notify customer
        System.out.println("Payment failed for order: " + orderId);
    }
    
    private void handlePaymentCancelled(JSONObject data) {
        String transactionId = data.getString("transaction_id");
        String orderId = data.getString("order_id");
        
        // Handle cancellation
        System.out.println("Payment cancelled for order: " + orderId);
    }
}
// Java Spring Boot Webhook Handler
import org.springframework.web.bind.annotation.*;
import org.springframework.http.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Map;

@RestController
@RequestMapping("/webhook")
public class WebhookController {
    
    private static final String API_SECRET = "sk_your_api_secret_here";
    
    @PostMapping("/rabbitpay")
    public ResponseEntity<Map<String, Object>> handleWebhook(
        @RequestBody Map<String, Object> payload,
        @RequestHeader("X-Signature") String signature
    ) {
        try {
            // Convert payload to JSON string for verification
            String payloadStr = new ObjectMapper().writeValueAsString(payload);
            
            // Calculate and verify signature
            String calculatedSignature = calculateHMAC(payloadStr, API_SECRET);
            
            if (!calculatedSignature.equals(signature)) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(Map.of("error", "Invalid signature"));
            }
            
            // Signature is valid, process webhook
            String event = (String) payload.get("event");
            Map<String, Object> data = 
                (Map<String, Object>) payload.get("data");
            
            switch (event) {
                case "payment.completed":
                    handlePaymentCompleted(data);
                    break;
                case "payment.failed":
                    handlePaymentFailed(data);
                    break;
                case "payment.cancelled":
                    handlePaymentCancelled(data);
                    break;
                default:
                    System.out.println("Unknown event: " + event);
            }
            
            return ResponseEntity.ok(Map.of("success", true));
            
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(Map.of("error", "Internal server error"));
        }
    }
    
    private String calculateHMAC(String data, String secret) {
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(
                secret.getBytes("UTF-8"), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            
            byte[] hash = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException("Error calculating HMAC", e);
        }
    }
    
    private void handlePaymentCompleted(Map<String, Object> data) {
        String transactionId = (String) data.get("transaction_id");
        String orderId = (String) data.get("order_id");
        Double amount = (Double) data.get("amount");
        
        // Process successful payment
        // 1. Update order status in database
        // 2. Send confirmation email to customer
        // 3. Trigger order fulfillment
        // 4. Update inventory
        
        System.out.println("Payment completed for order: " + orderId 
            + ", Amount: " + amount);
    }
    
    private void handlePaymentFailed(Map<String, Object> data) {
        String transactionId = (String) data.get("transaction_id");
        String orderId = (String) data.get("order_id");
        
        // Handle failed payment
        // 1. Update order status to failed
        // 2. Notify customer about failure
        // 3. Log the failure reason
        
        System.out.println("Payment failed for order: " + orderId);
    }
    
    private void handlePaymentCancelled(Map<String, Object> data) {
        String transactionId = (String) data.get("transaction_id");
        String orderId = (String) data.get("order_id");
        
        // Handle cancelled payment
        // 1. Update order status to cancelled
        // 2. Release reserved inventory
        // 3. Notify relevant parties
        
        System.out.println("Payment cancelled for order: " + orderId);
    }
}

// Optional: Create a Service layer for better organization
@Service
public class PaymentWebhookService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private EmailService emailService;
    
    @Transactional
    public void processPaymentCompleted(Map<String, Object> data) {
        String orderId = (String) data.get("order_id");
        Double amount = (Double) data.get("amount");
        
        // Update order in database
        Order order = orderRepository.findByOrderId(orderId);
        if (order != null) {
            order.setStatus("COMPLETED");
            order.setPaymentStatus("PAID");
            order.setPaidAmount(amount);
            order.setCompletedAt(LocalDateTime.now());
            orderRepository.save(order);
            
            // Send confirmation email
            emailService.sendOrderConfirmation(order);
            
            // Additional business logic
        }
    }
}
Webhook Security Best Practices
  • Always verify signatures: Never trust webhook data without verification
  • Use HTTPS: Ensure your webhook endpoint uses HTTPS
  • Implement idempotency: Handle duplicate webhook deliveries gracefully
  • Respond quickly: Return 200 OK within 5 seconds to avoid retries
  • Process asynchronously: Queue webhook processing for heavy operations
  • Log everything: Keep detailed logs of all webhook requests
  • Handle retries: We retry failed webhooks up to 3 times with exponential backoff
Webhook Events
  • payment.created - Payment order created
  • payment.completed - Payment successfully completed
  • payment.failed - Payment failed
  • payment.cancelled - Payment cancelled by user

Error Codes

Error Code HTTP Status Description
AUTH_001 401 Invalid or missing API token
AUTH_002 401 Inactive API token
AUTH_003 401 Invalid signature
PARAM_001 400 Missing required parameter
PARAM_002 400 Invalid parameter format
ORDER_001 409 Duplicate order ID
ORDER_002 404 Order not found
PAYMENT_001 422 Payment processing failed
RATE_001 429 Rate limit exceeded
SERVER_001 500 Internal server error

Java & Spring Boot Integration Guide

Complete integration guide for Java and Spring Boot applications
1. Maven Dependencies

Add these dependencies to your pom.xml:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring Boot Starter Data JPA (for database) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    
    <!-- JSON Processing -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    
    <!-- For Java 8 HTTP Client Alternative -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.13</version>
    </dependency>
    
    <!-- Lombok (Optional - for cleaner code) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
2. Configuration Class

Create a configuration class for Rabbit Pay settings:

// RabbitPayConfig.java
package com.yourcompany.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import lombok.Data;

@Configuration
@ConfigurationProperties(prefix = "rabbitpay")
@Data
public class RabbitPayConfig {
    private String apiUrl;
    private String apiToken;
    private String apiSecret;
    private String webhookUrl;
    private String redirectUrl;
}

// application.properties or application.yml
rabbitpay.api-url=https://yourdomain.com/api/payment.php
rabbitpay.api-token=pk_your_api_token_here
rabbitpay.api-secret=sk_your_api_secret_here
rabbitpay.webhook-url=https://yoursite.com/webhook/rabbitpay
rabbitpay.redirect-url=https://yoursite.com/payment/success
3. DTOs (Data Transfer Objects)
// PaymentRequest.java
package com.yourcompany.dto;

import lombok.Data;
import lombok.Builder;
import com.fasterxml.jackson.annotation.JsonProperty;

@Data
@Builder
public class PaymentRequest {
    private String action;
    private Double amount;
    
    @JsonProperty("order_id")
    private String orderId;
    
    @JsonProperty("customer_name")
    private String customerName;
    
    @JsonProperty("customer_email")
    private String customerEmail;
    
    @JsonProperty("customer_phone")
    private String customerPhone;
    
    @JsonProperty("product_name")
    private String productName;
    
    @JsonProperty("redirect_url")
    private String redirectUrl;
    
    @JsonProperty("webhook_url")
    private String webhookUrl;
}

// PaymentResponse.java
package com.yourcompany.dto;

import lombok.Data;
import com.fasterxml.jackson.annotation.JsonProperty;

@Data
public class PaymentResponse {
    private Boolean success;
    private String message;
    private PaymentData data;
    
    @JsonProperty("error_code")
    private String errorCode;
}

@Data
class PaymentData {
    @JsonProperty("transaction_id")
    private String transactionId;
    
    @JsonProperty("order_id")
    private String orderId;
    
    private Double amount;
    private String currency;
    
    @JsonProperty("payment_url")
    private String paymentUrl;
    
    @JsonProperty("razorpay_order_id")
    private String razorpayOrderId;
    
    private String status;
    
    @JsonProperty("created_at")
    private String createdAt;
}

// WebhookPayload.java
package com.yourcompany.dto;

import lombok.Data;
import java.util.Map;

@Data
public class WebhookPayload {
    private String event;
    private Map<String, Object> data;
    private String signature;
    private String timestamp;
}
4. Service Layer - Complete Implementation
// RabbitPayService.java
package com.yourcompany.service;

import com.yourcompany.config.RabbitPayConfig;
import com.yourcompany.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

@Service
@Slf4j
public class RabbitPayService {
    
    @Autowired
    private RabbitPayConfig config;
    
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * Create a payment order
     */
    public PaymentResponse createPaymentOrder(
        Double amount,
        String orderId,
        String customerName,
        String customerEmail,
        String customerPhone,
        String productName
    ) {
        try {
            // Prepare headers
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("X-API-Token", config.getApiToken());
            
            // Build request
            PaymentRequest request = PaymentRequest.builder()
                .action("create_order")
                .amount(amount)
                .orderId(orderId)
                .customerName(customerName)
                .customerEmail(customerEmail)
                .customerPhone(customerPhone)
                .productName(productName)
                .redirectUrl(config.getRedirectUrl())
                .webhookUrl(config.getWebhookUrl())
                .build();
            
            HttpEntity<PaymentRequest> entity = 
                new HttpEntity<>(request, headers);
            
            // Make API call
            ResponseEntity<PaymentResponse> response = restTemplate.exchange(
                config.getApiUrl(),
                HttpMethod.POST,
                entity,
                PaymentResponse.class
            );
            
            log.info("Payment order created successfully: {}", 
                response.getBody().getData().getTransactionId());
            
            return response.getBody();
            
        } catch (HttpClientErrorException e) {
            log.error("Error creating payment order: {}", e.getMessage());
            throw new RuntimeException("Payment creation failed: " 
                + e.getResponseBodyAsString());
        } catch (Exception e) {
            log.error("Unexpected error: {}", e.getMessage());
            throw new RuntimeException("Payment creation failed", e);
        }
    }
    
    /**
     * Verify payment status
     */
    public PaymentResponse verifyPayment(String transactionId) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("X-API-Token", config.getApiToken());
            
            PaymentRequest request = PaymentRequest.builder()
                .action("verify_payment")
                .build();
            
            // Add transaction_id to the request
            Map<String, Object> requestMap = new HashMap<>();
            requestMap.put("action", "verify_payment");
            requestMap.put("transaction_id", transactionId);
            
            HttpEntity<Map<String, Object>> entity = 
                new HttpEntity<>(requestMap, headers);
            
            ResponseEntity<PaymentResponse> response = restTemplate.exchange(
                config.getApiUrl(),
                HttpMethod.POST,
                entity,
                PaymentResponse.class
            );
            
            log.info("Payment verification result: {}", 
                response.getBody().getData().getStatus());
            
            return response.getBody();
            
        } catch (Exception e) {
            log.error("Error verifying payment: {}", e.getMessage());
            throw new RuntimeException("Payment verification failed", e);
        }
    }
    
    /**
     * Calculate HMAC signature for webhook verification
     */
    public String calculateHMAC(String data, String secret) {
        try {
            Mac sha256HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKey = new SecretKeySpec(
                secret.getBytes(StandardCharsets.UTF_8), 
                "HmacSHA256"
            );
            sha256HMAC.init(secretKey);
            
            byte[] hash = sha256HMAC.doFinal(
                data.getBytes(StandardCharsets.UTF_8)
            );
            
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString();
            
        } catch (Exception e) {
            throw new RuntimeException("Error calculating HMAC", e);
        }
    }
    
    /**
     * Verify webhook signature
     */
    public boolean verifyWebhookSignature(String payload, String signature) {
        String calculatedSignature = calculateHMAC(
            payload, 
            config.getApiSecret()
        );
        return calculatedSignature.equals(signature);
    }
}

// RestTemplate Configuration
@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
5. Controller - Payment Endpoints
// PaymentController.java
package com.yourcompany.controller;

import com.yourcompany.dto.*;
import com.yourcompany.service.RabbitPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

@RestController
@RequestMapping("/api/payments")
@Slf4j
public class PaymentController {
    
    @Autowired
    private RabbitPayService rabbitPayService;
    
    /**
     * Create a new payment order
     */
    @PostMapping("/create")
    public ResponseEntity<?> createPayment(
        @RequestBody CreatePaymentRequest request
    ) {
        try {
            PaymentResponse response = rabbitPayService.createPaymentOrder(
                request.getAmount(),
                request.getOrderId(),
                request.getCustomerName(),
                request.getCustomerEmail(),
                request.getCustomerPhone(),
                request.getProductName()
            );
            
            if (response.getSuccess()) {
                return ResponseEntity.ok(response);
            } else {
                return ResponseEntity.badRequest().body(response);
            }
            
        } catch (Exception e) {
            log.error("Error creating payment", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(Map.of("error", e.getMessage()));
        }
    }
    
    /**
     * Verify payment status
     */
    @GetMapping("/verify/{transactionId}")
    public ResponseEntity<?> verifyPayment(
        @PathVariable String transactionId
    ) {
        try {
            PaymentResponse response = 
                rabbitPayService.verifyPayment(transactionId);
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            log.error("Error verifying payment", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(Map.of("error", e.getMessage()));
        }
    }
    
    /**
     * Payment success callback page
     */
    @GetMapping("/success")
    public ResponseEntity<String> paymentSuccess(
        @RequestParam(required = false) String transaction_id,
        @RequestParam(required = false) String order_id
    ) {
        log.info("Payment success callback - Transaction: {}, Order: {}", 
            transaction_id, order_id);
        
        // Redirect to frontend success page or return success view
        return ResponseEntity.ok("Payment successful!");
    }
}

// CreatePaymentRequest.java
@Data
public class CreatePaymentRequest {
    private Double amount;
    private String orderId;
    private String customerName;
    private String customerEmail;
    private String customerPhone;
    private String productName;
}
6. Webhook Controller - Complete Implementation
// WebhookController.java
package com.yourcompany.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yourcompany.dto.WebhookPayload;
import com.yourcompany.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@RestController
@RequestMapping("/webhook")
@Slf4j
public class WebhookController {
    
    @Autowired
    private RabbitPayService rabbitPayService;
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private EmailService emailService;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    /**
     * Handle Rabbit Pay webhook notifications
     */
    @PostMapping("/rabbitpay")
    public ResponseEntity<Map<String, Object>> handleRabbitPayWebhook(
        @RequestBody String payload,
        @RequestHeader(value = "X-Signature", required = false) String signature
    ) {
        log.info("Received webhook payload");
        
        try {
            // Verify signature
            if (signature == null || signature.isEmpty()) {
                log.error("Missing webhook signature");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(Map.of("error", "Missing signature"));
            }
            
            if (!rabbitPayService.verifyWebhookSignature(payload, signature)) {
                log.error("Invalid webhook signature");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                    .body(Map.of("error", "Invalid signature"));
            }
            
            // Parse payload
            WebhookPayload webhookData = 
                objectMapper.readValue(payload, WebhookPayload.class);
            
            String event = webhookData.getEvent();
            Map<String, Object> data = webhookData.getData();
            
            log.info("Processing webhook event: {}", event);
            
            // Process webhook based on event type
            switch (event) {
                case "payment.created":
                    handlePaymentCreated(data);
                    break;
                    
                case "payment.completed":
                    handlePaymentCompleted(data);
                    break;
                    
                case "payment.failed":
                    handlePaymentFailed(data);
                    break;
                    
                case "payment.cancelled":
                    handlePaymentCancelled(data);
                    break;
                    
                default:
                    log.warn("Unknown webhook event: {}", event);
            }
            
            // Return success response
            return ResponseEntity.ok(Map.of(
                "success", true,
                "message", "Webhook processed successfully"
            ));
            
        } catch (Exception e) {
            log.error("Error processing webhook", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(Map.of("error", "Internal server error"));
        }
    }
    
    private void handlePaymentCreated(Map<String, Object> data) {
        String orderId = (String) data.get("order_id");
        String transactionId = (String) data.get("transaction_id");
        
        log.info("Payment created - Order: {}, Transaction: {}", 
            orderId, transactionId);
        
        // Update order status to 'payment_initiated'
        orderService.updateOrderStatus(orderId, "PAYMENT_INITIATED");
    }
    
    private void handlePaymentCompleted(Map<String, Object> data) {
        String orderId = (String) data.get("order_id");
        String transactionId = (String) data.get("transaction_id");
        Double amount = ((Number) data.get("amount")).doubleValue();
        String paymentMethod = (String) data.get("payment_method");
        
        log.info("Payment completed - Order: {}, Amount: {}", 
            orderId, amount);
        
        // Update order in database
        orderService.markOrderAsPaid(
            orderId, 
            transactionId, 
            amount, 
            paymentMethod
        );
        
        // Send confirmation email
        emailService.sendPaymentConfirmation(orderId);
        
        // Trigger order fulfillment
        orderService.initiateOrderFulfillment(orderId);
        
        // Update inventory
        orderService.updateInventory(orderId);
    }
    
    private void handlePaymentFailed(Map<String, Object> data) {
        String orderId = (String) data.get("order_id");
        String transactionId = (String) data.get("transaction_id");
        
        log.warn("Payment failed - Order: {}", orderId);
        
        // Update order status
        orderService.updateOrderStatus(orderId, "PAYMENT_FAILED");
        
        // Notify customer
        emailService.sendPaymentFailureNotification(orderId);
        
        // Release any reserved inventory
        orderService.releaseReservedInventory(orderId);
    }
    
    private void handlePaymentCancelled(Map<String, Object> data) {
        String orderId = (String) data.get("order_id");
        String transactionId = (String) data.get("transaction_id");
        
        log.info("Payment cancelled - Order: {}", orderId);
        
        // Update order status
        orderService.updateOrderStatus(orderId, "PAYMENT_CANCELLED");
        
        // Release inventory
        orderService.releaseReservedInventory(orderId);
    }
}
7. Usage Example - Complete Flow
// Example: E-commerce Checkout Flow
@Service
public class CheckoutService {
    
    @Autowired
    private RabbitPayService rabbitPayService;
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Transactional
    public PaymentResponse initiateCheckout(CheckoutRequest request) {
        // 1. Create order in your database
        Order order = new Order();
        order.setOrderId(generateOrderId());
        order.setCustomerName(request.getCustomerName());
        order.setCustomerEmail(request.getCustomerEmail());
        order.setCustomerPhone(request.getCustomerPhone());
        order.setAmount(request.getAmount());
        order.setStatus("PENDING");
        order.setCreatedAt(LocalDateTime.now());
        orderRepository.save(order);
        
        // 2. Create payment with Rabbit Pay
        PaymentResponse paymentResponse = rabbitPayService.createPaymentOrder(
            order.getAmount(),
            order.getOrderId(),
            order.getCustomerName(),
            order.getCustomerEmail(),
            order.getCustomerPhone(),
            request.getProductName()
        );
        
        // 3. Store transaction ID
        if (paymentResponse.getSuccess()) {
            order.setTransactionId(
                paymentResponse.getData().getTransactionId()
            );
            order.setPaymentUrl(
                paymentResponse.getData().getPaymentUrl()
            );
            orderRepository.save(order);
        }
        
        return paymentResponse;
    }
    
    private String generateOrderId() {
        return "ORD_" + System.currentTimeMillis() + 
               "_" + (int)(Math.random() * 10000);
    }
}

// Usage in your checkout API
@PostMapping("/checkout")
public ResponseEntity<?> checkout(@RequestBody CheckoutRequest request) {
    PaymentResponse response = checkoutService.initiateCheckout(request);
    
    if (response.getSuccess()) {
        // Redirect user to payment URL
        return ResponseEntity.ok(Map.of(
            "payment_url", response.getData().getPaymentUrl(),
            "transaction_id", response.getData().getTransactionId()
        ));
    } else {
        return ResponseEntity.badRequest().body(response);
    }
}
8. Testing Your Integration
// Unit Test Example
@SpringBootTest
class RabbitPayServiceTest {
    
    @Autowired
    private RabbitPayService rabbitPayService;
    
    @Test
    void testCreatePaymentOrder() {
        PaymentResponse response = rabbitPayService.createPaymentOrder(
            100.00,
            "TEST_ORDER_123",
            "Test Customer",
            "test@example.com",
            "+91 9876543210",
            "Test Product"
        );
        
        assertNotNull(response);
        assertTrue(response.getSuccess());
        assertNotNull(response.getData().getTransactionId());
        assertNotNull(response.getData().getPaymentUrl());
    }
    
    @Test
    void testWebhookSignatureVerification() {
        String payload = "{\"event\":\"payment.completed\"}";
        String signature = rabbitPayService.calculateHMAC(
            payload, 
            "sk_test_secret"
        );
        
        boolean isValid = rabbitPayService.verifyWebhookSignature(
            payload, 
            signature
        );
        
        assertTrue(isValid);
    }
}
Testing Tips:
  • Use test API credentials during development
  • Test webhook signatures with sample payloads
  • Implement idempotency for webhook handlers
  • Log all API requests and responses
  • Test error scenarios (network failures, invalid tokens, etc.)
Integration Checklist
  • ✅ Add Maven dependencies
  • ✅ Configure API credentials
  • ✅ Implement payment creation
  • ✅ Implement payment verification
  • ✅ Set up webhook endpoint
  • ✅ Verify webhook signatures
  • ✅ Handle all webhook events
  • ✅ Implement error handling
  • ✅ Add logging
  • ✅ Write unit tests
  • ✅ Test in production with real credentials

Test API

Use this interactive tool to test your API integration.
API Tester

Open API Test Page

The test page allows you to input your API credentials and test all endpoints with real API calls.