MH PAY Documentation

Version: 1.00

Updated: 1st September, 2023

General Overview

Connect effortlessly through our system. Link apps and data sources, automate tasks, and enjoy smooth workflows with ease. Receive payments directly into your personal account using MH PAY payment automation software. No need to handle payments manually anymore.

Installation Process

Installation Guide

Follow these steps carefully to install MH PAY Script on your server

Step 1: System Requirements Check

Before proceeding with the installation, ensure your server meets all the following requirements:

System Requirements Check

PHP Requirements:

File Permissions:

Step 2: License Verification

Enter your license key to verify your purchase and continue with the installation:

License Verification

License Key Format: XXXX-XXXX-XXXX-XXXX

Your product license key will be provided after purchase

Step 3: Database Configuration

Provide your database connection details. MySQL is recommended for most installations:

Database Configuration

Required Database Information:

Step 4: Administrator Account Setup

Create your administrator account to manage the application:

Administrator Account Setup

⚠️ Important Security Notice

Remember these credentials. You'll need them to access the admin panel.

Step 5: Installation Complete

Your application has been successfully installed and is ready to use!

Installation Complete

Installation Summary:

Admin URL https://payment.mhpay.cc/admin/
Database Tables Created 24
Administrator Username admin
Administrator Email admin@mhpay.cc

🔒 Security Warning

Important: For security reasons, please delete the /install directory from your server after installation.

Next Steps - Setup Your Credentials

After installation, configure the following in your admin panel:

  • Your API Key
  • Your Secret Key
  • Payment Methods
  • Domain Whitelist

Setup Your Mobile App

Checkpoint Tips

Download and configure the mobile app to receive payment notifications

📱 Download Mobile App

Complete the Following Process

  1. Install the app with necessary permissions from Download Link
  2. Register a device from admin panel https://pay.yourdomain.com/admin/sms-data
  3. Go to Sms Data
  4. Get back to mobile app and enter your Webhook URL
  5. Give SMS and Notification Permission to the App

Payment Process

MH PAY provides powerful RESTful APIs that let you integrate seamless payment solutions into your website, mobile app, or platform. All API requests use HTTPS and require authentication using your API credentials.

API Endpoints

Base URLs

Production: https://mhpay.cc/api
Sandbox: https://sandbox.mhpay.cc/api

Authentication

All API requests require authentication using your API Key and Secret Key. Include these credentials in your request headers.

Authentication Headers

Content-Type: application/json
X-API-Key: YOUR_API_KEY
Authorization: Bearer YOUR_SECRET_KEY

🔐 Security Best Practices

Keep your API keys secure and never expose them in client-side code or public repositories. Your Secret Key should only be used in direct server-to-server calls.

Request Parameters

Parameter Type Description Required
api_key String Your API Key from panel dashboard ✓ Yes
amount Number Payment amount (minimum: 10 BDT) ✓ Yes
currency String Currency code (default: BDT) No
order_id String Unique order identifier from your system ✓ Yes
customer_name String Customer's full name No
customer_email String Customer's email address No
customer_phone String Customer's phone number No
callback_url String Webhook URL for payment notifications ✓ Yes
success_url String URL to redirect after successful payment No
cancel_url String URL to redirect if payment is cancelled No
metadata Object Additional custom data (JSON format) No

Response Parameters

Parameter Type Description
status String Response status: success, failed, pending
message String Human-readable response message
transaction_id String Unique transaction identifier from MH PAY
order_id String Your original order identifier
payment_url String URL to redirect customer for payment
amount Number Payment amount
currency String Currency code
payment_method String Payment method used (bKash, Nagad, Rocket, etc.)
payment_status String Payment status: pending, completed, failed, cancelled
created_at DateTime Transaction creation timestamp (ISO 8601)
updated_at DateTime Transaction last update timestamp (ISO 8601)

Payment Status

Status Description
pending Payment request created, waiting for customer action
processing Payment is being processed by the gateway
completed Payment successfully completed
failed Payment failed due to insufficient funds or technical error
cancelled Payment cancelled by customer or expired
refunded Payment has been refunded

Webhook Notifications

MH PAY sends real-time webhook notifications to your callback URL when payment status changes. Your webhook endpoint should respond with HTTP 200 status to acknowledge receipt.

Webhook Payload Example

{
    "event": "payment.completed",
    "transaction_id": "TXN123456789",
    "order_id": "ORDER_1693526400",
    "amount": 1000,
    "currency": "BDT",
    "payment_method": "bKash",
    "payment_status": "completed",
    "customer_phone": "01712345678",
    "payment_date": "2023-09-01T10:30:45+06:00",
    "metadata": {
        "invoice_id": "INV-001"
    }
}

