Welcome To ZHR PAY BD Docs Last updated: 2026-10-10

ZHR PAY BD is a secure payment automation gateway designed to help merchants accept payments from customers through their own websites and applications.

This documentation provides everything required to integrate the ZHR PAY BD API, create payment sessions, redirect customers to the payment page and securely verify completed transactions.

Simple API Authentication

GG Pay API uses a single authentication credential: API-KEY No additional authentication header is required.

API Introduction

ZHR PAY BD provides a simple REST API for merchants. Your server sends payment information to the API, receives a secure payment URL and redirects the customer to complete the payment.

After payment completion, the customer is redirected to the success URL supplied during payment creation. Your backend should then verify the transaction before marking the merchant order as paid.

API Operation

The API uses HTTPS and JSON requests. Your server should support cURL, Guzzle, Laravel HTTP Client or another HTTPS-compatible HTTP client.

Live Environment

Base URL: https://payment.zhrteam.xyz/

Create Payment

POST https://payment.zhrteam.xyz/api/payment/create

Verify Payment

POST https://payment.zhrteam.xyz/api/payment/verify

Payment Flow

1
Merchant creates a payment request.
2
GG Pay returns a payment_url .
3
Merchant redirects the customer to the returned payment URL.
4
Customer completes the payment.
5
Customer returns to the merchant's success_url .
6
Merchant verifies the transaction from the backend.
7
Only after successful verification should the merchant mark the order as paid.
Important

Never consider a browser redirect alone as proof of payment. Always verify the transaction server-to-server.

Parameter Details

The following parameters are used when creating a payment.

Field Name Description Required Example
cus_name Customer's full name. YES John Doe
cus_email Customer's email address. YES [email protected]
amount Total payment amount. YES 10 / 10.50 / 10.6
success_url URL where the customer is redirected after the payment flow. YES https://yourdomain.com/payment/success
cancel_url URL where the customer is redirected when the payment is cancelled. YES https://yourdomain.com/payment/cancel
meta_data Optional JSON data used for merchant-side information such as order ID, customer ID or reference values. OPTIONAL {"order_id":"1001"}

Verify Payment Parameters

Field Name Description Required Example
transaction_id Transaction ID associated with the payment. YES OVKPXW165414

Headers

Every API request should send JSON and authenticate using your API-KEY .

Header Name Value Purpose
Content-Type application/json Indicates that the request body contains JSON.
Accept application/json Requests a JSON response.
API-KEY YOUR_API_KEY Authenticates the API request.
API Authentication

GG Pay uses API-KEY as the API authentication header. Keep this key private and use it only from trusted server-side code.

Security Warning

Never place your real API key inside public JavaScript, browser-side requests, GitHub repositories, screenshots or public source code.

cURL & DNS Troubleshooting

Most servers can connect to the GG Pay API normally. However, some shared hosting servers may have a local DNS/NSS resolver problem. In that situation, the domain may work from your computer but fail when requested from your hosting server.

Recommended Testing Order
  1. Test normal cURL first.
  2. Check DNS resolution.
  3. If DNS is incorrect or unavailable, test using --resolve.
  4. If --resolve works, ask your hosting provider to fix server-side DNS/NSS.
  5. For PHP cURL, use CURLOPT_RESOLVE as a temporary workaround.

1. Test Normal cURL

SSH / Terminal
curl -I "https://payment.zhrteam.xyz/"

You can also test the API endpoint:

curl -i -X POST "https://payment.zhrteam.xyz/api/payment/create" \-H "Content-Type: application/json" \-H "Accept: application/json" \-H "API-KEY: YOUR_API_KEY" \-d '{ "cus_name": "John Doe", "cus_email": "[email protected]", "amount": "100", "success_url": "https://yourdomain.com/payment/success", "cancel_url": "https://yourdomain.com/payment/cancel", "meta_data": { "order_id": "ORD-1001" }}'

2. Check DNS Resolution

Run one or more of the following commands:

getent hosts autopay.ggtopup.shop
nslookup autopay.ggtopup.shop
dig autopay.ggtopup.shop

If these commands return the wrong address, no address, or an unexpected internal/server address, the hosting server may have a DNS resolver/NSS configuration issue.

3. Test With cURL --resolve

If normal cURL fails because the server resolves the hostname incorrectly, you can temporarily force cURL to connect to a specific IP while still sending the correct HTTPS hostname.

Temporary DNS Override
curl --resolve autopay.ggtopup.shop:443:172.67.187.37 \-I "https://payment.zhrteam.xyz/"

For the Create Payment API:

