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
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
webhookURL where our server does a POST request after a payment is completedhttps://example.com/webhook
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',
  'webhook' => 'https://test.com/webhook',
  '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": null,
    "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",
    "webhook": "https://test.com/webhook",
    "send_sms": true,
    "send_email": true,
    "sms_status": "pending",
    "email_status": "pending",
    "allow_repeated_payments": true,
    "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.”

  • Option 1: Redirect to HitPay Checkout

  • Option 2: Present the 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 “redirect_url” defined in step 1.

You might be tempted to just use the “redirect_url” to mark your order as completed and show an “Order Success” screen to your users but this could be a security issue. You must always use the “Webhook” to confirm your order.

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.

Handling the webhook

  • Create an endpoint (E.g. /payment-confirmation/webhook) in your server that accepts POST requests. This request is application/x-www-form-urlencoded.
  • Validate the webhook data using your salt value
  • Return HTTP status code 200 to Hitpay
  • Mark your order as paid
  • Sample webhook payload data

Sample Webhook Payload

payment_id=92965a2d-ece3-4ace-1245-494050c9a3c1&payment_request_id=92965a20-dae5-4d89-a452-5fdfa382dbe1&reference_number=ABC123&phone=&amount=599.00&currency=SGD&status=completed&hmac=330c34a6a8fb9ddb75833620dedb94bf4d4c2e51399d346cbc2b08c381a1399c

Webhook fields

Following fields are sent with the webhook request:

ParameterDescription
payment_idPayment ID
payment_request_idPayment request ID
phoneBuyer’s phone number
amountAmount related to the payment
currencyCurrency related to the payment
statusPayment status (completed / failed)
reference_numberArbitrary reference number mapped during payment request creation
hmacMessage Authentication code of this webhook request

Validating a Webhook

To validate a webhook payload from HitPay, follow these steps:

  1. Payload Extraction: Extract the key-value pairs from the webhook payload. For example:
payment_id=92965a2d-ece3-4ace-1245-494050c9a3c1&payment_request_id=92965a20-dae5-4d89-a452-5fdfa382dbe1&reference_number=ABC123&phone=&amount=599.00&currency=SGD&status=completed&hmac=330c34a6a8fb9ddb75833620dedb94bf4d4c2e51399d346cbc2b08c381a1399c
  1. Exclude HMAC and Values: Remove the "hmac" key and its corresponding value from the extracted payload. For example:

  2. Concatenation and Sorting: Concatenate the keys and values from the remaining key-value pairs without using "&" and "=", and arrange them in alphabetical order of the keys. For example:

amount1.00currencySGDpayment_id91d94138-b0b5-4ba0-b78c-babc59776876payment_request_id91d94124-0d1c-4fb4-921e-51953793106cphonereference_number201000000Dstatuscompleted
  1. Signature Generation: Use the HMAC-SHA256 algorithm along with the secret salt from your dashboard to generate a signature for the concatenated string. This signature will be unique to this payload.

  2. Comparison and Validation: Compare the generated signature with the HMAC value present in the original payload, both values must match.

By following these steps, you can ensure the authenticity and integrity of the webhook payload received from HitPay. This process guarantees that the payload can be trusted and processed securely.

Sample Code

function generateSignatureArray($secret, array $args) {   
  $hmacSource = [];        
  foreach ($args as $key => $val) {
    $hmacSource[$key] = "{$key}{$val}";
  }
  ksort($hmacSource);
  $sig            = implode("", array_values($hmacSource));
  $calculatedHmac = hash_hmac('sha256', $sig, $secret); 

  return $calculatedHmac;
}

Congrats! You have now successfully completed the payment integration.

FAQs