Error Handling

The API uses standard HTTP response codes to indicate success or failure. Error responses include detailed information to help you troubleshoot issues.

HTTP Code Error Type Description
200 Success Request completed successfully
400 Bad Request Invalid parameters or missing required fields
401 Unauthorized Invalid API credentials
403 Forbidden API key doesn't have permission for this action
404 Not Found Requested resource doesn't exist
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Something went wrong on our end

Error Response Example

{
    "status": "failed",
    "error": {
        "code": "INVALID_AMOUNT",
        "message": "Amount must be at least 10 BDT",
        "field": "amount"
    }
}

Create Payment Request

To initiate a payment, send a POST request to the create payment endpoint with the required parameters. The API will return a payment URL that you can redirect your customer to complete the payment.

Endpoint

POST https://mhpay.cc/api/payment/create

Code Examples

cURL

curl -X POST https://mhpay.cc/api/payment/create \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -d '{
    "amount": 1000,
    "currency": "BDT",
    "order_id": "ORDER_1693526400",
    "customer_name": "John Doe",
    "customer_email": "[email protected]",
    "customer_phone": "01712345678",
    "callback_url": "https://yourdomain.com/payment/callback",
    "success_url": "https://yourdomain.com/payment/success",
    "cancel_url": "https://yourdomain.com/payment/cancel",
    "metadata": {
        "invoice_id": "INV-001",
        "user_id": "12345"
    }
}'

PHP

<?php
$api_key = "YOUR_API_KEY";
$secret_key = "YOUR_SECRET_KEY";

$data = [
    'amount' => 1000,
    'currency' => 'BDT',
    'order_id' => 'ORDER_' . time(),
    'customer_name' => 'John Doe',
    'customer_email' => '[email protected]',
    'customer_phone' => '01712345678',
    'callback_url' => 'https://yourdomain.com/payment/callback',
    'success_url' => 'https://yourdomain.com/payment/success',
    'cancel_url' => 'https://yourdomain.com/payment/cancel',
    'metadata' => [
        'invoice_id' => 'INV-001',
        'user_id' => '12345'
    ]
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://mhpay.cc/api/payment/create");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-API-Key: ' . $api_key,
    'Authorization: Bearer ' . $secret_key
]);

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

if ($httpCode == 200) {
    $result = json_decode($response, true);
    
    if ($result['status'] === 'success') {
        // Redirect to payment URL
        header('Location: ' . $result['payment_url']);
        exit;
    } else {
        // Handle error
        echo "Error: " . $result['message'];
    }
} else {
    echo "HTTP Error: " . $httpCode;
}
?>

Laravel

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class PaymentController extends Controller
{
    private $apiKey;
    private $secretKey;
    private $apiUrl;

    public function __construct()
    {
        $this->apiKey = config('mhpay.api_key');
        $this->secretKey = config('mhpay.secret_key');
        $this->apiUrl = config('mhpay.api_url', 'https://mhpay.cc/api');
    }

    /**
     * Create a new payment request
     */
    public function createPayment(Request $request)
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:10',
            'customer_name' => 'nullable|string',
            'customer_email' => 'nullable|email',
            'customer_phone' => 'nullable|string',
        ]);

        $orderId = 'ORDER_' . time() . '_' . rand(1000, 9999);

        try {
            $response = Http::withHeaders([
                'Content-Type' => 'application/json',
                'X-API-Key' => $this->apiKey,
                'Authorization' => 'Bearer ' . $this->secretKey,
            ])->post($this->apiUrl . '/payment/create', [
                'amount' => $validated['amount'],
                'currency' => 'BDT',
                'order_id' => $orderId,
                'customer_name' => $validated['customer_name'] ?? null,
                'customer_email' => $validated['customer_email'] ?? null,
                'customer_phone' => $validated['customer_phone'] ?? null,
                'callback_url' => route('payment.callback'),
                'success_url' => route('payment.success'),
                'cancel_url' => route('payment.cancel'),
                'metadata' => [
                    'user_id' => auth()->id(),
                    'ip_address' => $request->ip(),
                ],
            ]);

            if ($response->successful()) {
                $data = $response->json();
                
                if ($data['status'] === 'success') {
                    // Store transaction in database
                    \DB::table('transactions')->insert([
                        'order_id' => $orderId,
                        'transaction_id' => $data['transaction_id'],
                        'amount' => $data['amount'],
                        'status' => 'pending',
                        'created_at' => now(),
                    ]);

                    return redirect($data['payment_url']);
                }
            }

            return back()->withErrors(['error' => 'Payment creation failed']);

        } catch (\Exception $e) {
            Log::error('MH PAY Error: ' . $e->getMessage());
            return back()->withErrors(['error' => 'An error occurred']);
        }
    }

    /**
     * Handle payment callback
     */
    public function callback(Request $request)
    {
        // Verify webhook signature here
        $payload = $request->all();
        
        Log::info('MH PAY Callback:', $payload);

        $transaction = \DB::table('transactions')
            ->where('transaction_id', $payload['transaction_id'])
            ->first();

        if ($transaction) {
            \DB::table('transactions')
                ->where('transaction_id', $payload['transaction_id'])
                ->update([
                    'status' => $payload['payment_status'],
                    'payment_method' => $payload['payment_method'] ?? null,
                    'updated_at' => now(),
                ]);

            // Process order based on payment status
            if ($payload['payment_status'] === 'completed') {
                // Complete the order
                $this->completeOrder($payload['order_id']);
            }
        }

        return response()->json(['status' => 'success']);
    }

    /**
     * Handle successful payment redirect
     */
    public function success(Request $request)
    {
        $transactionId = $request->query('transaction_id');
        
        return view('payment.success', [
            'transaction_id' => $transactionId
        ]);
    }

    /**
     * Handle cancelled payment
     */
    public function cancel(Request $request)
    {
        return view('payment.cancel');
    }

    /**
     * Complete order after successful payment
     */
    private function completeOrder($orderId)
    {
        // Your order completion logic here
        Log::info('Order completed: ' . $orderId);
    }
}
?>