curl --resolve autopay.ggtopup.shop:443:172.67.187.37 \-X POST "https://payment.zhrteam.xyz/api/payment/create" \-H "Content-Type: application/json" \-H "Accept: application/json" \-H "API-KEY: YOUR_API_KEY" \-d '{ "cus_name": "John Doe", "cus_email": "[email protected]", "amount": "100", "success_url": "https://yourdomain.com/payment/success", "cancel_url": "https://yourdomain.com/payment/cancel", "meta_data": { "order_id": "ORD-1001" }}'
Important About --resolve

--resolve is a cURL testing/workaround feature. It does not permanently repair the hosting server's DNS configuration.

4. Why Does --resolve Work?

When cURL normally requests: autopay.ggtopup.shop the operating system first needs to resolve the hostname to an IP address.

If the hosting server's DNS resolver returns an incorrect address or fails to resolve the domain, the connection may fail.

With --resolve cURL is instructed to use the specified IP for that hostname and port.

Best Long-Term Solution

If --resolve works but normal cURL does not, contact your hosting provider and ask them to check the server's DNS/NSS resolver configuration. After the provider fixes DNS, remove the temporary override.

5. PHP cURL CURLOPT_RESOLVE

PHP applications can use the same temporary technique through libcurl's CURLOPT_RESOLVE option.

<?php$apiUrl = 'https://payment.zhrteam.xyz/api/payment/create';$payload = [ 'cus_name' => 'John Doe', 'cus_email' => '[email protected]', 'amount' => '100', 'success_url' => 'https://yourdomain.com/payment/success', 'cancel_url' => 'https://yourdomain.com/payment/cancel', 'meta_data' => [ 'order_id' => 'ORD-1001', ],];$ch = curl_init($apiUrl);curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json', 'API-KEY: YOUR_API_KEY', ], CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, CURLOPT_RESOLVE => [ 'autopay.ggtopup.shop:443:172.67.187.37', ], CURLOPT_CONNECTTIMEOUT => 15, CURLOPT_TIMEOUT => 60,]);$response = curl_exec($ch);if ($response === false) { throw new Exception( 'cURL Error: ' . curl_error($ch) );}$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);curl_close($ch);$data = json_decode($response, true);if (!is_array($data)) { throw new Exception( 'Invalid JSON response from GG Pay.' );}if ( $httpCode >= 200 && $httpCode < 300 && isset($data['status']) && (int) $data['status'] === 1 && !empty($data['payment_url'])) { header( 'Location: ' . $data['payment_url'] ); exit;}throw new Exception( $data['message'] ?? 'Unable to create payment.');
Temporary Workaround Only

Do not permanently hard-code a Cloudflare edge IP unless you fully control and understand the networking configuration. Cloudflare addresses and routing can change.

6. PHP Without CURLOPT_RESOLVE

If normal DNS works correctly on your server, you do not need CURLOPT_RESOLVE . Use normal PHP cURL:

curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json', 'API-KEY: YOUR_API_KEY', ], CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_CONNECTTIMEOUT => 15, CURLOPT_TIMEOUT => 60,]);

7. Common cURL Errors

Error Meaning Recommended Action
Could not resolve host Server cannot resolve the API hostname. Check DNS and test --resolve .
cURL error 6 Hostname could not be resolved. Check server DNS/NSS configuration.
Connection timed out Server could not establish the connection within the timeout. Test connectivity, firewall and DNS resolution.
SSL certificate problem TLS certificate validation failed. Keep SSL verification enabled and check the server CA bundle.
HTTP 401 / 403 Authentication or access was rejected. Check your API key and request headers.
HTTP 422 Request validation failed. Check required fields and their values.
HTTP 500 Server-side application error. Check response body and contact gateway support if necessary.

Integration

You can integrate ZHR PAY BD with PHP, Laravel, WordPress, WooCommerce, WHMCS, SMM panels and other platforms capable of sending HTTPS requests.

Create Payment

Send a POST request to the Create Payment endpoint.

POST https://payment.zhrteam.xyz/api/payment/create

Standard cURL Example

curl -X POST "https://payment.zhrteam.xyz/api/payment/create" \-H "Content-Type: application/json" \-H "Accept: application/json" \-H "API-KEY: YOUR_API_KEY" \-d '{ "cus_name": "John Doe", "cus_email": "[email protected]", "amount": "100", "success_url": "https://yourdomain.com/payment/success", "cancel_url": "https://yourdomain.com/payment/cancel", "meta_data": { "order_id": "ORD-1001" }}'

cURL With --resolve

Use this only if normal cURL cannot resolve the API hostname correctly on your server.

