Version1.0.0
Before You Start
1️⃣ Basic Information
| Item | Details |
|---|---|
| BaseURL | https://pay.clickpay.lol |
| Response Format | application/json |
| Time Unit | Unix Timestamp (seconds) |
| Array Sort Order | Ascending by time (earlier first) |
2️⃣ Common Status Codes
| HTTP Code | Meaning |
|---|---|
| 200 | Request succeeded |
| 400 | Invalid request parameters or headers |
| 401 | Access denied |
| 403 | Invalid signature |
| 404 | Request URL not found |
| 500 | Internal system error |
| 503 | Business failure (check business error code returned) |
3️⃣ Error Response Format
{
"code": "Error Code",
"message": "Error Message"
}
4️⃣ API Rate Limits and Timeouts
| Item | Rule |
|---|---|
| PayIN API rate limit | 150 requests per second per merchant, with a burst capacity of 150 requests |
| Payout API rate limit | 60 requests per second per merchant, with a burst capacity of 60 requests |
| PayIN API timeout | 60 seconds |
| Payout API timeout | 60 seconds |
| Merchant callback timeout | 10 seconds each for connection, read, and write |
If a PayIN or Payout request takes unusually long, treat it as an exception and contact support with the relevant request and order details. The callback is the authoritative source of the final transaction result.
5️⃣ Security Mechanism - Signature Verification Rules
📌 General Instructions
- All requests must include a signature in the header.
- Header parameter name:
Signature - Header names are case-insensitive; Base64 signature values are case-sensitive and must not be modified.
- Merchant: sign with private key.
- Platform: signs returned data with private key, merchant verifies with platform's public key.
Use lowercase hexadecimal SHA-512 digests and RSA PKCS#1 v1.5. Serialize JSON once and sign the exact UTF-8 bytes sent over HTTP. Never sort, format or re-serialize a received callback before verification. See the shared contract in each language example for supported key formats and diagnostic logging.
📌 Signature Algorithm Process
POST / PUT Requests
1️⃣ SHA512 body content -> Digest A
2️⃣ Concatenate path + Digest A + timestamp -> Text B
3️⃣ Use RSA private key to sign Text B with SHA512withRSA
GET / DELETE Requests
1️⃣ No body, Digest A is an empty string
2️⃣ Concatenate path + Digest A + timestamp -> Text B
3️⃣ Use RSA private key to sign Text B with SHA512withRSA
📌 Required Headers
| Header Name | Description |
|---|---|
| Timestamp | Current timestamp (seconds) |
| Merchant-Code | Merchant Code |
| Signature | Signature value |
6️⃣ API Example: Place Order API
Request URL
POST /v1/merchant/pay
Header Example
| Header | Value |
|---|---|
| Merchant-Code | 003 |
| Timestamp | 1699447297 |
| Signature | [Signature String] |
Request Parameters (JSON Body)
{
"amount": "2",
"method": "gee",
"phone": "1",
"name": "1",
"merchantSerialNo": "T1699447296",
"remark": "1",
"email": "1"
}
Signature Example Process (Pseudo Code)
Step 1: SHA512 Digest A
{"amount":"2","method":"gee",...} -> Digest A = 7e28... (128 lowercase hex characters, no timestamp)
Step 2: Concatenate
/v1/merchant/pay + Digest A + timestamp
-> /v1/merchant/pay7e28...1699447297
Step 3: RSA Signature
SHA512WithRSA(concatenated result) -> signature result
curl Example
curl -X POST 'https://pay.clickpay.lol/v1/merchant/pay' -H "Content-Type: application/json" -H "Merchant-Code: 003" -H "Timestamp: 1699447297" -H "Signature: [signature]" -d '{"amount":"2","method":"gee","phone":"1","name":"1","merchantSerialNo":"T1699447296","remark":"1","email":"1"}'
Success Response
{
"code": 0,
"msg": null,
"sign": "[returned signature]",
"timestamp": "1699448046",
"data": {
"merchantId": "618918202310181957279",
"merchantSerialNo": "T1699447296",
"method": "gee",
"amount": 2,
"transactionId": "6189182023110820540519",
"payUrl": "https://openapi.kypays.com/pix/6189182023110820540519",
"fee": "0.42000000",
"status": "10",
"payData": {"qrcode":"000201..."}
}
}
7️⃣ API Example: Query Balance
📍 Request URL
GET /v1/merchant/account
📌 Header Example
| Header | Value |
|---|---|
| Merchant-Code | 003 |
| Timestamp | 1699447297 |
| Signature | [Signature] |
🔐 Signature Process Example (Pseudocode)
Step 1: Parameter string (empty for GET without query params)
paramStr = ""
Step 2: Construct the string to sign
/v1/merchant/account + paramStr + Timestamp
-> /v1/merchant/account1699447297
Step 3: Generate RSA signature using SHA512WithRSA
Signature = SHA512WithRSA(concatenated string)
🧪 curl Example
curl -X GET 'https://pay.clickpay.lol/v1/merchant/account' \
-H "Merchant-Code: 003" \
-H "Timestamp: 1699447297" \
-H "Signature: [Signature]"
✅ Successful Response
{
"code": 0,
"sign": "[Response Signature]",
"timestamp": "1699448200",
"data": {
"currency": "[currency]",
"id": "263940537239867393",
"memberId": "618918202501161501465",
"memberCode": "UPITEST",
"memberName": "UPITEST",
"accountType": "11",
"cash": 112.0,
"freeze": 0.0,
"security": 0.0,
"unSettlement": 0.0,
"credit": 0.0,
"createTime": "2025-01-16 15:01:46"
}
}
8️⃣ Platform Callback Signature Rules ✅ (Important)
⚠️ Different from request signatures: callback signatures do not include the path, only the digest + timestamp are concatenated
📌 Signature Algorithm (Platform → Merchant)
1️⃣ Compute SHA512 of the callback Body -> Digest A
2️⃣ Concatenate Digest A + Timestamp (from Header)
3️⃣ Use the platform's RSA private key to sign the concatenated string using SHA512withRSA
📌 Header Example
| Header | Value |
|---|---|
| Timestamp | 1699447297 |
| Signature | [Signature Value] |
📌 Body Example
{
"merchantId": "618918202310181957279",
"merchantSerialNo": "T1699447296",
"method": "gee",
"amount": 2,
"transactionId": "6189182023110820540519",
"payUrl": "https://openapi.kypays.com/pix/6189182023110820540519",
"fee": "0.42000000",
"status": "10"
}
📌 Signature Procedure Example
Step 1: SHA512 Digest A
-> 7e28...
Step 2: Concatenate
7e28... + 1699447297
Step 3: Sign
SHA512withRSA(concatenated string) -> Signature Value
📌 Merchant Verification Process
After receiving the callback, the merchant should:
- Extract the callback JSON Body, and compute the SHA512 digest using UTF-8 encoding.
- Concatenate the digest with the Timestamp from the Header.
- Use the platform's public key and SHA512withRSA to verify the signature.
9️⃣ RSA Key Example
The complete runnable Python callback verification example includes a test platform public key, raw body, Timestamp, Signature and expected output. No private key is required to verify it.
The example uses a 2048-bit test key and a 256-byte Base64-decoded signature; it is not the production platform public key. Use the platform public key from the corresponding merchant account, not the merchant public key. A 1024-bit public key does not match a 256-byte signature; changing key formatting cannot resolve that mismatch.
🔟 Signature Value Reference Table
| Step | Example Value |
|---|---|
| SHA512 Digest A | 7e28... (128 lowercase hex characters) |
| RSA Signature | HpPa41g0aK4zP...== |
11. Code Examples
Java Integration Guide
For detailed SDK integration methods and sample code, please refer to the Java Example Documentation.
PHP Integration Guide
For detailed SDK integration methods and sample code, please refer to the PHP Example Documentation.
C# Integration Guide
For detailed SDK integration methods and sample code, please refer to the C# Example Documentation.
Go Integration Guide
For detailed SDK integration methods and sample code, please refer to the Go Example Documentation.
Python Integration Guide
For detailed SDK integration methods and sample code, please refer to the Python Example Documentation.
Node.js Integration Guide
For detailed SDK integration methods and sample code, please refer to the Node.js Example Documentation.
Public API Parameters
Enum Definitions
Order Status
Parameter Name (status)
Payment
| Status | Description |
|---|---|
00 | Pending merchant matching |
10 | Awaiting payment |
11 | Payment in progress |
12 | Payment timeout |
20 | Payment completed |
30 | Payment refunded |
31 | Payment failed |
Payout
| Status | Description |
|---|---|
00 | Pending Merchant Match |
10 | Pending Processing |
11 | Pending Payout |
12 | Payout in Progress |
20 | Payout Completed |
30 | Payout Refunded |
31 | Payout Failed |
Fee Types
Parameter Name (feeType)
| Fee Type | Description |
|---|---|
0 | Deducted from payout amount |
1 | Deducted from balance |
Collection Payment Methods
Parameter Name (method)
| Payment Method | Description |
|---|---|
QR | QR Code |
TRANSFER | Bank Transfer |
Payout Payment Methods
Parameter Name (method)
| Payment Method | Description |
|---|---|
BANK | Bank Transfer |
WALLET | Wallet Payment |
Collection
Place Order
POST /v1/merchant/pay
Request
{
"amount": "500",
"method": "QR",
"phone": null,
"name": "1",
"merchantSerialNo": "T1699447296",
"remark": "1",
"description": "1",
"title": "1",
"email": null
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| amount | string | No | Amount |
| method | string | No | See enum Payment Methods |
| phone | string | Yes | Phone number |
| name | string | No | Name |
| merchantSerialNo | string | No | Merchant order number |
| remark | string | Yes | Remark |
| title | string | Yes | Title |
| description | string | No | Description |
| string | Yes | Email address | |
| notifyUrl | string | Yes | Callback URL. If this value is not empty, the callback will be sent to this URL; otherwise, it will be sent to the callback address configured in the backend. |
| redirectUrl | string | Yes | Redirect URL. If this value is not empty, the user will be redirected to this URL after payment is completed. |
| directConnect | boolean | Yes | Direct connect flag. true = direct connect, false = non-direct (default false). |
Response
{
"code": 0,
"sign": "glOvHa8zstiAG6/6fZ/fhECYH64j4rdFj9uHW9qks5Vvdke1imEvmeMcImDrb1l+EDFYrGV/ovJ5SuEnmPZtmy1Gyeh1f3NlL9Y5N/PKvlMZn9CrGEmRHwn2hzFuNuYiYCHbYwPr2e5llMpojGF/ySNvUvPJXD7G3ouLQdSSIUE=",
"timestamp": "1754387547",
"data": {
"merchantCode": "M",
"currency": "myr",
"merchantSerialNo": "74769685-b602-4a85-a306-1c64aa627e22",
"method": "QR",
"amount": 500,
"transactionId": "122",
"payUrl": "https://cashier2.clickpay.lol/pay/v1/idr/php/122"
"fee": 60.0,
"status": "10"
}
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| code | int | No | See error codes |
| msg | string | Yes | Error message |
| sign | string | Yes | Signature |
| timestamp | string | Yes | Timestamp |
| data | object | Yes | Order data |
data
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| merchantSerialNo | string | No | Merchant order number |
| method | string | No | Payment method |
| amount | string | No | Amount |
| transactionId | string | No | Platform transaction ID |
| payUrl | string | Yes | Payment URL |
| status | string | No | See enum Order Status; must check status as network delays may affect polling |
| fee | string | No | Fee |
| payData | object | No | Payment data |
Query Collection Order
POST /v1/merchant/pay/order/info
Request
{
"transactionId": "61891820250719160658208575",
"merchantSerialNo": "T1699447296"
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| transactionId | String | Yes | Platform Order ID, at least one of the two must be provided |
| merchantSerialNo | String | Yes | Merchant Order ID |
Response
{
"code": 0,
"sign": "DKeoiWNFEByMQsRFix2dC7f7jA8GGXQOBTYVsRpmYtJXMA/Vd5j06M74Q23215kwjuuzBWRfiiQbZDKNq/kJRz1WMpsomyCL/TKsqzAhMX7JBXWCGYLql5WS0sIG2pNB4mSxKUVtOxqErEUf8V4e1ozrQBHfdtydDueegGK+rjUaQGLSM/KzPygwDN6X0n/egN1rYQwJ6yfafwAIDVH7cW3hrnzG0b2UToC6SaxWsxCRnGh2JUsHgT+xfrzjwtROSq311tuxLlNtu4nFTacyvk7xlYsF+NZKgeMe5RAzvFU1eAxncuqqqCrOyIGiOGZHjFlJmCmoiHmNb2bxgYieDg==",
"timestamp": "1737088697",
"data": {
"merchantId": "618918202501161501465",
"merchantSerialNo": "T1737088694387",
"method": "[method]",
"amount": 200,
"orderAmount": 200,
"transactionId": "61891820250117123815588",
"payUrl": "https://h5.simplypay.vip/payment/d1bab78392a941d4b4f570dbd0728303?cashUrl=https://pay.wepaytm.xyz/upi/checkout/4I6w",
"fee": 20.0,
"status": "10"
}
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| code | int | No | See Error Codes |
| msg | string | Yes | Error Message |
| sign | string | Yes | Signature |
| timestamp | string | Yes | Timestamp |
| data | object | Yes | Order Data |
data Fields
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| merchantSerialNo | string | No | Merchant Order No. |
| method | string | No | Payment Method |
| amount | string | No | Actual paid amount |
| orderAmount | string | No | Order amount |
| transactionId | string | No | Platform Order ID |
| payUrl | string | No | Payment URL |
| payData | string | Yes | Payment Content |
| status | string | No | See enum Order Status |
| fee | string | No | Service Fee |
| channelBankSerialNo | string | Yes | Bank Transaction No. |
| message | string | Yes | Failure Reason |
Collection Asynchronous Notification
POST to the merchant's configured collection callback URL
Request
HEADERS
| Parameter | Description |
|---|---|
| Signature | Signature |
| Timestamp | Timestamp |
BODY
{
"transactionId": "2",
"amount": "1",
"orderAmount": "1",
"method": "gee",
"currency": "",
"merchantSerialNo": "T1699447296",
"status": "20",
"payUrl": "http://",
"fee": "0.1"
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| merchantSerialNo | string | No | Merchant Order No. |
| method | string | No | Payment Method |
| currency | string | No | Currency |
| amount | string | No | Actual paid amount |
| orderAmount | string | No | Order amount |
| transactionId | string | No | Platform Order ID |
| payUrl | string | No | Payment URL |
| status | string | No | See enum Order Status |
| fee | string | No | Service Fee |
| channelBankSerialNo | string | Yes | Bank Transaction No. |
| message | string | Yes | Failure Reason |
Response
SUCCESS
Merchants must return SUCCESS. The first notification is sent immediately. Failed notifications are checked again every 60 seconds, with a maximum of 10 delivery attempts in total.
Payout
Place Order
POST /v1/merchant/payout
Request
{
"bankCode": "affinbank",
"bankName": "AffinBank",
"amount": "2",
"method": "BANK",
"bankCard": "03123456789",
"accountEmail": null,
"accountMobile": null,
"accountName": "1",
"merchantSerialNo": "T1701344062",
"bankName": "1",
"remark": "1",
"feeType": "1"
}
Parameter List
| Parameter | Type | Nullable | Description |
|---|---|---|---|
| amount | string | No | Amount |
| method | string | Yes | See the enum Payment Method |
| bankCode | string | Yes | Bank code. See Bank List |
| bankCard | string | No | Bank withdrawal account |
| accountMobile | string | Yes | Phone number |
| accountEmail | string | Yes | Email address |
| accountName | string | No | Account name |
| bankName | string | No | Bank name, can be a fixed value |
| merchantSerialNo | string | No | Merchant order number |
| remark | string | Yes | Remark |
| feeType | string | No | See enum Fee Type |
| notifyUrl | string | Yes | Callback URL; if not empty, callback will be sent here, otherwise to the default backend callback URL |
Response
{
"code": 0,
"msg": null,
"sign": "jTY5Z021R2J/ixsi1t6P4+sH0XoZ4La4YMEFTYe5MlxoEn5s4xcRwv4oZAM5Nk/+lqWyVSRCpKbqzCsyAFo27duJ+MxvzCyIweDSV1tDnyQ42j8IhaAoo61bSVHbmMS2UFMX0wCpiyFLyE0VsAza3hsqYk2Ad0RK043xsasyOrP3PA0x2LLdbY3XauW/Lh9U6VJ6yJyL646inPQ1WmahtZr2bWiL/ueTephTdv/JljwzphyJ3gnrm4a0F9lgMXQX8eborvMhhEQBPYYhpq6trxZ4nOmDQuTx/rHK3WlgTm19VY/IqxZtRcs368qQVe+gFuF3pgyjB4+M9bR5npRQ7w==",
"timestamp": "1701344063",
"data": {
"merchantId": "618918202310181957279",
"merchantSerialNo": "T1701344062",
"method": "BANK",
"amount": 2,
"transactionId": "618918202311301934237",
"fee": "10.20000000",
"status": "10"
}
}
Parameter List
| Parameter | Type | Nullable | Description |
|---|---|---|---|
| code | int | No | See error codes |
| msg | string | Yes | Error message |
| sign | string | Yes | Signature |
| timestamp | string | Yes | Timestamp |
| data | object | Yes | Order data |
data
| Parameter | Type | Nullable | Description |
|---|---|---|---|
| merchantSerialNo | string | No | Merchant order number |
| method | string | No | Payment method |
| amount | string | No | Amount |
| transactionId | string | No | Platform order number |
| status | string | No | See enum Order Status |
| fee | string | No | Fee |
Query Payout Order
POST /v1/merchant/payout/order/info
Request
{
"transactionId": "61891820250719160658208575",
"merchantSerialNo": "T1699447296"
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| transactionId | String | Yes | Platform Order ID, at least one of the two must be provided |
| merchantSerialNo | String | Yes | Merchant Order Number |
Response
{
"code": 0,
"msg": null,
"sign": "dZMsjIJd5JrH660JZVKmc3XTwnNOV9WxvvMcuMqIMmbdDXjYUXENL7vshZU965ilkBniBVs2MJEkpz3irB6CaiT7oCY/HirQXrzOrF4csxeBz00sr0fZr+Mv0lWRSgS4CS8ppMB9IYkwuzp8c7gEsRVIV/DaEX3nUdwCPRM1rqKK3M2QvRUvZYHuhof0ewfMRDs5CwTS5s8WL63z2wzChsM0Op5bidG8+Xfdzw8s9x0cphwa4kY8YG4tPfqJy7tcEi0JJerImjGfUyRWX8xR0dU9krwOyKCL5oh+y5eCnF4yKO5BLvQ9RHdz5vZxZc+nkfuXghmN4KmtZzj/Rr/PPw==",
"timestamp": "1701350818",
"data": {
"merchantId": "618918202310181957279",
"merchantSerialNo": "T1701348703",
"method": "BANK",
"amount": 2.0,
"transactionId": "618918202311302051438",
"fee": "10.20000000",
"status": "10"
}
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| code | int | No | See error codes |
| msg | string | Yes | Error message |
| sign | string | Yes | Signature |
| timestamp | string | Yes | Timestamp |
| data | object | Yes | Order data |
data Fields
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| merchantSerialNo | string | No | Merchant Order Number |
| method | string | No | Payment Method |
| amount | string | No | Amount |
| transactionId | string | No | Platform Order Number |
| status | string | No | See enum Order Status |
| fee | string | No | Fee |
| channelBankSerialNo | string | Yes | Bank transaction number |
| message | string | Yes | Failure Reason |
Payout Asynchronous Notification
POST to the merchant-configured payout callback URL
Request
HEADERS
| Parameter | Description |
|---|---|
| Signature | Signature |
| Timestamp | Timestamp |
BODY
{
"transactionId": "2",
"amount": "1",
"currency": "",
"method": "BANK",
"merchantSerialNo": "T1699447296",
"status": "20",
"fee": "0.1"
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| merchantSerialNo | string | No | Merchant order number |
| method | string | No | Payment method |
| currency | string | No | Currency |
| amount | string | No | Amount |
| transactionId | string | No | Platform order number |
| status | string | No | See enum Order Status |
| fee | string | No | Fee |
| channelBankSerialNo | string | Yes | Bank transaction number |
| message | string | Yes | Failure reason |
Response
SUCCESS
The merchant must return SUCCESS. The first notification is sent immediately. Failed notifications are checked again every 60 seconds, with a maximum of 10 delivery attempts in total.
Query Balance
GET /v1/merchant/account
Response
{
"code": 0,
"sign": "C3i5JNPU7KLXOM8tWlbJM9pPmeHJ2ciE60VbTJBbfDhK+5hUEDOeqa32yYUX9m7hIgrNIj12Y8SNKctSxB5pw9BVUr2FzDrEb0DY8ppSuQ20KieLXX2xyxXmEAh288I1ikHlO36eWr7u/Plpi/3FEMnLGtHd8ma5T/hz86XIY41a7VwJUvEhwpihASUd4fYtqSRoI+9bFjuC6d92yfpyXo+i/M43lezLSbhOBJnj1pDjF3iBPZVbszOPIK+tsbZjdWPP+SjT59lCMjKtkCAtY/tO7/NQB69Yz/LrS3ar7Z1/Qzo+GYdikCqpi+oCDDZjVgE9IQRuw25NCm+yo5v9hw==",
"timestamp": "1737090710",
"data": {
"currency": "[currency]",
"id": "263940537239867393",
"memberId": "618918202501161501465",
"memberCode": "UPITEST",
"memberName": "UPITEST",
"accountType": "11",
"cash": 112.0,
"freeze": 0.0,
"security": 0.0,
"unSettlement": 0.0,
"credit": 0.0,
"createTime": "2025-01-16 15:01:46"
}
}
Parameter List
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| code | int | No | See error codes |
| msg | string | Yes | Error message |
| sign | string | Yes | Signature |
| timestamp | string | Yes | Timestamp |
| data | object | Yes | Balance data |
data fields:
| Parameter Name | Type | Nullable | Description |
|---|---|---|---|
| currency | string | No | Currency |
| cash | string | No | Cash balance |
| freeze | string | No | Frozen balance |
| unSettlement | string | No | Pending settlement balance |
Bank List
| Bank Code | Bank Name |
|---|---|
| affinbank | AffinBank |
| agrobank | AgroBank |
| alliancebank | Alliance Bank |
| ambank | AmBank |
| bimb | Bank Islam Malaysia |
| bsn | BSN |
| cimb | CIMB |
| hongleongbank | Hong Leong Bank |
| maybank | Maybank |
| mbsb | MBSB |
| publicbank | Public Bank |
| rhb | RHB |
| uob_my | UOB Malaysia |
| bankrakyat | Bank Rakyat |
| ocbc_my | OCBC Bank |
| hsbc | HSBC |
Wallet List
| Wallet Code | Wallet Name |
|---|---|
| touchngo | Touch 'n Go |
Error Code List
| Error Code | Description |
|---|---|
| 0 | Success |
| 400 | Invalid Request Parameters |
| 1000 | Insufficient User Balance |
| 403 | Signature verify failure |
| 500 | Internal server error, please contact administrator. |
| 9999 | Unknown exception |
| 9000 | Invalid parameter |
| 9002 | Unauthorized access |
| 9008 | Duplicate request |
| 8000 | Merchant is frozen |
| 8001 | Merchant does not support this payment method |
| 8003 | The requested payment method or amount is not supported. Use the documented method value with the exact case and no leading or trailing spaces, and check that amount meets the requirements of your enabled payment service. If both are correct, contact support. |
