Skip to main content

Core Concept

At a high level, integrating payments into your system involves a 3-step process:

Authentication

Before integration, it’s essential to understand how Hitpay APIs are authenticated. Hitpay utilizes API keys to grant access to the API. You can locate this key in your dashboard under “API keys.” Hitpay requires the API key to be included in all API requests to the server. This key should be placed in a header that follows the format shown below: X-BUSINESS-API-KEY: meowmeowmeow
$request->setHeaders(array(
  'X-BUSINESS-API-KEY' => 'meowmeowmeow',
  'Content-Type' => 'application/x-www-form-urlencoded',
  'X-Requested-With' => 'XMLHttpRequest'
));

API keys should be kept confidential and only stored on your servers. Do not store it on your mobile or web client

Step 1: Create Payment Request

This is the first step of the payment flow, once you have all the details from the user and are ready to collect payments, use this API to create a payment request. Since this is a server-to-server communication, if you have a mobile or Web client that communicates with your REST API, you must have a new endpoint E.g. /create-order, or reuse an existing endpoint. This endpoint will be responsible for making the payment request API call to hitpay.

Endpoint

POST https://api.sandbox.hit-pay.com/v1/payment-requests

Request Parameters

Mandatory fields are amount and currency. Remember to include header Content-Type: application/x-www-form-urlencoded
ParameterDescriptionExample
amountAmount related to the payment2500.00
payment_methods[]Choice of payment methods you want to offer the customerpaynow_online, card, wechat, alipay, grabpay, fave_duit, shopback, atome
(Local Payment Methods)
(Cross-border Payment Methods)
currencyCurrency related to the paymentSGD
emailBuyer’s emailfoo@example.com
purposePurpose of the Payment requestFIFA 16
nameBuyer’s nameJohn Doe
reference_numberArbitrary reference number that you can map to your internal reference number. This value cannot be edited by the customerXXXX123
redirect_urlURL where we redirect the user after a payment. Query arguments reference (payment request id) and status are sent alonghttps://example.com/callback
allow_repeated_paymentsIf set to true, multiple payments can be paid on a payment request link. Default value is falsefalse
expiry_dateTime after which the payment link will be expired (time in SGT). Applicable for repeated payments. Default is Null2021-02-02 01:01:01
$client = new http\Client;
$request = new http\Client\Request;
$request->setRequestUrl('https://api.sandbox.hit-pay.com/v1/payment-requests');
$request->setRequestMethod('POST');
$body = new http\Message\Body;
$body->append(new http\QueryString(array(
  'email' => 'tom@test.com',
  'redirect_url' => 'https://test.com/success',
  'reference_number' => 'REF123',
  'currency' => 'SGD',
  'amount' => '599')));$request->setBody($body);