Node.js

const axios = require('axios');

const apiKey = 'YOUR_API_KEY';
const secretKey = 'YOUR_SECRET_KEY';
const apiUrl = 'https://mhpay.cc/api';

async function createPayment(paymentData) {
    try {
        const response = await axios.post(`${apiUrl}/payment/create`, {
            amount: paymentData.amount,
            currency: 'BDT',
            order_id: `ORDER_${Date.now()}`,
            customer_name: paymentData.customerName,
            customer_email: paymentData.customerEmail,
            customer_phone: paymentData.customerPhone,
            callback_url: 'https://yourdomain.com/payment/callback',
            success_url: 'https://yourdomain.com/payment/success',
            cancel_url: 'https://yourdomain.com/payment/cancel',
            metadata: paymentData.metadata || {}
        }, {
            headers: {
                'Content-Type': 'application/json',
                'X-API-Key': apiKey,
                'Authorization': `Bearer ${secretKey}`
            }
        });

        if (response.data.status === 'success') {
            console.log('Payment URL:', response.data.payment_url);
            return response.data;
        } else {
            throw new Error(response.data.message);
        }
    } catch (error) {
        console.error('Payment Error:', error.message);
        throw error;
    }
}

// Express.js webhook handler
app.post('/payment/callback', async (req, res) => {
    const payload = req.body;
    
    console.log('Payment Webhook:', payload);

    // Update database with payment status
    await updateTransaction(payload.transaction_id, {
        status: payload.payment_status,
        payment_method: payload.payment_method,
        payment_date: payload.payment_date
    });

    if (payload.payment_status === 'completed') {
        // Complete the order
        await completeOrder(payload.order_id);
    }

    res.json({ status: 'success' });
});

Python

import requests
import json
import time

API_KEY = 'YOUR_API_KEY'
SECRET_KEY = 'YOUR_SECRET_KEY'
API_URL = 'https://mhpay.cc/api'

def create_payment(amount, customer_data):
    """Create a new payment request"""
    
    headers = {
        'Content-Type': 'application/json',
        'X-API-Key': API_KEY,
        'Authorization': f'Bearer {SECRET_KEY}'
    }
    
    payload = {
        'amount': amount,
        'currency': 'BDT',
        'order_id': f'ORDER_{int(time.time())}',
        'customer_name': customer_data.get('name'),
        'customer_email': customer_data.get('email'),
        'customer_phone': customer_data.get('phone'),
        'callback_url': 'https://yourdomain.com/payment/callback',
        'success_url': 'https://yourdomain.com/payment/success',
        'cancel_url': 'https://yourdomain.com/payment/cancel',
        'metadata': customer_data.get('metadata', {})
    }
    
    try:
        response = requests.post(
            f'{API_URL}/payment/create',
            headers=headers,
            json=payload
        )
        
        response.raise_for_status()
        data = response.json()
        
        if data['status'] == 'success':
            print(f"Payment URL: {data['payment_url']}")
            return data
        else:
            raise Exception(data['message'])
            
    except requests.exceptions.RequestException as e:
        print(f'Payment Error: {e}')
        raise