curl --resolve autopay.ggtopup.shop:443:172.67.187.37 \-X POST "https://payment.zhrteam.xyz/api/payment/create" \-H "Content-Type: application/json" \-H "Accept: application/json" \-H "API-KEY: YOUR_API_KEY" \-d '{ "cus_name": "John Doe", "cus_email": "[email protected]", "amount": "100", "success_url": "https://yourdomain.com/payment/success", "cancel_url": "https://yourdomain.com/payment/cancel", "meta_data": { "order_id": "ORD-1001" }}'

Successful Response

{ "status": 1, "message": "Payment Link", "payment_url": "https://payment.zhrteam.xyz/api/execute/XXXXXXXX"}
Next Step

Redirect the customer to the returned payment_url .

Example PHP Redirect

$data = json_decode($response, true);if ( isset($data['status']) && (int) $data['status'] === 1 && !empty($data['payment_url'])) { header('Location: ' . $data['payment_url']); exit;}

Verify Payment

After the customer returns to your success URL, retrieve the transaction ID and verify the transaction from your backend.

POST https://payment.zhrteam.xyz/api/payment/verify

cURL Example

curl -X POST "https://payment.zhrteam.xyz/api/payment/verify" \-H "Content-Type: application/json" \-H "Accept: application/json" \-H "API-KEY: YOUR_API_KEY" \-d '{ "transaction_id": "TRANSACTION_ID"}'

cURL With --resolve

curl --resolve autopay.ggtopup.shop:443:172.67.187.37 \-X POST "https://payment.zhrteam.xyz/api/payment/verify" \-H "Content-Type: application/json" \-H "Accept: application/json" \-H "API-KEY: YOUR_API_KEY" \-d '{ "transaction_id": "TRANSACTION_ID"}'

Possible Transaction Status

Status Meaning Recommended Action
COMPLETED Payment has been completed. Verify transaction and amount, then mark the order as paid.
PENDING Payment is not completed yet. Keep the order pending and verify again later.
ERROR Payment verification failed. Do not mark the order as paid.

Example Response

{ "status": "COMPLETED", "cus_name": "John Doe", "cus_email": "[email protected]", "amount": "100", "transaction_id": "OVKPXW165414", "metadata": { "order_id": "ORD-1001" }, "payment_method": "..."}
Never Trust Only the Redirect

A customer reaching your success_url does not by itself prove that the payment was completed. Always call the Verify Payment API from your server.

Laravel Integration

The following example uses Laravel's built-in HTTP Client.

Environment Configuration

GGPAY_API_KEY=your_api_key_here
Keep the API key private

Do not put the API key in frontend JavaScript, React browser code or public HTML.

Laravel Create Payment

use Illuminate\Support\Facades\Http;$apiUrl = 'https://payment.zhrteam.xyz/';$response = Http::withHeaders([ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'API-KEY' => env('GGPAY_API_KEY'),])->timeout(60)->post($apiUrl . 'api/payment/create', [ 'cus_name' => $customer->name, 'cus_email' => $customer->email, 'amount' => $order->amount, 'success_url' => route('payment.success'), 'cancel_url' => route('payment.cancel'), 'meta_data' => [ 'order_id' => $order->id, ],]);$data = $response->json();if ( $response->successful() && isset($data['status']) && (int) $data['status'] === 1 && !empty($data['payment_url'])) { return redirect()->away( $data['payment_url'] );}return back()->with( 'error', $data['message'] ?? 'Unable to create payment.');

Laravel Verify Payment

