THB Cash Api
# Code Example
- The code example is for reference only, please refer to
request parameter description
for specific parameter description
TopPayRequestUtil Click to obtain code examples
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.util.Map;
import java.util.TreeMap;
public class TopCashDemo {
//MCH_ID: Merchant ID
//1.Please log in to the merchant backend
//2.Click on personal center > personal information
//3.Get Merchant ID in Basic Information
private static final String MCH_ID = "S820211021094748000001";
private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB"; // platform public key
private static final String MCH_PRIVATE_KEY = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAJU8gKFKD0luIYx7X8+JRdCIE0UDBctS6LjXxWLEv/EO7jDBTid6zYP1KmNgpd2DAWWtBFBSQ+gcNwVZZSBHJiSDqVvvJVs2FEbeBvfdv4X93+IYRAXksBasSW5Tpdshbo82pVL4V7wuKCuFLk9UxBHbpQjWAbfyF66RmwIbZD71AgMBAAECgYBjPe7UU2nDDSfmQg0++CyjNjqKRC5QPfxhH6w1uF1kMueXKJWOj42n2RutJpJmsj31nY8m0u4xpsG4HvCu/GGSFhhKZCHLvzp41oY2ubYj9nuFNU//81LycQjulWo2y0UUBY0k2piEt+SwPaiUNbT6nMxNMjlnjRe2okp/3rw+KQJBANG3YlZWoVbCEqzy64bJJLxiPsCA5ErGB0NzRGitq44xkhqGtR8ZZQyVz40pruNa58d73O2xyJSy5+fmZGn4E+sCQQC2LBnguj0CSCKub0mPDcunTTz9V79VXBBZdlB1/YGmRUx2s4sQrJNZS7rL4EqBQ3maIRnG+s+AXCSTfsYrV6CfAkEAxugnVfpelhoGepEAgNuggyivmgfl/2Gpm/jk5l/qOjib+ZrQiQmeBPzGWX4yiSM8eMDrP2sC8r5pJFMp5DRONwJBAJ4n4XuSFJ9jgwCPy3vvzSv9SYLk6E6yM9uHdUlKgoGYzk6Lh6M9QFuY/J49plFdBDiEnj16yCU3WeXXfTJpzB8CQQDMNMR/rIOTE9xGybS3mlQbt22AUnO6XhupWcckEKW4nPGxATwYBQzCY3i/9FTGN0vA+9ZPC2cwHtNxI2kXf3Vp"; // merchant private key
private static final String cashUrl = "https://tl-openapi.toppay.asia/gateway/cash";
private static final String cashNotify = "http://host:port/notify";
public static void main(String[] args) throws Exception {
cash();
}
private static void cash() throws Exception {
Map<String, String> requestParams = new TreeMap<>();
requestParams.put("merchantCode", MCH_ID);
requestParams.put("orderNum", "186888188666"); // Merchant order number
requestParams.put("method", "Disbursement"); // Payment method (disbursement by default)
requestParams.put("orderType", "0"); // Order Type(0-baht transaction)
requestParams.put("money", "125.12"); // Order amount, supports two decimal places
requestParams.put("feeType", "0"); // fee type
requestParams.put("dateTime", "20200101235959");// timestamp format yyyyMMddHHmmss
requestParams.put("number", "2021071209403321313122"); // Customer bank card number
requestParams.put("bankCode", "001"); // Bank code: refer to Appendix I pay
//Name The original text participates in the signature, but Unicode encoding is required when calling the API
requestParams.put("name", "จางซาน"); // customer name
requestParams.put("mobile", "082122965511"); // customer phone,Can not pass
requestParams.put("email", "[email protected]"); // customer mail,Can not pass
//The original text of description participates in the signature, but Unicode encoding is required when calling the API
requestParams.put("description", "คำอธิบาย"); // description
requestParams.put("notifyUrl", cashNotify); // callback address
StringBuilder stringBuilder = new StringBuilder();
for (String key : requestParams.keySet()) {
stringBuilder.append(requestParams.get(key)); // stitching parameters
}
String keyStr = stringBuilder.toString(); // get the string to be encrypted
System.out.println("keyStr:" + keyStr);
String signedStr = TopPayRequestUtil.privateEncrypt(keyStr, TopPayRequestUtil.getPrivateKey(MCH_PRIVATE_KEY)); // private key encryption
requestParams.put("sign", signedStr);
//After the signature is completed, encode the name and description UnicodeUtil sample code reference Item 9 of this section Thai Unicode
requestParams.put("name", UnicodeUtil.toUnicode("จางซาน", true)); // customer name
requestParams.put("description", UnicodeUtil.toUnicode("คำอธิบาย", true)); // description
String postJson = new Gson().toJson(requestParams);
System.out.println("Post Json Params:" + postJson);
String responseJson = TopPayRequestUtil.doPost(cashUrl, postJson); // send post json request
System.out.println("Response Msg:" + responseJson);
boolean pass = TopPayRequestUtil.verifySign(new Gson().fromJson(responseJson, JsonObject.class), PLAT_PUBLIC_KEY); // signature verification
if (pass) {
// ... signature verification passed,execute normal business logic
} else {
// ... signature verification error
}
}
}
# Request Address
- Request method: POST
- Request address: https://tl-openapi.toppay.asia/gateway/cash
# Request param
Note: Do not fill in Chinese in all the parameters! ! !
Param | Type | Required | Remark | Example |
---|---|---|---|---|
merchantCode | string | Y | merchant ID,Get it in Merchant Platform-Personal Center-Personal Information | S820211021094748000001 |
orderType | string(10) | Y | order Type | 0-baht transaction |
method | string(10) | Y | payment method | Disbursement is passed by default |
orderNum | string | Y | merchant order number | 10000001 |
money | string | Y | payment amount | 150.12(supports two decimal places) |
feeType | String | Y | fee type | 0: deducted from the payment amount(Amount received = order amount - fee) 1: extra handling fee(Amount received = order amount) |
bankCode | String | Y | bank number | Click to view supported bank codes |
number | String | Y | customer bank card number | 12312431241 |
name | String | Y | Customer name | Jack |
mobile | String | N | customer phone | 1234567890 |
String | N | customer mail | [email protected] | |
notifyUrl | string | Y | callback address | https://123123.com |
dateTime | string | Y | timestamp format:yyyyMMddHHmmss | 20200101235959 |
description | string | Y | return by request parameter | pai |
sign | string | Y | Sign | Yg+ePvTFhiRrARcZKBcRG0l8 ... |
# Request example
{
"merchantCode": "S820211021094748000001",
"orderType": "0",
"method": "Disbursement",
"orderNum": "186888188666",
"money": "100.00",
"feeType": "1",
"bankCode": "001",
"number": "2021071209403321313122",
"name": "test cash name",
"mobile": "082122965511",
"email": "[email protected]",
"notifyUrl": "your notify url",
"dateTime": "20220101235959",
"description": "test cash",
"sign": "Yg+ePvTFhiRrARcZKBcRG0l89rqisPIuZQStYqBIwSMPaqwH77qRXI1J+jElOBpa"
}
# Response param
Param | Type | Required | Remark | Example |
---|---|---|---|---|
platRespCode | String | Y | code | FAIL:fail\SUCCESS:success |
platRespMessage | String | Y | Message | SUCCESS |
platOrderNum | String | Y | Platform order number | PI1453242857400963072 |
orderNum | String | Y | merchant order number | 23645782 |
status | Int | Y | order status | Click to view the order status description |
statusMsg | String | Y | order status information | Apply |
money | string | Y | payment amount | 100.00 |
fee | String | Y | fee amount | 10.00 |
feeType | String | Y | fee type | 0:order deduction 1:extra handling fee |
bankCode | String | N | bank number | Click to view supported bank codes |
number | String | Y | customer bank card number | 12312431241 |
name | String | Y | customer name | Jack |
description | String | Y | return by request parameter | pay |
platSign | String | Y | Sign | PI1453242857400963072 |
# Response example
{
"platRespCode": "SUCCESS",
"platRespMessage": "Request success",
"platOrderNum": "W0620220119174331000001",
"orderNum": "186888188666",
"status": 0,
"statusMsg": "Apply",
"money": "100.00",
"fee": "10.00",
"feeType": "0",
"bankCode": "001",
"number": "2021071209403321313122",
"name": "test cash name",
"description": "test cash",
"platSign": "E5uNF7B9NXyhtlRo2I7/KVHN4Sbz0c3VbwCLpH3vjUpv6Cai+bmJA/Q8dVE2RJRe1+dsbzg=="
}
# Cash api callback notify
- When verifying the signature, use the
platform public key
provided inMerchant Background-Receipt and Payment Configuration-API Configuration
to decrypt! ! ! - When verifying the signature, the actual callback parameters shall prevail. Do not verify the fixed parameters
- The final status of the order is subject to the status of the notification! ! !
- After TopPay results are notified asynchronously, you need to respond with the
SUCCESS
string, otherwise TopPay will continue to send 5 notifications to the downstream.
# Notify Params
Param | Remark | Example |
---|---|---|
platOrderNum | platform order number | BK_1563278763273 |
orderNum | merchant order number | T1231511321515 |
money | amount | 100000 |
feeType | fee type | 0:deduction in order, 1:deduction out order |
fee | fee | 10.00 |
name | name | Neo |
number | bank number | 45649849659456 |
bankCode | bank code | Click to view supported bank codes |
status | order status | Click to view the order status description |
statusMsg | order status message | Payout Success |
description | description | description |
platSign | sign | ja6R8eukQY9jc8... |
# Cash api callback notify example
{
"platOrderNum": "W0620220119174331000001",
"orderNum": "186888188666",
"money": "100.00",
"fee": "10.00",
"feeType": "0",
"name": "test cash name",
"number": "2021071209403321313122",
"bankCode": "001",
"status": "2",
"statusMsg": "SUCCESS",
"description": "test cash",
"platSign": "LGEpz2LjbZ6Iyvn+zLc/+t26AaH0aEhHVD62lSCdo6XIkAg86AUncCvmym62wVoE3r2+dHnv27qi/01UQDcqFK8DYioRCcydYSjB4QRVezG3fcZlhWrACmWGacnXkE7p5zChL7pK5h0HuBhbo1zKt4FunQR6QMmcBVfv7YfB3W0"
}
# Thai unicode
When placing an order in French currency (Thai Baht), name
and description
will need to be converted to Unicode when placing an order.
requires attention! When signing parameters, please use the original Thai text to participate in the signature, otherwise the signature verification will fail! ! !
import org.apache.commons.lang3.StringUtils;
/**
* unicode tools
*
*/
public class UnicodeUtil {
public static void main(String[] args) {
String str = "ข้อความต้นฉบับ";
System.out.println("raw string:" + str);
String unicodeStr = toUnicode(str, true);
System.out.println("converted unicode string:" + unicodeStr);
String originalStr = toString(unicodeStr);
System.out.println("convert back to original string:" + originalStr);
}
/**
* converts a string to a unicode encoded string
*
* @param originalText original text to be converted
* @param isSkipAscii Whether to skip ASCII characters (only visible characters are skipped)
* @return converted unicode
*/
public static String toUnicode(String originalText, boolean isSkipAscii) {
if (StringUtils.isEmpty(originalText)) {
return originalText;
}
final int len = originalText.length();
final StringBuilder unicode = new StringBuilder(originalText.length() * 6);
char c;
for (int i = 0; i < len; i++) {
c = originalText.charAt(i);
if (isSkipAscii && isAsciiPrintable(c)) {
unicode.append(c);
} else {
unicode.append(toUnicodeHex(c));
}
}
return unicode.toString();
}
/**
* unicode convert string
*
* @param unicode original text to be converted
* @return converted string
*/
public static String toString(String unicode) {
if (StringUtils.isBlank(unicode)) {
return unicode;
}
final int len = unicode.length();
StringBuilder sb = new StringBuilder(len);
int i;
int pos = 0;
while ((i = StringUtils.indexOfIgnoreCase(unicode, "\\u", pos)) != -1) {
sb.append(unicode, pos, i);//write the part before the unicode character
pos = i;
if (i + 5 < len) {
char c;
try {
c = (char) Integer.parseInt(unicode.substring(i + 2, i + 6), 16);
sb.append(c);
pos = i + 6;//skip entire unicode characters
} catch (NumberFormatException e) {
//illegal unicode character skip
sb.append(unicode, pos, i + 2);//Write "\\u"
pos = i + 2;
}
} else {
//non unicode character end
break;
}
}
if (pos < len) {
sb.append(unicode, pos, len);
}
return sb.toString();
}
/**
* Whether it is a visible ASCII character, the visible character is between 32~126
*
* @param ch character to be checked
* @return whether it is a visible ascii character
*/
public static boolean isAsciiPrintable(char ch) {
return ch >= 32 && ch < 127;
}
/**
* convert char to unicode
*
* @param ch char to be converted
* @return converted unicode
*/
public static String toUnicodeHex(char ch) {
String hex = Integer.toHexString(ch);
if (hex.length() < 4) {
hex = "0" + hex;
}
return "\\u" + hex;
}
}