Skip to main content

Introduction

Embedded QR Code Payments allow seamless integration of QR payments directly into your platform without redirecting the users away.

Core Concept

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

Supported Methods

Please note that not all payment methods support embedded QR Codes. Here is the list of methods that support QR Codes:
Payment MethodCode
PayNowpaynow_online
ShopeePayshopee_pay
QRISdoku_qris (Indonesia merchants), ifpay_qris (other merchants)
WeChatPaywechat_pay
VietQRvietqr_payme
PromptPayopn_prompt_pay
TrueMoneyopn_true_money_qr
GrabPaygrabpay_direct
GrabPay PayLatergrabpay_paylater
UPIupi_qr
Gcashgcash_qr
QRPHqrph_netbank
Touch ‘n Gotouch_n_go
ShopBackComing Soon

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 a 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.

Endpoint

POST /v1/payment-requests Creates a payment request and generates a QR code for the paynow_online payment method.

Request Parameters

ParameterTypeDescription
amountstringRequired. The amount to be paid.
currencystringRequired. The currency of the payment (e.g., “sgd”).
payment_methods[]arrayRequired. Specify paynow_online as the payment method.
generate_qrbooleanRequired. Set to true to generate the QR code.
namestringOptional. The name of the customer.
emailstringOptional. The email of the customer.
phonestringOptional. The phone number of the customer.
purposestringOptional. The purpose of the payment.
reference_numberstringOptional. A reference number for the payment.

Example Request

{
  "amount": "123.00",
  "currency": "sgd",
  "payment_methods": ["paynow_online"],
  "generate_qr": true,
  "expiry_date": "2024-06-01T14:37:11"
}

Response

The response will include a qr_code_data object, which contains the data to be converted into a scannable QR code (qr_code).
{
  "id": "9c262fb5-f3cd-4187-8c3e-fbe20730b9c6",
  "name": null,
  "email": null,
  "phone": null,
  "amount": "123.00",
  "currency": "sgd",
  "is_currency_editable": false,
  "status": "pending",
  "purpose": null,
  "reference_number": null,
  "payment_methods": [
    "paynow_online"
  ],
  "url": "https://securecheckout.hit-pay.com/payment-request/@nitinmuthyala/9c262fb5-f3cd-4187-8c3e-fbe20730b9c6/checkout",
  "redirect_url": null,
  "webhook": null,
  "send_sms": true,
  "send_email": false,
  "sms_status": "pending",
  "email_status": "pending",
  "allow_repeated_payments": false,
  "expiry_date": null,
  "address": null,
  "line_items": null,
  "executor_id": null,
  "created_at": "2024-05-28T14:37:11",
  "updated_at": "2024-05-28T14:37:11",
  "qr_code_data": {
    "qr_code": "00020101021226550009SG.PAYNOW010120210201605883W030100414202405281445315204000053037025406123.005802SG5905Nitin6009Singapore62290125DICNP17168782314914MWULPX63043561",
    "qr_code_expiry": null
  }
}

Step 2: Generate and Present the QR Code

Once the payment request is created, generate the QR code using the response data and present it to the user.
Note for Sandbox Testing:In sandbox, the qr_code value returned may be a URL (e.g. https://securecheckout.sandbox.hit-pay.com/...) instead of the raw PayNow QR string. This is intended to help you test the flow using a standard QR code reader or by visiting the link directly in a browser.
In production, the qr_code will be a raw PayNow payload string that you should convert into a scannable QR code for use with banking apps.

Step 3: Client Scans and Initiates Payment

The client scans the presented QR code with their banking app and initiates the payment process.

Step 4: Handle Webhooks and Server Communication

After the payment is processed, handle webhooks to receive payment notifications and manage server-client communication to update the payment status in your system.

What is a Webhook?

A webhook is a POST request sent from HitPay’s server to your server about the payment confirmation. You must mark your order as paid ONLY after the webhook is received and validated.

Register Your Webhook

To receive payment notifications, 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": "9c262fb5-f3cd-4187-8c3e-fbe20730b9c6",
  "name": "John Doe",
  "email": "[email protected]",
  "phone": "+6512345678",
  "amount": "123.00",
  "currency": "SGD",
  "status": "completed",
  "purpose": "Order #12345",
  "reference_number": "REF123",
  "payment_methods": ["paynow_online"],
  "created_at": "2024-05-28T14:37:11",
  "updated_at": "2024-05-28T14:38:25",
  "payments": [
    {
      "id": "9c262fb5-a1b2-4c3d-8e9f-123456789abc",
      "status": "succeeded",
      "buyer_email": "[email protected]",
      "currency": "sgd",
      "amount": "123.00",
      "refunded_amount": "0.00",
      "payment_type": "paynow_online",
      "fees": "0.50",
      "created_at": "2024-05-28T14:37:11",
      "updated_at": "2024-05-28T14:38:25"
    }
  ]
}

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');
}

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
Migration:
  1. Register your webhook URL in Settings > API Keys
  2. Subscribe to payment_request.completed event
  3. Update your webhook handler to accept JSON payloads
  4. Remove the webhook parameter from your API calls
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.
Ensure the following before moving to production:
  • Change the base URL for all API calls to https://api.hit-pay.com/v1/
  • Complete payment method setup in production
  • Update API keys and Salt values from the production dashboard
  • Register your webhook URL in production
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.