use Illuminate\Support\Facades\Http;$transactionId = request('transactionId');$response = Http::withHeaders([ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'API-KEY' => env('GGPAY_API_KEY'),])->timeout(60)->post( 'https://payment.zhrteam.xyz/api/payment/verify', [ 'transaction_id' => $transactionId, ]);$data = $response->json();if (($data['status'] ?? '') === 'COMPLETED') { /* |-------------------------------------------------------------------------- | IMPORTANT |-------------------------------------------------------------------------- | | Verify: | | 1. Transaction ID | 2. Expected amount | 3. Merchant order ID | 4. Current order status | | Then mark the order as paid. | */ // $order->update([ // 'status' => 'paid', // ]);}

Laravel Shared Hosting DNS Workaround

If the Laravel HTTP Client fails because the hosting server cannot correctly resolve the API hostname, you can temporarily use a custom Guzzle handler or native cURL configuration with a DNS resolve override.

For a simple Laravel project, the easiest approach is to fix the server DNS first. If that is not immediately possible, use native cURL with CURLOPT_RESOLVE as shown in the PHP cURL section.

Recommended Laravel Approach

Use normal Laravel HTTP Client when server DNS works. Use CURLOPT_RESOLVE only as a temporary workaround when your hosting environment has a DNS resolution problem.

Native PHP cURL

If you are using plain PHP without Laravel or another framework, you can integrate GG Pay directly using PHP cURL.

Standard PHP cURL

<?php$apiUrl = 'https://payment.zhrteam.xyz/api/payment/create';$payload = [ 'cus_name' => 'John Doe', 'cus_email' => '[email protected]', 'amount' => '100', 'success_url' => 'https://yourdomain.com/payment/success', 'cancel_url' => 'https://yourdomain.com/payment/cancel', 'meta_data' => [ 'order_id' => 'ORD-1001', ],];$ch = curl_init($apiUrl);curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json', 'API-KEY: YOUR_API_KEY', ], CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_CONNECTTIMEOUT => 15, CURLOPT_TIMEOUT => 60,]);$response = curl_exec($ch);if ($response === false) { $error = curl_error($ch); curl_close($ch); die('cURL Error: ' . $error);}$httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE);curl_close($ch);$data = json_decode( $response, true);if (!is_array($data)) { die('Invalid JSON response.');}if ( $httpCode >= 200 && $httpCode < 300 && isset($data['status']) && (int) $data['status'] === 1 && !empty($data['payment_url'])) { header( 'Location: ' . $data['payment_url'] ); exit;}die( $data['message'] ?? 'Payment creation failed.');

PHP cURL With CURLOPT_RESOLVE

Use this version only when normal PHP cURL cannot resolve the API hostname on your hosting server.

<?php$apiUrl = 'https://payment.zhrteam.xyz/api/payment/create';$payload = [ 'cus_name' => 'John Doe', 'cus_email' => '[email protected]', 'amount' => '100', 'success_url' => 'https://yourdomain.com/payment/success', 'cancel_url' => 'https://yourdomain.com/payment/cancel', 'meta_data' => [ 'order_id' => 'ORD-1001', ],];$ch = curl_init($apiUrl);curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json', 'API-KEY: YOUR_API_KEY', ], CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, /* |-------------------------------------------------------------------------- | Temporary DNS workaround |-------------------------------------------------------------------------- */ CURLOPT_RESOLVE => [ 'autopay.ggtopup.shop:443:172.67.187.37', ], CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, CURLOPT_CONNECTTIMEOUT => 15, CURLOPT_TIMEOUT => 60,]);$response = curl_exec($ch);if ($response === false) { $error = curl_error($ch); curl_close($ch); die('cURL Error: ' . $error);}$httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE);curl_close($ch);$data = json_decode( $response, true);if (!is_array($data)) { die('Invalid JSON response.');}if ( $httpCode >= 200 && $httpCode < 300 && isset($data['status']) && (int) $data['status'] === 1 && !empty($data['payment_url'])) { header( 'Location: ' . $data['payment_url'] ); exit;}die( $data['message'] ?? 'Payment creation failed.');

WordPress / WooCommerce

Integrate ZHR PAY BD with WordPress or WooCommerce using the provided payment module.

The integration should create the payment from server-side PHP, redirect the customer to the returned payment URL and verify the transaction before completing the order.

WooCommerce Security

Do not place the API key inside frontend JavaScript. The API request should be made from the WordPress server.

Modules

Ready-to-use modules and integrations for supported platforms.

WordPress Plugin

Integrate ZHR PAY BD into your WordPress website or WooCommerce store.

WHMCS Module

Integrate the payment gateway into your WHMCS installation and allow customers to pay their invoices through ZHR PAY BD.

SMM Panel Module

Integrate ZHR PAY BD with your SMM panel and allow customers to add balance using the payment gateway.

Sketchware SWB

Download the Sketchware project for Android application integration.

Android Security

Do not embed a permanent merchant API key directly into a publicly distributed Android application. Mobile applications can be reverse engineered.

Mobile App

Download the ZHR PAY BD Android application.

Setup Video

Add your setup/tutorial video URL here when it becomes available.

Production Checklist

Check Recommendation
API Authentication Use only your API-KEY from server-side code.
HTTPS Always use HTTPS for API requests.
API Key Storage Store the API key in environment variables or secure server-side configuration.
Payment Verification Verify the transaction from your backend before fulfilling the order.
Amount Verification Compare the verified payment amount with your original order amount.
Transaction ID Verify that the returned transaction belongs to the correct merchant order.
cURL Resolve Use --resolve or CURLOPT_RESOLVE only as a temporary DNS workaround.
DNS If normal DNS fails but --resolve works, ask the hosting provider to fix the server DNS/NSS configuration.
Recommended Production Flow

Create Payment → Redirect Customer → Customer Pays → Customer Returns → Backend Verify Payment → Verify Amount → Verify Transaction → Mark Order Paid.

Never Do This

Do not mark an order as paid only because the customer reached your success URL. Do not expose your API key in frontend code. Do not disable SSL certificate verification in production. Do not permanently depend on a hard-coded Cloudflare IP.