Ⅰ、TopPay API Reference
Welcome to the TopPay API documentation page, which is aimed at technical personnel with development capabilities. Java language can directly refer to the Java code example on the right. If you have any questions, able to pass Telegram Messenger 👨💻 Cindy contact us for a consultation.
Ⅱ、Introduction
RequestMode
HTTP POST
ContentType
application/json
Sign
The shaded area on the right is the signature tool class
import com.google.gson.JsonObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* <p>
* TopPay RSA signatureToolClass
* </p>
*
* @author TopPay
*/
public class TopPayRequestUtil {
/**
* VERIFY SIGNATURE
* @param params
* @return
*/
public static boolean verifySign(JsonObject params, String publickey) throws InvalidKeySpecException, NoSuchAlgorithmException {
String platSign = params.remove("platSign").getAsString(); // sign
List<String> paramNameList = new ArrayList<>(params.keySet());
Collections.sort(paramNameList);
StringBuilder stringBuilder = new StringBuilder();
for (String name : paramNameList) {
stringBuilder.append(params.get(name).getAsString());
}
System.out.println("keys:" + stringBuilder);
String decryptSign = publicDecrypt(platSign, getPublicKey(publickey));
System.out.println("decryptSign:" + decryptSign);
return stringBuilder.toString().equals(decryptSign);
}
/**
* PRIVATE KEY ENCRYPTION
* @param data
* @param privateKey
* @return
*/
public static String privateEncrypt(String data, RSAPrivateKey privateKey){
try{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64String(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), privateKey.getModulus().bitLength()));
}catch(Exception e){
throw new RuntimeException("ENCRYPTED STRING[" + data + "]Encountered an exception", e);
}
}
/**
* PUBLIC KEY DECRYPTION
* @param data
* @param publicKey
* @return
*/
public static String publicDecrypt(String data, RSAPublicKey publicKey){
try{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), "UTF-8");
}catch(Exception e){
throw new RuntimeException("When attempting to encrypt the string [" + data + "], an exception occurred.", e);
}
}
/**
* GET PRIVATE KEY
* @param privateKey KEY STRING (BASE 64 ENCODED)
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//Obtain the private key object through the Key command encoded by PKCS 8
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
return key;
}
/**
* GET PUBLIC KEY
* @param publicKey KEY STRING (BASE 64 ENCODED)
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//Obtain the public key object through the Key command encoded by X509
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
}
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
int maxBlock = 0;
if(opmode == Cipher.DECRYPT_MODE){
maxBlock = keySize / 8;
}else{
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try{
while(datas.length > offSet){
if(datas.length-offSet > maxBlock){
buff = cipher.doFinal(datas, offSet, maxBlock);
}else{
buff = cipher.doFinal(datas, offSet, datas.length-offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
}catch(Exception e){
throw new RuntimeException("An exception occurred while encrypting or decrypting data with a threshold of [" + maxBlock + "].", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
public static String doPost(String url,String json) throws IOException {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
StringEntity s = new StringEntity(json);
s.setContentEncoding("UTF-8");
s.setContentType("application/json");//SENDING JSON DATA NEEDS TO SET CONTENT TYPE
post.setEntity(s);
HttpResponse res = client.execute(post);
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
return EntityUtils.toString(res.getEntity());// RETURN JSON FORMAT
}
return null;
}
}
How to Sign:
RSA BASED SIGNATURE VERIFICATION METHOD
After sorting the keys of all non-empty parameters according to ASCII, take the parameter value (excluding Key) and splicing
Use the RAS algorithm to calculate the string and calculate the signature string.
Parameter example
Param | Type |
---|---|
merchantCode | S820211021094748000001 |
orderNum | T1642592278863 |
payMoney | 150.60 |
notifyUrl | your notify ur |
dateTime | 2022-01-01 10:55:00 |
expiryPeriod | 1440 |
How to get data for sign
Example
First sort according to ASCII according to the parameter Key, and encrypt the string after sorting.
StrA = 2022-01-01 10:55:[email protected] notify
urlT1642593166888150.60082122965511Test Pay
How to calculate signature
Use the key pair you configured in the backend of the Top Pay merchant, and use your private key to encrypt and calculate RSA (Str A) to get the final signature string
sign = IMLn23c4orM+7pZhHoRmbjrol4X33jeAqFxbZuQ+pnznBIGhb6Ail3qQPmKwcuhNCt536nmldpbWI72
k1lDxd0zZ95ZHElcNzwTFHFKtd8063uy6rFaxaW6DQ47t4U/95dpGfHAZe0GiIFAQ6xQquaoLINyQa4QqL+cpB
JFEg1dyW6GYLFSdJnx7ycQvFYllmOpGZmdPLny62GvrCWvkiIARUsmc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQ
bYDxZ5WBuU1GZeiJjPuzSxvzWP6VoQBsfpwTI5kdJs6aQCekGO2/YScD+tGgrm2J89Pc/axPcb1xZzsi5SxpWh
feabQ\u003d\u003d
Ⅲ、Configure merchant public key information
1.Bind google verification code
Log in to the merchant background->PERSONAL CENTER->Security information, use Google Authenticator to scan the QR code on the page to bind your account
2.Rsa key pair generation address
POST http://pay.hehebo.com:15082/index-rsa.jsp
3.Configure public key
Click Payment Configuration->API Configuration, fill in your public key information and save. The configuration is complete
4.Merchant platform url
https://tl-merchant.toppayment.com/
Ⅳ、Pay Api
1.Code example
The code example is for reference only. For specific parameter descriptions, please refer to Request Parameter Description
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;
import java.util.TreeMap;
public class TopPayDemo {
// test account
private static final String MCH_CODE = "S820211021094748000001"; //merchant code
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 payUrl = "https://tl-openapi.toppay.asia/gateway/prepaidOrder";
private static final String cashUrl = "https://tl-openapi.toppay.asia/gateway/cash";
private static final String payNotify = "your notify url";
private static final String cashNotify = "your notify url";
public static void main(String[] args) throws Exception {
pay();
}
private static void pay() throws Exception {
Map<String, String> requestParams = new TreeMap<>();
requestParams.put("merchantCode", MCH_CODE);
requestParams.put("orderType", "0"); // orderType(0-BAHT transaction)
requestParams.put("method", "BankTransfer"); // When using online banking, pass in the corresponding bank abbreviation, and pass in qr Pay when using a QR code, or not
requestParams.put("transAccNo", "1234567890"); // When using online banking, the card number paid by the user must be transmitted, and the real card number must be passed, otherwise the transaction will fail
requestParams.put("orderNum", "T1642592278863"); // merchant order number
requestParams.put("payMoney", "150.12"); // order amount
requestParams.put("notifyUrl", payNotify);// callback address
requestParams.put("dateTime", "20220101235959");// timestamp format yyyyMMddHHmmss
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);
String postJson = new Gson().toJson(requestParams);
System.out.println("Post Json Params:" + postJson);
String responseJson = TopPayRequestUtil.doPost(payUrl, postJson); // post request
System.out.println("Response Msg:" + responseJson);
}
}
<?php
// platform public key, from Secret key config
$platPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiaKBgQCcEUIvQ/5L+SWbHOeR8VFeZvLbUk7V7OeEAQlQwIVLSZMTef3KtsOKKAsUYPf/aAcKRzZZXECODsPQiDPcdZvM/rFkgrFWkR7lPjTj5SiPxGaiK2Z2sne7A8aDF7fV/D7lfmEwNdZ7FWKVEB84/81BHnlGUwb5HpRTISG+boSO6wIDAQAB';
// mchchant private key
$mchPrivateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMigm7rtWnTeNagwFzGTH+Uw1ypbiy7VhIoFJbgSYSSHdCaXWdT/l2+2fQlEYgAETVZ/IXB29MCnrf3O0dwRFXiipIbsm5zyqSLiS6cKXe8zN1/PlQWUbEt5wyWm0GADB/4bV6eu6gA7sGXmjQqrzfKZkcie3aK7+7ry1NFxTI51AgMBAAECgYEAklqXQAVlt1tiSQ7L3J425jp6u6uMHN4lkYmvuleuBbfKQ1yla3wIPLYjAF+iHeEFidOz0Rb19JRdmIkHDkJoJg2W27LvO6RdUwzgRnsuA3OuNz97w08B3aXXbPmB91nTFjKSlUsbh3IQWP71noxW+iKn844EW5hC5Gvn4L3quAECQQDrz1r0VKIbBSBB2aLuz1XyD/TBT2aRhvOKf0XtTRiQhNjtJxoQmvNbbhvUwj8an7HyCuihAbdbrC2ymFFyOSDZAkEA2c4Yudi48C6COrroi1cWgPlEFeGJXP/V1k5loZ1n2vstYAGPhAB4wUnFBLDvMqaBzWJt7MRkiazT8KnBQCDY/QJAMXpNlEyZwt+deBOpO0BnwSWV7mWxmMFfImU4D+WITPbC7aexsWBBxaJh1o93XCe715RwYTAR//stj3akSDoyaQJAa4FKuxC51/Nc3Fg9R+modeiTLqmv/3NXvPvdNjRXesLX1rduex0wfVdII9ShfEKrdxDKaT9W0NyzD+r6NAkCkQJBAMAnTgPYf0f7rh417GdoP7R7Nwi8KBKwPHlmfRukibOQlKt9xjqpsKJwglLn8pcnXbYbswXIdqzuBvIGAe3OWNg=';
// merchent ID from idntask, from User info
$merchantCode = 'YOUR_MERCHANT_CODE_HERE';
//Order Type(0-BAHT TRANSACTION)
$orderType = '0';
// Merchant system unique order number
$orderNum = 'TEST1231231231';
// pay money
$payMoney = '15.12';
// url for callback
$notifyUrl = 'http://example.com/callback';
// order time
$dateTime = date("YmdHis",time());
$params = array(
'merchantCode' => $merchantCode,
'orderType' => $orderType,
'orderNum' => $orderNum,
'payMoney' => $payMoney,
'notifyUrl' => $notifyUrl,
'dateTime' => $dateTime,
);
ksort($params);
$params_str = '';
foreach ($params as $key => $val) {
$params_str = $params_str . $val;
}
$sign = pivate_key_encrypt($params_str, $mchPrivateKey);
$params['sign'] = $sign;
$params_string = json_encode($params);
$url = 'https://tl-openapi.toppay.asia/gateway/prepaidOrder';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $params_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($params_string))
);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
//execute post
$request = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 200)
{
$result = json_decode($request, true);
echo "platRespCode :". $result['platRespCode'] . "\n";
echo "platRespMessage :". $result['platRespMessage'] . "\n";
echo "platOrderNum :". $result['platOrderNum'] . "\n";
echo "orderNum :". $result['orderNum'] . "\n";
echo "payMoney :". $result['payMoney'] . "\n";
echo "payFee :". $result['payFee'] . "\n";
echo "platSign :". $result['platSign'] . "\n";
$decryptStr = public_key_decrypt($result['platSign'], $platPublicKey);
echo "decryptStr :". $decryptStr . "\n";
}
else {
echo $httpCode;
}
function pivate_key_encrypt($data, $pivate_key)
{
$pivate_key = '-----BEGIN PRIVATE KEY-----'."\n".$pivate_key."\n".'-----END PRIVATE KEY-----';
$pi_key = openssl_pkey_get_private($pivate_key);
$crypto = '';
foreach (str_split($data, 117) as $chunk) {
openssl_private_encrypt($chunk, $encryptData, $pi_key);
$crypto .= $encryptData;
}
return base64_encode($crypto);
}
function public_key_decrypt($data, $public_key)
{
$public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
$data = base64_decode($data);
$pu_key = openssl_pkey_get_public($public_key);
$crypto = '';
foreach (str_split($data, 128) as $chunk) {
openssl_public_decrypt($chunk, $decryptData, $pu_key);
$crypto .= $decryptData;
}
return $crypto;
}
2.Request address
We provide two modes of collection and order placement.
Cashier mode(Mode 1, you can use our cashier page):
POST https://tl-openapi.toppay.asia/gateway/prepaidOrder
API mode(Mode 2 directly requests the API to obtain the returned information, and you can choose according to your own needs):
POST https://tl-openapi.toppay.asia/gateway/payment
Note: Do not fill in Chinese in all the parameters! ! !
3.Request param
Cashier mode(Mode 1):
Param | Type | Required | Describe | Example |
---|---|---|---|---|
merchantCode | string(32) | Y | merchant ID,Get it in merchant background | S820211021094748000001 |
orderType | string(10) | Y | order type | 0-Fiat currency transaction |
orderNum | string(32) | Y | merchant order number | 10000001 |
transAccNo | string(16) | N | The user's payment card number (real) is valid when using online bank transfer | 1234567890 |
payMoney | string(10) | Y | payment amount(only two decimal) | 20.54 |
notifyUrl | string(100) | Y | asynchronous notification address of successful order payment (used to receive notification after successful order transaction) | https://host:port/notifyUrl |
dateTime | string(32) | Y | timestamp format:yyyyMMddHHmmss | 20190101235959 |
method | string(32) | N | pay type 1.If you need to specify a payment method, you can choose one of the payment methods in the example on the right; 2.If you do not specify a payment method, you do not need to pass this parameter (only in cashier mode), all supported payment methods are displayed by default. |
BankTransfer (online bank transfer) qrPay(qr code scanning) |
sign | string(255) | Y | sign | fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+XxO2jo92dyjKHFU9/4hNECilMooOcH |
Api mode((Mode 2):
Param | Type | Required | Describe | Example |
---|---|---|---|---|
merchantCode | string(32) | Y | merchant ID,Get it in merchant background | S820211021094748000001 |
orderType | string(10) | Y | order type | 0-Fiat currency transaction |
orderNum | string(32) | Y | merchant order number | 10000001 |
payMoney | string(10) | Y | payment amount(only two decimal) | 20.54 |
notifyUrl | string(100) | Y | asynchronous notification address of successful order payment (used to receive notification after successful order transaction) | https://host:port/notifyUrl |
dateTime | string(32) | Y | timestamp format:yyyyMMddHHmmss | 20190101235959 |
method | string(32) | Y | pay type | BankTransfer(online bank transfer) qrPay(qr code scanning) |
transAccNo | string(16) | N | User payment card number (true) must be passed when using online banking transfer | 1234567890 |
sign | string(255) | Y | sign | fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+XxO2jo92dyjKHFU9/4hNECilMooOcH |
4.Request example
Mode 1,(method and transAccNo can not be passed, the page to be redirected is different)
{
"merchantCode": "S820211021094748000001",
"orderType": "0",
"orderNum": "T1642593166888",
"transAccNo": "1234567890",
"payMoney": "150.12",
"method": "BankTransfer",
"notifyUrl": "your notify url",
"dateTime": "2022-01-01 10:55:00",
"sign": "fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+Xxd1yc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQbYDxZ5WBuU1GZeiJ"
}
Mode 2,(method must pass,When using qr Pay, you can not pass the transAccNo, and you must pass the transAccNo when using online banking transfer)
{
"merchantCode": "S820211021094748000001",
"orderType": "0",
"orderNum": "T1642593166888",
"transAccNo": "1234567890",
"payMoney": "150.12",
"method": "BankTransfer",
"notifyUrl": "your notify url",
"dateTime": "2022-01-01 10:55:00",
"sign": "fnbSOvY83pr8hXg+FdNNYi2ubQUGNv/qGYc4TjRl+Xxd1yc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQbYDxZ5WBuU1GZeiJ"
}
5.Response param
Param | Type | Required | Describe | Example |
---|---|---|---|---|
platRespCode | String | Y | whether the business is successful | FAIL/SUCCESS |
platRespMessage | String | Y | interface response information prompt | Request Transaction Success |
platOrderNum | String | Y | platform order number | PI1453242857400963072 |
payMoney | string | Y | payment amount | 150.32 |
orderNum | String | Y | merchant order number | 23645782 |
url | String | N | cash register link | Cashier mode(mode 1),Returned when 'platRespCode' is SUCCESS |
payData | String | N | response parameters | Api mode(mode 2),Returned when 'platRespCode' is SUCCESS |
6.Response example
Cashier mode
{
"platOrderNum": "PRE1483771634191044608",
"payMoney": "150.32",
"orderNum": "T1642593166888",
"platRespCode": "SUCCESS",
"platRespMessage": "Request Transaction Success",
"url": "https://tl-openapi.toppay.asia/gateway/order/PRE1483771634191044608"
}
Api mode(When using qrPay, payData returns the QR code serial number; when using online banking transfer, it returns the receiving card number)
{
"payData": "123456789",
"platOrderNum": "PRE1483771634191044608",
"payMoney": "150.32",
"orderNum": "T1642593166888",
"platRespCode": "SUCCESS",
"method": "BankTransfer",
"bankName": "KBANK",
"platRespMessage": "Request Transaction Success"
}
Example of a failure response message
{
"platRespCode": "FAIL",
"platRespMessage": "Error message"
}
7.Pay api callback notify
When verifying the signature, use the Platform Public Key
provided in Merchant Background-Receipt and Payment Configuration-API Configuration
to decrypt! ! !
When verifying the signature, verify the signature according to the actual callback parameters, do not use fixed parameters
After accepting the asynchronous notification, you need to respond with SUCCESS
string, without quotation marks, not in Json format.
Otherwise, TopPay will continue to initiate 5 notifications.
import com.google.gson.JsonObject;
public class TopPayNotify {
// test account
private static final String MCH_CODE = "S820211021094748000001"; // merchant number
private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2JoMfFqLsSJjAiCahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB"; // platform public key
public static void main(String[] args) throws Exception {
JsonObject notifyBody = new jsonObject();
boolean verifyResult = TopPayRequestUtil.verifySign(notifyBody,PLAT_PUBLIC_KEY);
if (verifyResult) {
// ... signature verification passed,do something
} else {
// ... signature verification error
}
}
}
<?php
$res = json_decode(file_get_contents('php://input'), true);
$platSign = $res['platSign'];
unset($res['platSign']);
$public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFJ/AmUV4Z8udG8aOBUt/kEwc/DbxF5Gtfw6Y00NHQ4Pz2X2x9IxjUZxn2dnFxmrmhqKNlfwXOqyejhBzi0pSHyGoI4XP9IEfZGO6YkSb9DCY1ZxX8fDl2G+tPCbWYTVO4JutFmzTWgk1Uhhu6L9dlOMUHvZf3/6czA/a9C7azXwIDAQAB';
$decryptSign = public_key_decrypt($platSign, $public_key);
$params = $res;
ksort($params);
$params_str = '';
foreach ($params as $key => $val) {
$params_str = $params_str . $val;
}
if($params_str == $decryptSign) {
if($res['code'] == '00') {
echo 'success';
}
else {
echo 'fail';
}
}
else {
echo 'fail';
}
function public_key_decrypt($data, $public_key)
{
$public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
$data = base64_decode($data);
$pu_key = openssl_pkey_get_public($public_key);
$crypto = '';
foreach (str_split($data, 128) as $chunk) {
openssl_public_decrypt($chunk, $decryptData, $pu_key);
$crypto .= $decryptData;
}
return $crypto;
}
Param | Remark | Example |
---|---|---|
code | response code | 00 |
msg | response message | SUCCESS |
method | pay type | Online bank transfer: the abbreviation of the bank when placing an order QR code scanning: qrPay |
status | pay result | INIT_ORDER:order initialization NO_PAY:unpaid SUCCESS:payment successful PAY_CANCEL:revoke PAY_ERROR:payment failed |
platOrderNum | platform order number | BK_1563278763273 |
orderNum | merchant order number | T1231511321515 |
payMoney | payment amount | 100000 |
payFee | merchant fee | 500 |
transAccNo | User payment card number | 123456 It will only be returned if the method is online banking transfer |
platSign | platform signature | ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs |
8.Pay api callback notify example
{
"code": "00",
"msg": "SUCCESS",
"status": "SUCCESS",
"method": "BankTransfer",
"platOrderNum": "PRE1483771634191044608",
"orderNum": "T1642593166888",
"payMoney": "150",
"payFee": "16",
"transAccNo": "*****1236",
"platSign": "ja6R8eukQY9jc8zrhtf34654ungj7u8sdgdfjfs"
}
Ⅴ、Cash api
1.Code example
The code example is for reference only, please refer to request parameter description
for specific parameter description
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.util.Map;
import java.util.TreeMap;
public class TopPayDemo {
private static final String MCH_CODE = "S820211021094748000001"; // merchant code
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_CODE);
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
}
}
}
<?php
// platform public key, from Secret key config
$platPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiaKBgQCcEUIvQ/5L+SWbHOeR8VFeZvLbUk7V7OeEAQlQwIVLSZMTef3KtsOKKAsUYPf/aAcKRzZZXECODsPQiDPcdZvM/rFkgrFWkR7lPjTj5SiPxGaiK2Z2sne7A8aDF7fV/D7lfmEwNdZ7FWKVEB84/81BHnlGUwb5HpRTISG+boSO6wIDAQAB';
// mchchant private key
$mchPrivateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMigm7rtWnTeNagwFzGTH+Uw1ypbiy7VhIoFJbgSYSSHdCaXWdT/l2+2fQlEYgAETVZ/IXB29MCnrf3O0dwRFXiipIbsm5zyqSLiS6cKXe8zN1/PlQWUbEt5wyWm0GADB/4bV6eu6gA7sGXmjQqrzfKZkcie3aK7+7ry1NFxTI51AgMBAAECgYEAklqXQAVlt1tiSQ7L3J425jp6u6uMHN4lkYmvuleuBbfKQ1yla3wIPLYjAF+iHeEFidOz0Rb19JRdmIkHDkJoJg2W27LvO6RdUwzgRnsuA3OuNz97w08B3aXXbPmB91nTFjKSlUsbh3IQWP71noxW+iKn844EW5hC5Gvn4L3quAECQQDrz1r0VKIbBSBB2aLuz1XyD/TBT2aRhvOKf0XtTRiQhNjtJxoQmvNbbhvUwj8an7HyCuihAbdbrC2ymFFyOSDZAkEA2c4Yudi48C6COrroi1cWgPlEFeGJXP/V1k5loZ1n2vstYAGPhAB4wUnFBLDvMqaBzWJt7MRkiazT8KnBQCDY/QJAMXpNlEyZwt+deBOpO0BnwSWV7mWxmMFfImU4D+WITPbC7aexsWBBxaJh1o93XCe715RwYTAR//stj3akSDoyaQJAa4FKuxC51/Nc3Fg9R+modeiTLqmv/3NXvPvdNjRXesLX1rduex0wfVdII9ShfEKrdxDKaT9W0NyzD+r6NAkCkQJBAMAnTgPYf0f7rh417GdoP7R7Nwi8KBKwPHlmfRukibOQlKt9xjqpsKJwglLn8pcnXbYbswXIdqzuBvIGAe3OWNg=';
// merchent ID from idntask, from User info
$merchantCode = 'YOUR_MERCHANT_CODE_HERE';
// Merchant system unique order number
$orderNum = 'T'.date("YmdHis",time());
// Payment method
$method = 'Disbursement';
//order type(0-baht transaction)
$orderType = '0';
// withdraw money
$money = '20000';
// fee type
$feeType = '1';
// timestamp format yyyyMMddHHmmss
$dateTime = date("YmdHis",time());
// customer bank card number
$number = '123456';
// bank code(for details refer to the bottom of the document)
$bankCode = '014';
// Display name on bank confirmation display
$name = 'จางซาน';
// Customer's mobile number
$mobile = '082112345678';
// Customer's email address
$email = '[email protected]';
// The virtual account description
$description = 'คำอธิบาย';
// url for callback
$notifyUrl = 'http://example.com/callback';
$params = array(
'merchantCode' => $merchantCode,
'orderType' => $orderType,
'method' => $method,
'orderNum' => $orderNum,
'money' => $money,
'feeType' => $feeType,
'dateTime' => $dateTime,
'number' => $number,
'bankCode' => $bankCode,
'name' => $name,
'mobile' => $mobile,
'email' => $email,
'notifyUrl' => $notifyUrl,
'description' => $description
);
ksort($params);
$params_str = '';
foreach ($params as $key => $val) {
$params_str = $params_str . $val;
}
$sign = pivate_key_encrypt($params_str, $mchPrivateKey);
$params['sign'] = $sign;
//After the original text participates in the signature, it needs to use unicode encoding. For the encoding method, refer to Item 9 in this section. Thai Unicode
$params['name'] = unicode_encode($name);
$params['description'] = unicode_encode($description);
$params_string = json_encode($params);
$url = 'https://tl-openapi.toppay.asia/gateway/prepaidOrder';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $params_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($params_string))
);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
//execute post
$request = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 200)
{
$result = json_decode($request, true);
echo "platRespCode :". $result['platRespCode'] . "\n";
echo "platRespMessage :". $result['platRespMessage'] . "\n";
echo "platOrderNum :". $result['platOrderNum'] . "\n";
echo "orderNum :". $result['orderNum'] . "\n";
echo "status :". $result['status'] . "\n";
echo "statusMsg :". $result['statusMsg'] . "\n";
echo "money :". $result['money'] . "\n";
echo "fee :". $result['fee'] . "\n";
echo "feeType :". $result['feeType'] . "\n";
echo "bankCode :". $result['bankCode'] . "\n";
echo "number :". $result['number'] . "\n";
echo "name :". $result['name'] . "\n";
echo "description :". $result['description'] . "\n";
echo "platSign :". $result['platSign'] . "\n";
$decryptStr = public_key_decrypt($result['platSign'], $platPublicKey);
echo "decryptStr :". $decryptStr . "\n";
}
else {
echo $httpCode;
}
function pivate_key_encrypt($data, $pivate_key)
{
$pivate_key = '-----BEGIN PRIVATE KEY-----'."\n".$pivate_key."\n".'-----END PRIVATE KEY-----';
$pi_key = openssl_pkey_get_private($pivate_key);
$crypto = '';
foreach (str_split($data, 117) as $chunk) {
openssl_private_encrypt($chunk, $encryptData, $pi_key);
$crypto .= $encryptData;
}
return base64_encode($crypto);
}
function public_key_decrypt($data, $public_key)
{
$public_key = '-----BEGIN PUBLIC KEY-----'."\n".$public_key."\n".'-----END PUBLIC KEY-----';
$data = base64_decode($data);
$pu_key = openssl_pkey_get_public($public_key);
$crypto = '';
foreach (str_split($data, 128) as $chunk) {
openssl_public_decrypt($chunk, $decryptData, $pu_key);
$crypto .= $decryptData;
}
return $crypto;
}
2.Request address
POST https://tl-openapi.toppay.asia/gateway/cash
Note: Do not fill in Chinese in all the parameters! ! !
3.Request param
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,1:extra handling fee |
bankCode | string | Y | bank number | 014(REFER TO APPENDIX II BANKCODE SECTION) |
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+ePvTFhiRrARcZKBcRG0l89rqisPIuZQStYqBIwSMPaqvqbc3dFevgS9jt |
4.Request example
{
"merchantCode": "S820211021094748000001",
"orderType": "0",
"method": "Disbursement",
"orderNum": "186888188666",
"money": "50000",
"feeType": "1",
"bankCode": "014",
"number": "2021071209403321313122",
"name": "test cash name",
"mobile": "082122965511",
"email": "[email protected]",
"notifyUrl": "your notify url",
"dateTime": "2021-07-12 09:41:00",
"description": "test cash",
"sign": "Yg+ePvTFhiRrARcZKBcRG0l89rqisPIuZQStYqBIwSMPaqwH77qRXI1J+jElOBpa"
}
5.Response param
Param | Type | Required | Remark | Example |
---|---|---|---|---|
platRespCode | String | Y | code | FAIL:fail\SUCCESS:success |
platRespMessage | String | Y | message | successful request |
platOrderNum | String | Y | platform order number | PI1453242857400963072 |
orderNum | String | Y | merchant order number | 23645782 |
status | int | Y | order status | 0-pending 1-processing 2-successful payment 4-payment failed 5-bank payment |
statusMsg | String | Y | order status information | Apply |
money | string | Y | payment amount | 150000 |
fee | String | Y | fee amount | 12.25 |
feeType | String | Y | fee type | 0:order deduction,1:extra handling fee |
bankCode | String | N | bank number | 014(Refer to appendix ii bankcode section) |
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 |
6.Response example
{
"platRespCode": "SUCCESS",
"platRespMessage": "Request success",
"platOrderNum": "W0620220119174331000001",
"orderNum": "186888188666",
"status": 0,
"statusMsg": "Apply",
"money": "50000",
"fee": "7",
"feeType": "0",
"bankCode": "014",
"number": "2021071209403321313122",
"name": "test cash name",
"description": "test cash",
"platSign": "E5uNF7B9NXyhtlRo2I7/KVHN4Sbz0c3VbwCLpH3vjUpv6Cai+bmJA/Q8dVE2RJRe1+dsbzg=="
}
7.Cash api callback notify
When verifying the signature, use the Platform Public Key
provided in Merchant Background-Receipt and Payment Configuration-API Configuration
to decrypt! ! !
After accepting the asynchronous notification, you need to respond with SUCCESS
string, without quotation marks, not in Json format.
Otherwise, TopPay will continue to initiate 5 notifications.
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 | 500 |
name | name | Neo |
number | bank number | 45649849659456 |
bankCode | bank code | 014 @see BankCode |
status | order status | 0-Todo 1-Doing 2-Success 4-Failed 5-Bank doing |
statusMsg | order status message | Payout Success |
description | description | description |
platSign | sign | ja6R8eukQY9jc8... |
8. Cash api callback notify example
{
"platOrderNum": "W0620220119174331000001",
"orderNum": "186888188666",
"money": "50000",
"fee": "7",
"feeType": "0",
"name": "test cash name",
"number": "2021071209403321313122",
"bankCode": "014",
"status": "2",
"statusMsg": "SUCCESS",
"description": "test cash",
"platSign": "LGEpz2LjbZ6Iyvn+zLc/+t26AaH0aEhHVD62lSCdo6XIkAg86AUncCvmym62wVoE3r2+dHnv27qi/01UQDcqFK8DYioRCcydYSjB4QRVezG3fcZlhWrACmWGacnXkE7p5zChL7pK5h0HuBhbo1zKt4FunQR6QMmcBVfv7YfB3W0"
}
9.Thai unicode
The order is paid in Thai Baht. If name
and description
are in Thai, they need to be converted to Unicode when placing the order
Please pay 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;
}
}
<?php
function unicode_encode($str) {
$unicode = '';
for ($i = 0; $i < mb_strlen($str); $i++) {
$char = mb_substr($str, $i, 1);
$unicode .= '\u' . str_pad(dechex(mb_ord($char)), 4, '0', STR_PAD_LEFT);
}
return $unicode;
}
$str = 'จ้าเหมยแซ่หลี่';
$unicode = unicode_encode($str);
echo $unicode;
?>
Ⅵ、Order query
1.Order query
import com.google.gson.JsonObject;
public class OrderQuery {
// test account
private static final String MCH_CODE = "S820211021094748000001"; // merchant code
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 orderQueryUrl = "https://tl-openapi.toppay.asia/gateway/query";
public static void main(String[] args) throws Exception {
// pay
query();
}
private static void query() throws Exception {
Map<String, String> requestParams = new TreeMap<>();
requestParams.put("merchantCode", MCH_CODE);
requestParams.put("queryType", "CASH_QUERY"); // payment channel
requestParams.put("orderNum", "186888188666"); // merchant order number
requestParams.put("platOrderNum", "PRE186888188666"); // platform order number
requestParams.put("dateTime", "20220101105500");// timestamp format yyyyMMddHHmmss
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);
String postJson = new Gson().toJson(requestParams);
System.out.println("Post Json Params:" + postJson);
String responseJson = TopPayRequestUtil.doPost(orderQueryUrl, postJson); // send post json request
System.out.println("Response Msg:" + responseJson);
}
}
Request address
POST https://tl-openapi.toppay.asia/gateway/query
Note: Both the merchant order number and the platform order number must be passed one of them, or they can be passed at the same time
Request param
param | required | description | example |
---|---|---|---|
merchantCode | Y | merchant code | S820190712000002 |
queryType | Y | query type | pay:ORDER_QUERY.cash:CASH_QUERY |
orderNum | Y | merchant order number | T1231511321515 |
platOrderNum | Y | platform order number | PRE1234567890 |
dateTime | Y | timestamp | 20191018105510 yyyy-MM-dd HH:mm:ss |
sign | Y | RSA sign | ja6R8eukQ... |
merchantCode(format reference-sample pay order query response message)
Param | Type | Required | description | Example |
---|---|---|---|---|
success | BOOLEAN | Y | response status | true/false |
code | int | Y | response code | 1000 means success, others are failure |
message | String | Y | response message | return specific response information |
data | Json | Y | response parameters | The following parameters are all returned in data, or null if failed |
msg | String | Y | order status details | Request Transaction Success |
platOrderNum | String | Y | platform order number | PI1453242857400963072 |
amount | String | Y | payment amount | 1500 |
fee | string | Y | fee amount | 5 |
orderNum | String | Y | merchant order number | 23645782 |
inAddress | string | N | Account address | TLRx8JXsDidC7PYVLmeD6Bhk5k5CUjnPV3 |
sendAddress | String | N | Billing address | TLRx8JcxDidC7PYVLmeD6Bhk5k5CUjnPV3 |
platRespCode | String | Y | request business status | FAIL:fail\SUCCESS:succeed |
platRespMessage | String | Y | respond to information prompts | Request Transaction Success |
status | int/String | Y | order status | cash status returns string type, payment status returns int type |
2.Request example
{
"dateTime": "20220101105500",
"merchantCode": "S820211021094748000001",
"orderNum": "T1642593166888",
"platOrderNum": "PRE1642593166888",
"queryType": "ORDER_QUERY",
"sign": "lGw1OJcuUL0MGaIq44U2u2bFM5dalJJuT/G6mQWbIBT9dmVAJaLwR125emPDXYYSdnOtNxja86A2VJJLf40BCg2HevHolebvt2ay3ukCQaUhwNkIGz4KF0Ud+XMUA36LoFTWZbDYv9y8vgCnWxwZFKj7ePrfLxc+TA7jpqv65lQ\u003d"
}
3.Order query example for pay api
{
"success": true,
"code": 1000,
"message": "Success",
"data": {
"msg": "Payment Success",
"platOrderNum": "PRE1483771634191044608",
"amount": "150",
"fee": "16",
"orderNum": "T1642593166888",
"platRespCode": "SUCCESS",
"platRespMessage": "success",
"status": "SUCCESS"
}
}
4.Order query example for cash api
{
"success": true,
"code": 1000,
"message": "Success",
"data": {
"msg": "test cash",
"platOrderNum": "W0620220119174331000001",
"amount": "125",
"fee": "7",
"orderNum": "186888188666",
"platRespCode": "SUCCESS",
"platRespMessage": "success",
"status": 2
}
}
Ⅶ、Bank account query
1. Bank account query
import com.google.gson.JsonObject;
public class OrderQuery {
// test account
private static final String MCH_CODE = "S820211021094748000001"; // merchant code
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 orderQueryUrl = "https://tl-openapi.toppay.asia/gateway/query";
public static void main(String[] args) throws Exception {
query();
}
private static void query() throws Exception {
Map<String, String> requestParams = new TreeMap<>();
requestParams.put("merchantCode", MCH_CODE);
requestParams.put("currency", "THB"); // currency(THB)
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);
String postJson = new Gson().toJson(requestParams);
System.out.println("Post Json Params:" + postJson);
String responseJson = TopPayRequestUtil.doPost(orderQueryUrl, postJson); // send post json request
System.out.println("Response Msg:" + responseJson);
}
}
Request address
POST https://tl-openapi.toppay.asia/gateway/interface/getBalance
Request param
param | required | description | example |
---|---|---|---|
merchantCode | Y | merchant code | S820211021094748000001 |
currency | N | currency | THB(If no currency is passed, the balance of all currency units will be displayed) |
sign | Y | RSA sign | ja6R8eukQ... |
Request param
param | type | required | description | example |
---|---|---|---|---|
success | BOOLEAN | Y | response status | true/false |
code | int | Y | response code | 1000 means success, others are failure |
message | String | Y | response message | return specific response information |
data | Json | Y | data | The following parameters are all returned in data, or null if failed |
mchId | String | Y | merchant code | S8202110212321300001 |
mchName | String | Y | merchant name | test |
mchNo | String | Y | merchant number | TP123 |
currency | string | Y | currency | IDR |
balance | String | Y | balance | 1000.00 |
freeze | String | Y | freeze | 10.00 |
waitingSettleAmount | String | Y | waiting settle amount | 200.00 |
freezeWaitingSettleAmount | String | Y | freeze waiting settle amount | 100.00 |
totalAmount | String | Y | total amount(balance+freeze+waiting settle amount +freeze waiting settle amount) | 20000.00 |
2.Request example
{
"merchantCode": "S8202110212321300001",
"currency": "THB",
"sign": "X/o+IQUzLJqYe9Feid9Uww72mJGOvhJSJEIfo1EUChrZyVZnzGHtd61QhOqRmXCtAwk7V7k="
}
3.Response example
{
"success": true,
"code": 1000,
"message": "SUCCESS",
"data": [
{
"mchId": "S82022091232130000001",
"mchName": "test",
"mchNo": "test",
"country": "THAILAND",
"currency": "THB",
"balance": "1000000.01",
"freeze": "10.00",
"waitingSettleAmount": "10.00",
"freezeWaitingSettleAmount": "20.00",
"totalAmount": "1000040.01"
}
]
}
Ⅷ、Append
1. Pay business
a. Status param
Field | Remark |
---|---|
INIT_ORDER | The order has just been initialized |
NO_PAY | The order has not been paid |
SUCCESS | The order has been paid successfully |
PAY_CANCEL | The order has been canceled |
PAY_ERROR | The order has failed to be paid |
2. Cash business
a. Status param
Field | Remark |
---|---|
0 | Todo |
1 | Accepted |
2 | Success |
4 | Failed |
5 | Bank doing |
b. BankCode param
Bank Abbreviation | Bank Name | Bank Code |
---|---|---|
KBANK | Kasikorn Bank Plc. | 001 |
BBL | Bangkok Bank Plc. | 003 |
KTB | Krung Thai Bank | 004 |
ABN | ABN Amro Bank N.V. | 005 |
TTB | TMBThanachart | 007 |
SCB | Siam Commercial Bank | 010 |
UOB | UOB Bank Plc. | 016 |
BAY | Bank of Ayudhya / Krungsri | 017 |
CIMB | CIMB Thai Bank Public Company Limited | 018 |
LHBANK | Land and Houses Bank Public Company Limited | 020 |
GSB | Government Savings Bank | 022 |
KKP | Kiatnakin Phatra Bank Public Company Limited | 023 |
CITI | Citibank N.A. | 024 |
GHB | Government Housing Bank | 025 |
BAAC | Bank for Agriculture and Agricultural Cooperatives | 026 |
MHCB | Mizuho Corporate Bank Limited | 027 |
IBANK | Islamic Bank of Thailand | 028 |
TISCO | TISCO Bank Plc. | 029 |