Integration Steps
Integration Steps
Authentication
Hitpay uses API keys to allow access to the API. You can register a new API key at our developer portal.
Hitpay expects the API key to be included in all API requests to the server in a header that looks like the following:
X-BUSINESS-API-KEY: meowmeowmeow
$request->setHeaders(array(
'X-BUSINESS-API-KEY' => 'meowmeowmeow',
'Content-Type' => 'application/x-www-form-urlencoded',
'X-Requested-With' => 'XMLHttpRequest'
));
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here"
-H "X-BUSINESS-API-KEY: meowmeowmeow"
-H "X-Requested-With: XMLHttpRequest"
API Security
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.
HTTP Request
POST https://api.sandbox.hit-pay.com/v1/payment-requests
Query Parameters
Mandatory fields are amount
and currency
. Remember to include header Content-Type: application/x-www-form-urlencoded
Parameter | Description | Example |
---|---|---|
amount | Amount related to the payment | 2500.00 |
payment_methods[] | Choice of payment methods you want to offer the customer | paynow_online , card, wechat, alipay, grabpay, fave_duit, shopback, atome |
currency | Currency related to the payment | SGD |
Buyer’s email | [email protected] | |
purpose | Purpose of the Payment request FIFA 16 | |
name | Buyer’s name | John Doe |
reference_number | Arbitrary reference number that you can map to your internal reference number. This value cannot be edited by the customer | XXXX123 |
redirect_url | URL where we redirect the user after a payment. Query arguments reference (payment request id) and status are sent along | https://example.com/callback |
webhook | URL where our server do POST request after a payment If done | https://example.com/webhook |
allow_repeated_payments | If set is true, multiple payments can be paid on a payment request link. Default value is false | false |
expiry_date | Time after which the payment link will be expired(time in SGT). Applicable for repeated payments. Default is Null | 2021-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' => '[email protected]',
'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": "[email protected]",
"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
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
Option 2: Present the Drop-In:
Unlike the redirect checkout page, the drop-in is embedded into your webpage so your customer will never have to leave your site. To present this you will need 2 values "default_link" and "payment_request_id". The default link value can be found in your Dashboard > Payment Links > Default link and this value is fixed for all your payment.
Sample code for Drop-In UI can be found here
NOTE
Drop-in UI currently does not support Apple Pay.
Warning
Do not use
status
oronSuccess
to mark your order as completed. Please refer to the webhook section for more details.
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.
Webhooks
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.
- 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
payment_id=92965a2d-ece3-4ace-1245-494050c9a3c1&payment_request_id=92965a20-dae5-4d89-a452-5fdfa382dbe1&reference_number=ABC123&phone=&amount=599.00¤cy=SGD&status=completed&hmac=330c34a6a8fb9ddb75833620dedb94bf4d4c2e51399d346cbc2b08c381a1399c
Webhook fields
Following fields are sent with the webhook request:
Parameter | Description |
---|---|
payment_id | Payment ID |
payment_request_id | Payment request ID |
phone | Buyer’s phone number |
amount | Amount related to the payment |
currency | Currency related to the payment |
status | Payment status (completed / failed) |
reference_number | Arbitrary reference number that you have mapped during payment request creation |
hmac | Message Authentication code of this webhook request |
Validate Webhook
Hitpay creates a list of all values from the key-value pairs that we send in the POST request and sort them in the order of their keys alphabetically. We then concatenate all these values together. We then use the HMAC-SHA256 algorithm to generate the signature. The HMAC key for the signature generation is the secret salt
from your dashboard under Settings > Payment Gateway > API Keys
.
public 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;
}
Signature Mismatch?
Possible reasons for wrong hmac value generated
- Ensure that you are using the correct salt value from the correct environment (Sandbox or Production)
- Make sure NOT to include the hamc value when calculating the hmac
- Make sure all the values stated above are included in the payload including reference_number. Use an empty string if the value does not exist
Next Step
Congrats! You have now successfully completed the payment integration.
Refund API: This is an optional API call, you may use this to refund a specific payment.
Production Checklist: Checkout before you go live.
Payment Request: Reference to the API Details
Updated 4 days ago