$request->setOptions(array());
$request->setHeaders(array(
  'X-BUSINESS-API-KEY' => 'meowmeowmeow',
  'Content-Type' => 'application/x-www-form-urlencoded',
  'X-Requested-With' => 'XMLHttpRequest'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();

Response

{
    "id": "90f28b43-2cff-4f86-a29e-15697424b3e7",
    "name": null,
    "email": "tom@test.com",
    "phone": null,
    "amount": "599.00",
    "currency": "SGD",
    "status": "pending",
    "purpose": null,
    "reference_number": "REF123",
    "payment_methods": [
        "paynow_online",
        "card",
        "wechat",
        "alipay"
    ],
    "url": "https://securecheckout.sandbox.hit-pay.com/payment-request/@amazone-prime-pte-ltd/90f28b43-2cff-4f86-a29e-15697424b3e7/checkout",
    "redirect_url": "https://test.com/success",
    "send_sms": true,
    "send_email": true,
    "sms_status": "pending",
    "email_status": "pending",
    "allow_repeated_payments": false,
    "expiry_date": null,
    "created_at": "2020-07-03T02:18:49",
    "updated_at": "2020-07-03T02:18:49"
}

Step 2: Presenting the Checkout UI

After the payment request is completed, your server must return the payment_request_id and URL values to the client. There are 2 ways to present the checkout UI: “Redirect to HitPay checkout” or “Present Drop-In UI.”
Navigate your user to the URL, and HitPay will take care of the rest of the flow. Once the payment is completed, the user will be navigated back to the “redirect_url” that was configured during the payment request step, along with the status.PayNow Checkout Page

Step 3: Handle Successful Payment

Once the payment is completed, the user will be redirected to the redirect_url defined in step 1. While you can use this redirect to show an “Order Success” screen to your users, you should not rely on it alone to mark orders as paid. The redirect_url can be triggered by anyone, so always use webhooks to securely confirm payment before fulfilling orders.

What is a Webhook?

Webhook is a POST request sent from HitPay’s server to your server about the payment confirmation. If you are using HitPay APIs to integrate into your e-commerce checkout, you must mark your order as paid ONLY after the webhook is received and validated.

Register Your Webhook

To receive payment notifications, you need to register a webhook URL from your HitPay Dashboard:
  1. Navigate to Developers > Webhook Endpoints in your dashboard
  2. Click on New Webhook
  3. Enter a name and your webhook URL
  4. Select the payment_request.completed event
  5. Save your webhook configuration
Webhook Registration

Webhook Payload

When a payment is completed, HitPay sends a JSON payload to your registered webhook URL with the following headers:
HTTP HeaderDescription
Hitpay-SignatureHMAC-SHA256 signature of the JSON payload, using your salt value
Hitpay-Event-Typecompleted
Hitpay-Event-Objectpayment_request
User-AgentHitPay v2.0

Sample Webhook Payload

{
  "id": "9e9be41b-2866-4307-8621-e35c633c431f",
  "name": "John Doe",
  "email": "john@example.com",
  "phone": "+6512345678",
  "amount": "100.00",
  "currency": "SGD",
  "status": "completed",
  "purpose": "Order #12345",
  "reference_number": "REF123",
  "payment_methods": ["card", "paynow_online"],
  "url": "https://securecheckout.hit-pay.com/payment-request/@business/9e9be41b.../checkout",
  "redirect_url": "https://example.com/success",
  "created_at": "2025-04-06T15:17:21",
  "updated_at": "2025-04-06T15:17:43",
  "payments": [
    {
      "id": "9e9be41c-2869-4b8c-8701-6c44af86b7d0",
      "status": "succeeded",
      "buyer_email": "john@example.com",
      "currency": "sgd",
      "amount": "100.00",
      "refunded_amount": "0.00",
      "payment_type": "card",
      "fees": "4.15",
      "created_at": "2025-04-06T15:17:21",
      "updated_at": "2025-04-06T15:17:43"
    }
  ]
}

Validating the Webhook

To ensure the webhook is authentic, validate the Hitpay-Signature header:
  1. Receive the JSON payload and Hitpay-Signature from the request
  2. Use your salt value (from the dashboard) as the secret key
  3. Compute HMAC-SHA256 of the JSON payload using your salt
  4. Compare the computed signature with Hitpay-Signature - they must match
function validateWebhook($payload, $signature, $salt) {
    $computedSignature = hash_hmac('sha256', $payload, $salt);
    return hash_equals($computedSignature, $signature);
}

// Usage
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_HITPAY_SIGNATURE'];
$salt = 'your_salt_from_dashboard';

if (validateWebhook($payload, $signature, $salt)) {
    $data = json_decode($payload, true);
    // Process the payment confirmation
    // Mark order as paid
} else {
    http_response_code(401);
    exit('Invalid signature');
}
Congrats! You have now successfully completed the payment integration.

Other Integration Types

FAQs

The webhook parameter in the payment request API is deprecated and will be removed in a future version.Why the change?
  • The new registered webhook system supports JSON payloads with richer data
  • You can subscribe to multiple event types (not just payment completion)
  • Centralized management from your dashboard
  • Better scalability - one webhook URL handles all your payment requests
  • Supports events beyond payments: refunds, orders, invoices, transfers, and more
Migration:
  1. Register your webhook URL in Settings > API Keys
  2. Subscribe to payment_request.completed and charge.created events
  3. Update your webhook handler to accept JSON payloads
  4. Remove the webhook parameter from your API calls
If you’re currently using the webhook parameter, your integration will continue to work, but we recommend migrating to the registered webhook system for better functionality and future compatibility.
Possible reasons for signature mismatch:
  • Ensure you are using the correct salt value from the correct environment (Sandbox or Production)
  • Make sure you are computing the HMAC-SHA256 of the raw JSON payload
  • Verify the signature is being read from the Hitpay-Signature header
Possible reasons for this error:
  • You are using a production key in the sandbox or a sandbox key in production. Make sure the API base URL is correct.
  • You are missing headers. Ensure that you include both the ‘Content-Type’ and ‘X-Requested-With’ headers. Refer to this section again.
Ensure the following before moving to production
  • Change the base URL for all API calls to https://api.hit-pay.com/v1/
  • Finish paynow and other payment methods set up in production
  • Update API keys and Salt values from the production dashboard
  • If you are using Drop-In UI, update the default link to the production URL
HitPay enforces the following rate limits to ensure optimal performance and prevent abuse:
  • General API Rate Limit: 400 requests per minute across all endpoints
  • Payment Request Endpoint: 70 requests per minute (additional limit to prevent payment request misuse)
To avoid hitting rate limits and ensure reliable payment status updates, implement webhooks instead of polling the API for payment status. Use API status checks only as a fallback mechanism when webhooks fail.
If you are using a payment plugin, after every successful payment, a webhook is sent to your store to acknowledge the payment confirmation. Your order is marked as paid through this webhook.A webhook status showing as "failed" indicates that Hitpay failed to communicate with your server. This can happen for the following reasons:
  • Your store may have a security feature that blocked Hitpay's request.
  • Your server was unavailable during this time.
To avoid this issue, ensure that you whitelist Hitpay's IP addresses:
  • Production: 3.1.13.32, 52.77.254.34
  • Sandbox: 54.179.156.147
For further details, please review your store's debug logs.