Product Introduction
With this payment method, the customer uses his mobile phone to scan the QR code displayed by the merchant. This payment method is mainly used by Chinese customers who shop in overseas stores. Merchants can integrate this payment method into their cashier system to improve user experience by providing them with the familiar and comfortable payment method, as well as to facilitate payment, foreign exchange and settlement for both merchants and customers. After integration, an Alipay payment collection button is added to the cashier system/software.
-
The cashier clicks the payment collection button, and then a QR code is displayed.
-
The customer needs to open Alipay app to scan this QR code to complete payment.
-
Meanwhile, HipoPay will inform the merchant about the payment result via an asynchronous notification, which features a reliable built-in retry mechanism.
Payment Process and User Experience
-
The merchant clicks the Alipay payment collection button:
-
A payment collection code is generated:
- The customer opens Alipay app to scan the QR code to complete payment:
Integration Process
-
Process digital signature
-
Integrate with order placement API
-
Receive asynchronous notification
-
Integrate with refund API
Digital Signature
Unless otherwise stated, all APIs require the siginature for HipoPay to confirm the identity of the user.。
HipoPay SDK has processed signature and signature verification and thus integration can be accelerated.
If it is not convenient to usd the SDK, perform the following steps to process signature.
I. Generate the private key and the public key.
- Private Key
Purpose: It performs paramter signing when the client requests the API.
Storage: Please keep it safe and properly. Do not reveal it to others.
Locally generated private key: openssl genrsa -out private.key 2048
- Public Key
Purpose: It is used for signature verification by HipoPay.
Storage: Please send it to HipoPay.
Locally generated public key: openssl rsa -pubout -in private.key -out public.key
II. Generate to-be-signed string.
-
Arrange the request parameters (query string of the GET request and form of the POST request) by parameter names based on the ASCII code in ascending lexicographical order, and use the URL key pair format (key1=value1&key2=value2…) to generate a signature string.
-
Append Timestamp to the signature string and separate them with a
,
to generate a to-be-signed string.
III. Generate the signature.
-
Encrypt the to-be-signed string by using RSA. Specify SHA256 as Hash algorithm, and use the private key in the key pair submitted when the service is requested.
-
Code the encryption result by using base64 to generate the final signature result.
IIII. Add the request header.
When the merchant sends the request, add the following four paramters in the header.
Header Parameter | Description | Generation Method |
---|---|---|
MerchantNO | Merchant No. | Allocated by HipoPay |
Version | API version No. | Fixed value 1.0 |
Timestamp | Timestamp | Timestamp as described in step II. 2 |
Signature | API signature | Result generated in step III. 4 |
When receiving HipoPay asynchronous notification, the merchant should verify the signature to confirm that the notification is sent by HipoPay and is intact. The signature verification method is as follows:
Signature verification method:
-
Arrange the returned contents corrsponding to form of the POST request by parameter names based on the ASCII code in ascending lexicographical order, and use the URL key pair format (key1=value1&key2=value2…) to generate a signature string.
-
Append the Timestamp value in the header of the POSTrequest to the signature string and separate them with a
,
to get the query_string. -
Verify the query_string and the Signature value in the header of the POST request by using SHA-256. Contact HipoPay to obtain the public key.
API List ¶
- Sandbox HOST: https://testapi.hipopay.com/
-
Mainland Wallet: Bank account with currency of CNY binded on Wechat/Alipay
-
HongKong Wallet: Bank account with currency of HKD binded on Wechat/Alipay
- Feedback: kongfm@transfereasy.com
Place an Order ¶
Place an OrderPOST/alipay/qrcode/payment
- Request Parameter
Field | Type | Required | Description | Example Value |
---|---|---|---|---|
out_trade_id | string | Y | Merchant transaction No. | “201901021232211023” |
amount | string | Y | Amount of the payment order, to two decimal places at most. For JPY and KRW, the currency units are Japanese Yen and Korean Won respectively, without decimal places. | “8.88” |
currency | string | Y | Currency of the payment order. For details, see currency code. | “HKD” |
product_info | string | Y | Product information | “Hipopay - product for test” |
client_ip | string | Y | IP address of the client | “10.129.35.61” |
hk_wallet | string | N | Whether to use AlipayHK wallet. Optional values are "TRUE" and "FALSE" . The default value is “FALSE”. |
“FALSE” |
notify_url | string | N | URL of the asynchronous notification |
- Response Data
Field | Required | Description |
---|---|---|
is_success | Y | Whether the service request is successful. Optional values are True and False . |
response | N | Service response data. It is returned when is_success=True . |
error | N | Service error code. It is returned when is_success=False . For details, see Error Code below. |
error_message | N | Service error description. It is returned when is_success=False . |
When is_success=True
, response
contains the following fields:
Field | Required | Description |
---|---|---|
amount | Y | Amount of the payment order |
currency | Y | Currency of the payment order. For details, see currency code. |
exchange_rate | N | Exchange rate adopted for settlement. It is returned when the payment order status is PAID . |
finish_time | N | Time when payment is completed. It is returned when the payment order status is PAID . |
out_trade_id | Y | Merchant transaction No. |
payment_no | Y | Payment order No. |
status | Y | Payment order status |
product_info | Y | Product information |
trade_time | Y | Time when transaction is created |
trade_type | Y | Payment method |
qrcode_url | Y | QR code information. Merchants need to generate the QR code by themselves according to qrcode_url . |
- Error Code
Error Code | Meaning |
---|---|
FOREX_MERCHANT_NOT_SUPPORT_THIS_CURRENCY | This currency is not supported. |
ILLEGAL_SECURITY_PROFILE | This encryption method is not supported. |
success
{
"is_success": True,
"response": {
"amount": "0.10",
"currency": "HKD",
"exchange_rate": "0.881890",
"out_trade_id": "d2849e8140a6",
"payment_no": "2018081316331654230251111",
"status": "INIT",
"product_info": "Alipay QRCODE Pay",
"trade_time": "2018-08-13 16:33:16",
"finish_time": "2018-08-13 16:33:16",
"trade_type": "NATIVE",
"qrcode_url": "https://unitradeprod.alipay.com/exterfaceAssign.htm?...&qrcode_width=200&sign_type=RSA",
}
}
failed
{
"is_success": False,
"error": "FOREX_MERCHANT_NOT_SUPPORT_THIS_CURRENCY",
"error_message" : "This currency is not supported",
}
Check Payment Order ¶
Check Payment OrderGET/payment
- .Request Parameter:
Field | Type | Required | Description | Example Value |
---|---|---|---|---|
payment_no | string | N | Payment order No. | “2019062231224380479532988” |
out_trade_id | string | N | Merchant transaction No. | “2746847384112837273872” |
Note:
**You can check order information by payment_no or out_trade_id, which cannot be both null at the same time.
- .Response Data:
Field | Required | Description |
---|---|---|
is_success | Y | Whether the service request is successful. Optional values are True and False . |
response | N | Service response data. It is returned when is_success=True . |
error | N | Service error code. It is returned when is_success=False . For details, see Error Code below. |
error_message | N | Service error description. It is returned when is_success=False . |
When is_success=True
, response
contains the following fields:
Field | Required | Description |
---|---|---|
amount | Y | Amount of the payment order |
currency | Y | Currency of the payment order. For details, see currency code. |
exchange_rate | Y | Exchange rate |
out_trade_id | Y | Merchant transaction No. |
payment_no | Y | Payment order No. |
status | Y | Payment order status |
product_info | Y | Product information |
trade_time | Y | Time when transaction is created |
trade_type | Y | Payment method |
- Error Code:
Error Code | Meaning |
---|---|
PAYMENT_NOT_FOUND | Order not found |
ILLEGAL_SECURITY_PROFILE | This encryption method is not supported. |
success
{
"is_success": True,
"response": {
"amount": "0.02",
"currency": "HKD",
"exchange_rate": "0.881890",
"out_trade_id": "2746847384112837273872",
"payment_no": "2018071823332342210483065",
"status": "PAID",
"product_info": "Alipay App Pay",
"trade_time": "2018-07-18 23:33:23",
"trade_type": "APP",
}
}
failed
{
"is_success": False,
"error": "PAYMENT_NOT_FOUND",
"error_message" : "Order not found",
}
Check Exchange Rate ¶
Check Exchange RateGET/alipay/forex_rate
Note:
The reference exchange rate (target currency / CNY) is returned. The actual rate should be the live exchange rate when transaction occurs.
- Request Parameter
Field | Type | Required | Description | Example Value |
---|---|---|---|---|
currency | string | Y | Currency | “USD” |
- Response Data
Field | Required | Description |
---|---|---|
is_success | Y | Whether the service request is successful. Optional values are True and False . |
response | N | Service response data. It is returned when is_success=True . |
error | N | Service error code. It is returned when is_success=False . For details, see Error Code below. |
error_message | N | Service error description. It is returned when is_success=False . |
When is_success=True
, response
contains the following fields:
Field | Required | Description |
---|---|---|
currency | Y | Currency of the payment order. For details, see currency code. |
forex_rate | Y | Exchange rate |
- Error Code
Error Code | Meaning |
---|---|
CURRENCY_NOT_SUPPORT | This currency is not supported. |
ILLEGAL_SECURITY_PROFILE | This encryption method is not supported. |
success
{
"is_success": true,
"response": {
"currency": "USD",
"forex_rate": "0.1488471786017296042153520980"
}
}
failed
{
"is_success": False,
"error": "CURRENCY_NOT_SUPPORT",
"error_message" : "This currency is not supported",
}
Payment Notification ¶
Payment NotificationPOST/[notify_url]
After the customer pays successfully, HipoPay will send a POST request to the notify_url specified in the order information. If the successful response (‘success’) is not received, HipoPay will send the request for another 10 times at most at the interval of 1s / 2s / 4s / 8s / 60s / 60s / 60s / 600s / 600s / 1800s respectively until the successful response is received.
Note:
-
It is an asynchronous notification. A same notification might be sent to the merchant system for several times. The merchant system must be able to process repeated notification properly.
-
The best practices for dealing with such case: when a notification is received and processed, the enclosed payment data should be checked first to confirm whether the payment result has previously been processed or not. If so, return the processed result; if no, proceed with processing the result first before returning. Before checking the payment data, a transaction lock shall be used for concurrency to prevent data corruption caused by transaction race conditions.
- Fields in the notification:
Field | Required | Description |
---|---|---|
status | Y | PAID: payment successful. Note: it is notified only when payment is successful. |
trade_type | Y | Payment method |
exchange_rate | Y | Exchange rate adopted for settlement |
payment_no | Y | Payment order No. |
currency | Y | Pricing currency of the payment order. For details, see currency code. |
settle_currency | Y | Settlement currency of the payment order. For details, see currency code. |
amount | Y | Amount of the payment order |
trade_time | Y | Time when transaction is created |
finish_time | Y | Time when payment is completed |
pay_currency | Y | Payment currency. For details, see currency code. |
pay_amount | Y | Payment amount |
out_trade_id | Y | Merchant transaction No. |
Note:
If add response_version = 3.0 while request payment notify will add params below
Field | Description | For example | |
---|---|---|---|
pay_rate | rate between payment currency and price currency | ||
pay_rate_reversed | 1 / pay_rate | ||
bank_type | 银行类型 | ||
promotion_detail | activity_id | activity ID | 931386 |
name | promotion name | coupon-6 | |
amount | promotion amount | 1 | |
promotion_id | coupon ID | 109519 | |
scope | promotion scope | GLOBAL; SINGLE | |
type | promotion type | COUPON;DISCOUNT |
Public Key of SandBox ENV for callbackDownload
Public Key of Prod ENV for callbackDownload
Refund ¶
RefundPOST/payment_refund
- .Request Parameter
Field | Type | Required | Description | Example Value |
---|---|---|---|---|
payment_no | string | Y | Payment order No. | “201901021232211023” |
out_refund_id | string | Y | External refund order No. | “R201901021232213” |
refund_amount | string | N | Refund amount. If this parameter is transferred, multiple refunds can be initiated, but the total refund amount cannot exceed the order amount. If this parameter is not transferred, the full order amount will be refunded. | “8.88” |
- .Response Data
Field | Required | Description |
---|---|---|
is_success | Y | Whether the service request is successful. Optional values are True and False . |
response | N | Service response data. It is returned when is_success=True . |
error | N | Service error code. It is returned when is_success=False . For details, see Error Code below. |
error_message | N | Service error description. It is returned when is_success=False . |
When is_success=True
, response
contains the following fields:
Field | Required | Description |
---|---|---|
refund_no | Y | Refund order No. |
status | Y | Refund order status |
refund_amount | Y | Refund amount |
payment_no | Y | Payment order No. |
out_refund_id | Y | External refund order No. |
finish_time | N | Refund completion time (refund successful)/Refund form creation time (refund unsuccessful) |
- Error Code
Error Code | Meaning |
---|---|
REFUND_AMOUNT_INVALID | Refund amount is invalid. |
ILLEGAL_SECURITY_PROFILE | This encryption method is not supported. |
success
{
"is_success": true,
"response": {
"fail_message": "Settled Balance Not Enough",
"finish_time": "2021-12-23 16:42:34",
"out_refund_id": "R201901021232213",
"payment_no": "2637473637382",
"refund_amount": "8.88",
"refund_no": "2637473637452",
"result_code": "0011",
"status": "FAIL"
},
"return_message": "OK"
}
failed
{
"is_success": False,
"error": "REFUND_AMOUNT_INVALID",
"error_message" : "Refund amount is invalid",
}
Check Refund ¶
Check RefundGET/payment_refund
- Request Parameter
Field | Type | Required | Description | Example Value |
---|---|---|---|---|
refund_no | string | N | Refund order No. refund_no and out_refund_id cannot be both null at the same time. |
“20192637473637452” |
out_refund_id | string | N | External refund order No. out_refund_id and refund_no cannot be both null at the same time. |
“R2019263747363” |
- Response Data
Field | Required | Description |
---|---|---|
is_success | Y | Whether the service request is successful. Optional values are True and False . |
response | N | Service response data. It is returned when is_success=True . |
error | N | Service error code. It is returned when is_success=False . For details, see Error Code below. |
error_message | N | Service error description. It is returned when is_success=False . |
When is_success=True
, response
contains the following fields:
Field | Required | Description |
---|---|---|
refund_no | Y | Refund order No. |
out_refund_id | Y | External refund order No. |
status | Y | Refund order status |
refund_amount | Y | Refund amount |
payment_no | Y | Payment order No. |
finish_time | N | Refund completion time (refund successful)/Refund form creation time (refund unsuccessful) |
- Error Code
Error Code | Meaning |
---|---|
REFUND_NOT_FOUND | Refund order not found |
ILLEGAL_SECURITY_PROFILE | This encryption method is not supported. |
success
{
"is_success": true,
"response": {
"finish_time": "2021-12-23 19:22:14",
"out_refund_id": "R201637473637452",
"payment_no": "2637473637382",
"refund_amount": "8.88",
"refund_no": "2637473637452",
"result_code": "0000",
"status": "SUCCESS"
},
"return_message": "OK"
}
failed
{
"is_success": False,
"error": "REFUND_NOT_FOUND",
"error_message" : "Refund order not found",
}
Export Reconciliation Report ¶
Export Reconciliation ReportGET/download_bill
- Request Parameter
Specify the Version field in the header of this API to 3.0.
Field | Type | Required | Description | Example Value |
---|---|---|---|---|
merchant_no | string | Y | Merchant No. | HPXXXXX |
start_date | string | Y | Start time | 20190101 |
end_date | string | Y | End time | 20190301 |
- Response Data This API can query the records of the recent three months. A txt file will be returned.
- Format of the returnd data is as follows (slide left and right to view all fields):
Test: company's reconciliation report of 20190101 to 20190120
Transaction Type,Transaction Time,Order No.,External order No.,Credit,Debit,Balance,Transaction Amount,Exchange Rate Adopted for Settlement,Service Fee,Refund Amount,Refund Order,External Refund Order No.,Fee for Withdrawal,Converted Currency,Exchange Rate Adopted for Conversion,Amount After Conversion,Payment Channel
Collection via WeChat Pay,2019-01-02 10:55:10,`2019010210551024660612990,`13260056057_wechat_1546397710000,0.99 HKD,-,1.06 HKD,1.00 HKD,1,0.01 HKD,-,-,-,-,-,-,-,WECHATPAYCN
Collection via WeChat Pay,2019-01-02 11:07:05,`2019010211070452703917004,`13260056057_wechat_1546398424000,0.99 HKD,-,2.05 HKD,1.00 HKD,1,0.00 HKD,-,-,-,-,-,-,-,WECHATPAYCN
Refund,2019-01-04 10:50:34,`2019010410503295208356067,`,-,-0.99 HKD,1.06 HKD,-,-,-,1.00 HKD,`2019010211070452703917004,`13260056057_wechat_1546398424000,-,-,-,-,WECHATPAYCN
Currency Code
Currency | 3-Character Code |
---|---|
Chinese Yuan | CNY |
Great Britain Pound | GBP |
Hong Kong Dollar | HKD |
US Dollar | USD |
Japanese Yen | JPY |
Canadian Dollar | CAD |
Australian Dollar | AUD |
Euro | EUR |
New Zealand Dollar | NZD |
Korean Won | KRW |
Thai Baht | THB |
Payment Order Status
Status Code | Description |
---|---|
INIT | Payment order has been created |
PAID | Payment successful |
FAIL | Payment failed |
USERPAYING | Waiting for payment |
EXPIRED | Timeout |
Refund Status
Status Code | Description |
---|---|
SUCCESS | Refund successful |
PROCESSING | Processing |
FAIL | Refund failed |
Refund Code
code | message | Description |
---|---|---|
0000 | Refund Processing | |
0001 | Refund xxxxxxxx Already Exists. | |
0002 | payment xxxxxxxxxx Not Found. | |
0003 | Refund currency error. | |
0004 | Payment not paid yet. | |
0005 | Payment not credited yet. | |
0006 | Payment full refunded. | |
0007 | payment settle_forex rate is -0.1 | |
0008 | Payment refundable not enough. | |
0009 | refund amount must more than zero. | |
0010 | merchant has not HKD balance. | |
0011 | Settled Balance not enough. | |
0012 | Unsettled Balance not enough. | |
0013 | Refund xxxxx Invalid | |
0099 | SYSYTEM_ERROR | |
0101 | NOTENOUGH | merchant balance not enough for refunding |
0102 | USER_ACCOUNT_ABNORMAL | User account signed out |
0103 | SYSTEMERROR | API Errore |
0104 | BIZERR_NEED_RETRY | Need retry |
0105 | TRADE_OVERDUE | payment expeired |
0106 | ERROR | Channel Error |
0107 | INVALID_REQ_TOO_MUCH | invalid request too much |
0108 | INVALID_TRANSACTIONID | invalid transaction_id |
0109 | PARAM_ERROR | param error |
0110 | APPID_NOT_EXIST | appid not exist |
0111 | MCHID_NOT_EXIST | mchid not exist |
0112 | ORDERNOTEXIST | payment not exist |
0113 | REQUIRE_POST_METHOD | |
0114 | SIGNERROR | |
0115 | XML_FORMAT_ERROR | |
0116 | FREQUENCY_LIMITED | |
0117 | NOAUTH | |
0118 | CERT_ERROR | |
0119 | REFUND_FEE_MISMATCH | double request different amount |
0120 | INVALID_REQUEST | param error |
0121 | ORDER_NOT_READY | payment processing ,try later |
0199 | SYSYTEM_ERROR | wechatpay unknown error |
0201 | MERCHANT_BALANCE_NOT_ENOUGH | |
0202 | REFUNDMENT_VALID_DATE_EXCEED | |
0203 | SYSTEM_EXCEPTION | |
0204 | ILLEGAL_ARGUMENT | |
0205 | REPEATED_REFUNDMENT_REQUEST | |
0206 | RETURN_AMOUNT_EXCEED | |
0207 | CURRENCY_NOT_SAME | |
0208 | PURCHASE_TRADE_NOT_EXIST | |
0209 | TRADE_NOT_EXIST | |
0210 | TRADE_STATUS_ERROR | |
0211 | REFUND_AMT_RESTRICTION | |
0212 | BUYER_NOT_EXIST | |
0213 | REFUND_CHARGE_ERROR | |
0214 | INVALID_PARAMETER | |
0215 | REASON_TRADE_BEEN_FREEZEN | |
0216 | REQUEST_AMOUNT_EXCEED | |
0217 | ILLEGAL_SIGN | |
0218 | ILLEGAL_SERVICE | |
0219 | ILLEGAL_PARTNER | |
0220 | ILLEGAL_SIGN_TYPE | |
0221 | ILLEGAL_PARTNER_EXTERFACE | |
0222 | ILLEGAL_DYN_MD5_KEY | |
0223 | ILLEGAL_ENCRYPT | |
0224 | ILLEGAL_USER | |
0225 | ILLEGAL_EXTERFACE | |
0226 | ILLEGAL_AGENT | |
0227 | HAS_NO_PRIVILEGE | |
0228 | INVALID_CHARACTER_SET | |
0229 | SYSTEM_ERROR | |
0230 | SESSION_TIMEOUT | |
0231 | ILLEGAL_TARGET_SERVICE | |
0232 | ILLEGAL_ACCESS_SWITCH_SYSTEM | |
0233 | EXTERFACE_IS_CLOSED | |
0299 | SYSYTEM_ERROR | alipay unknow error |