# Flask webhook handler
@app.route('/payment/callback', methods=['POST'])
def payment_callback():
    payload = request.get_json()
    
    print(f'Payment Webhook: {payload}')
    
    # Update database with payment status
    update_transaction(
        payload['transaction_id'],
        status=payload['payment_status'],
        payment_method=payload.get('payment_method'),
        payment_date=payload.get('payment_date')
    )
    
    if payload['payment_status'] == 'completed':
        # Complete the order
        complete_order(payload['order_id'])
    
    return jsonify({'status': 'success'})

Success Response

{
    "status": "success",
    "message": "Payment request created successfully",
    "transaction_id": "TXN123456789",
    "order_id": "ORDER_1693526400",
    "amount": 1000,
    "currency": "BDT",
    "payment_url": "https://mhpay.cc/pay/TXN123456789",
    "payment_status": "pending",
    "created_at": "2023-09-01T10:30:45+06:00"
}

Error Response

{
    "status": "failed",
    "message": "Invalid API credentials",
    "error": {
        "code": "UNAUTHORIZED",
        "field": "api_key"
    }
}

Verify Payment

Use the verify payment endpoint to check the current status of a transaction. This is useful for confirming payment completion before delivering goods or services.

Endpoint

POST https://mhpay.cc/api/payment/verify

Request Parameters

Parameter Type Description Required
transaction_id String Transaction ID from MH PAY ✓ Yes
order_id String Your original order ID (alternative to transaction_id) No

Code Examples

cURL

curl -X POST https://mhpay.cc/api/payment/verify \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Authorization: Bearer YOUR_SECRET_KEY" \
  -d '{
    "transaction_id": "TXN123456789"
}'

PHP

<?php
function verifyPayment($transactionId) {
    $api_key = "YOUR_API_KEY";
    $secret_key = "YOUR_SECRET_KEY";

    $data = [
        'transaction_id' => $transactionId
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://mhpay.cc/api/payment/verify");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'X-API-Key: ' . $api_key,
        'Authorization: Bearer ' . $secret_key
    ]);

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

    if ($httpCode == 200) {
        $result = json_decode($response, true);
        return $result;
    }
    
    return null;
}

// Usage
$transactionId = $_GET['transaction_id'];
$payment = verifyPayment($transactionId);

if ($payment && $payment['status'] === 'success' && $payment['payment_status'] === 'completed') {
    // Payment is verified and completed
    echo "Payment successful!";
    echo "Transaction ID: " . $payment['transaction_id'];
    echo "Amount: " . $payment['amount'] . " " . $payment['currency'];
    echo "Method: " . $payment['payment_method'];
} else {
    echo "Payment verification failed or incomplete";
}
?>

Laravel

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class MHPayService
{
    private $apiKey;
    private $secretKey;
    private $apiUrl;

    public function __construct()
    {
        $this->apiKey = config('mhpay.api_key');
        $this->secretKey = config('mhpay.secret_key');
        $this->apiUrl = config('mhpay.api_url', 'https://mhpay.cc/api');
    }

    /**
     * Verify payment status
     */
    public function verifyPayment($transactionId)
    {
        try {
            $response = Http::withHeaders([
                'Content-Type' => 'application/json',
                'X-API-Key' => $this->apiKey,
                'Authorization' => 'Bearer ' . $this->secretKey,
            ])->post($this->apiUrl . '/payment/verify', [
                'transaction_id' => $transactionId,
            ]);

            if ($response->successful()) {
                $data = $response->json();
                
                if ($data['status'] === 'success') {
                    return [
                        'verified' => true,
                        'payment_status' => $data['payment_status'],
                        'amount' => $data['amount'],
                        'currency' => $data['currency'],
                        'payment_method' => $data['payment_method'],
                        'payment_date' => $data['payment_date'],
                        'data' => $data
                    ];
                }
            }

            return ['verified' => false, 'message' => 'Verification failed'];

        } catch (\Exception $e) {
            Log::error('MH PAY Verification Error: ' . $e->getMessage());
            return ['verified' => false, 'message' => 'An error occurred'];
        }
    }

    /**
     * Check if payment is completed
     */
    public function isPaymentCompleted($transactionId)
    {
        $result = $this->verifyPayment($transactionId);
        return $result['verified'] && $result['payment_status'] === 'completed';
    }
}

// Controller usage
public function verifyPayment($transactionId)
{
    $mhpay = new MHPayService();
    $result = $mhpay->verifyPayment($transactionId);

    if ($result['verified'] && $result['payment_status'] === 'completed') {
        // Payment completed successfully
        return view('payment.success', ['data' => $result]);
    }

    return view('payment.pending');
}
?>

Node.js

const axios = require('axios');

async function verifyPayment(transactionId) {
    const apiKey = 'YOUR_API_KEY';
    const secretKey = 'YOUR_SECRET_KEY';
    const apiUrl = 'https://mhpay.cc/api';

    try {
        const response = await axios.post(`${apiUrl}/payment/verify`, {
            transaction_id: transactionId
        }, {
            headers: {
                'Content-Type': 'application/json',
                'X-API-Key': apiKey,
                'Authorization': `Bearer ${secretKey}`
            }
        });

        if (response.data.status === 'success') {
            return {
                verified: true,
                payment_status: response.data.payment_status,
                amount: response.data.amount,
                currency: response.data.currency,
                payment_method: response.data.payment_method,
                data: response.data
            };
        }

        return { verified: false };

    } catch (error) {
        console.error('Verification Error:', error.message);
        return { verified: false, error: error.message };
    }
}

// Express.js route
app.get('/payment/verify/:transactionId', async (req, res) => {
    const { transactionId } = req.params;
    const result = await verifyPayment(transactionId);

    if (result.verified && result.payment_status === 'completed') {
        res.render('payment-success', { payment: result });
    } else {
        res.render('payment-pending');
    }
});

Python

import requests

def verify_payment(transaction_id):
    """Verify payment status"""
    
    api_key = 'YOUR_API_KEY'
    secret_key = 'YOUR_SECRET_KEY'
    api_url = 'https://mhpay.cc/api'
    
    headers = {
        'Content-Type': 'application/json',
        'X-API-Key': api_key,
        'Authorization': f'Bearer {secret_key}'
    }
    
    payload = {
        'transaction_id': transaction_id
    }
    
    try:
        response = requests.post(
            f'{api_url}/payment/verify',
            headers=headers,
            json=payload
        )
        
        response.raise_for_status()
        data = response.json()
        
        if data['status'] == 'success':
            return {
                'verified': True,
                'payment_status': data['payment_status'],
                'amount': data['amount'],
                'currency': data['currency'],
                'payment_method': data.get('payment_method'),
                'data': data
            }
        
        return {'verified': False}
        
    except requests.exceptions.RequestException as e:
        print(f'Verification Error: {e}')
        return {'verified': False, 'error': str(e)}

# Django view
def payment_verify(request, transaction_id):
    result = verify_payment(transaction_id)
    
    if result['verified'] and result['payment_status'] == 'completed':
        return render(request, 'payment_success.html', {
            'payment': result
        })
    
    return render(request, 'payment_pending.html')

Success Response

{
    "status": "success",
    "message": "Payment verified successfully",
    "transaction_id": "TXN123456789",
    "order_id": "ORDER_1693526400",
    "amount": 1000,
    "currency": "BDT",
    "payment_status": "completed",
    "payment_method": "bKash",
    "customer_phone": "01712345678",
    "payment_date": "2023-09-01T10:30:45+06:00",
    "created_at": "2023-09-01T10:25:30+06:00",
    "updated_at": "2023-09-01T10:30:45+06:00",
    "metadata": {
        "invoice_id": "INV-001",
        "user_id": "12345"
    }
}

Best Practices

💡 Verification Tips

  • Always verify payments on your server before delivering goods/services
  • Don't rely solely on redirect URLs for payment confirmation
  • Use webhook callbacks for real-time payment updates
  • Implement retry logic for failed verification attempts
  • Store transaction IDs in your database for reference
  • Handle all payment statuses appropriately (pending, completed, failed, etc.)

All Modules

MH PAY supports integration with various platforms through dedicated modules. Download and install the appropriate module for your platform:

🛒

WHMCS

Version 1.0

Complete payment gateway module for WHMCS. Accept payments directly in your billing system with automatic order processing.

Download Module
📱

SMM PANEL

Version 1.0

Integrate MH PAY with your SMM Panel. Perfect for social media marketing platforms requiring automated payments.

Comming Soon
📝

WORDPRESS

Version 2.0

WordPress plugin for WooCommerce and Easy Digital Downloads. Accept payments seamlessly on your WordPress site.

Comming Soon

📖 Installation Instructions

Each module comes with detailed installation and configuration instructions. Please refer to the README file included in the module package.

Need a Custom Module?

If you need a module for a platform not listed here, please contact our support team. We can develop custom integrations for your specific requirements.

Contact Support →