Version: V1.0.3 - Last Updated:
This documentation is intended for: Technical architects, R&D engineers, and system operation engineers using the TetherU merchant self-service system. Through this document, merchants can understand TetherU's integration technology, product business, integration process, integration specifications and other information to facilitate merchants to successfully complete the integration work.
Gateway URL: /getway.html
Submit Method: POST
Parameter Name | Parameter Description | Required | Include in Signature | Parameter Notes |
---|---|---|---|---|
merchantid | Merchant ID | Yes | Yes | Platform assigned merchant number |
network | Network | Yes | Yes | Mainnet 1: mainnet, Test 2: test [For debugging, use 1 in production] |
orderid | Order ID | Yes | Yes | Unique merchant order ID, max 20 characters |
create_time | Submit Time | Yes | Yes | Unix timestamp: 1626373569 |
cashier | Return JSON (integer) | No | Yes | 1: Return JSON data, 2: Redirect to cashier |
notifyurl | Async Notification URL | Yes | Yes | Used for callback notification of order status (POST return data) |
amount | Order Amount (USD) | Yes | Yes | Keep 4 decimal places, no rounding |
productname | Product Name | No | Yes | Product description information |
sign | MD5 Signature | Yes | No | Please refer to signature algorithm |
Parameter Name | Parameter Description | Parameter Notes |
---|---|---|
status | Status Code | 1: Success, 0: Failed |
message | Return Message | Status description |
data | Return Data | JSON object containing order information |
data.qrcode | QR Code | Base64 encoded QR code image |
data.account_address | Payment Address | USDT receiving wallet address |
data.amount | Payment Amount | Actual USDT amount to be paid |
data.orderid | Merchant Order ID | Merchant submitted order ID |
data.platform_orderid | Platform Order ID | System generated unique order ID (starts with PYS) |
data.create_time | Creation Time | Order creation time |
data.time_out | Timeout | Order validity period (seconds) |
data.pay_code | Payment Type | 1: Ethereum ERC20, 2: Tron TRC20 |
data.cashier_url | Cashier URL | Cashier redirect link when cashier=2 |
POST /getway.html HTTP/1.1 Content-Type: application/x-www-form-urlencoded merchantid=1&network=1&orderid=TEST20230101000001&create_time=1626373569&cashier=1¬ifyurl=https://yourdomain.com/notify.php&amount=10.0000&productname=Test Product&sign=A1B2C3D4E5F6G7H8I9J0
When request parameter cashier=1, returns JSON and QR code example:
{ "status": 1, "message": "Order created successfully", "data": { "qrcode": "data:image/png;base64", "account_address": "TFpS9NJ4Djm29RTmax3VonXL8HumgrC4zw", "amount": "10.69", "platform_orderid": "PYS2025032450595", "orderid": "202503201546059331", "create_time": "2025-03-20 15:46:05", "time_out": 1800, "pay_code": "2" } }
When request parameter cashier=2, returns cashier URL example:
{ "status": 1, "message": "Order created successfully", "data": { "cashier_url": "http://loc.weepay.com:8888/index/index/cashier.html?osn=202503201544321601", "amount": "10.78", "orderid": "202503201544321601", "create_time": "2025-03-20 15:44:32", "time_out": 1800, "pay_code": "2" } }
Response parameter description:
Submit Method: POST
Parameter Name | Parameter Description | Required | Include in Signature | Parameter Notes |
---|---|---|---|---|
code | Status Code | Yes | No | 1: Success, 0: Failed |
msg | Message | Yes | No | Return message description |
data | Data Object | Yes | Yes | JSON object containing order information - Non-empty data fields participate in signature |
data.merchantid | Merchant ID | Yes | Yes | Platform assigned merchant number |
data.orderid | Platform Order ID | Yes | Yes | System generated unique order ID (starts with PYS) |
data.out_trade_id | Merchant Order ID | Yes | Yes | Original order ID submitted by merchant |
data.amount | Order Amount | Yes | Yes | Payment amount in USDT |
data.poundage | Service Fee | Yes | Yes | Service fee amount in USDT |
data.status | Order Status | Yes | Yes | 0: Unpaid, 1: Processing, 2: Paid, 3: Order timeout |
sign | MD5 Signature | Yes | No | Please refer to signature algorithm |
{ "code": 1, "msg": "success", "data": { "merchantid": "1", "orderid": "PYS2025032450595", "out_trade_id": "202503241012158778", "amount": "10.7300", "poundage": "0.1073", "status": 2, "sign": "63FB0B1B2340AB0E0801FE0F249012E4" } }
Submit Method: POST
URL: /query.html
Parameter Name | Parameter Description | Required | Include in Signature | Parameter Notes |
---|---|---|---|---|
merchantid | Merchant ID | Yes | Yes | Platform assigned merchant ID |
orderid | Merchant Order ID | Yes | Yes | Merchant system order ID |
query_type | Query Type | No | Yes | payment: Payment order, payout: Payout order, empty: Auto detect |
sign | MD5 Signature | Yes | No | Please refer to signature algorithm |
Parameter Name | Parameter Description | Parameter Notes |
---|---|---|
orderid | Platform Order ID | System generated order number |
out_trade_id | Merchant Order ID | Order ID submitted by merchant |
amount | Order Amount | Unit: USDT |
time_end | Payment Success Time | Format: yyyy-mm-dd HH:ii:ss |
trade_state | Payment Status | Payment order: SUCCESS: Payment successful, NOTPAY: Unpaid Payout order: SUCCESS: Payout successful, NOTPAY: Unpaid, PAYING: Payout processing, PAY_FAILED: Payout failed |
order_type | Order Type | payment: Payment order, payout: Payout order |
status_text | Status Description | Chinese description of order status |
POST /query.html HTTP/1.1 Content-Type: application/x-www-form-urlencoded merchantid=1&orderid=TEST20230101000001&query_type=payment&sign=A1B2C3D4E5F6G7H8I9J0
{ "code": 1, "msg": "Payment order query successful", "data": { "orderid": "PAY202301010001", "out_trade_id": "TEST20230101000001", "amount": "10.0000", "time_end": "2023-01-01 12:05:30", "trade_state": "SUCCESS", "order_type": "payment", "status_text": "Paid", "sign": "B2C3D4E5F6G7H8I9J0K1" } }
The system will automatically determine the order type and return the order_type field to identify the order type in the query result. If you need to query a specific type of order, you can add the query_type parameter to the request parameters.
Submit Method: POST
URL: /payout.html
Parameter Name | Parameter Description | Required | Include in Signature | Parameter Notes |
---|---|---|---|---|
merchantid | Merchant ID | Yes | Yes | Platform assigned merchant number |
network | Network | Yes | Yes | Mainnet 1: mainnet, Test 2: ropsten |
orderid | Order ID | Yes | Yes | Unique merchant order ID, max 20 characters |
create_time | Submit Time | Yes | Yes | Unix timestamp: 1626373569 |
pay_type | Currency Selection (integer) | Yes | Yes | Currency selection USDT: 1 |
notifyurl | Server Notification | Yes | Yes | Server return address (POST return data) |
withdraw_query_url | Payout Double Confirmation URL | If double confirmation is enabled, this parameter is required | Yes | Merchant needs double confirmation, if not needed then this parameter can be omitted. |
pay_code | Payment Type (integer) | Yes | Yes | 1: Ethereum ERC20, 2: Tron TRC20 |
amount | Order Amount | Yes | Yes | Keep 4 decimal places, no rounding |
address | Payout Address | Yes | Yes | USDT receiving address (ERC20 or TRC20) |
sign | MD5 Signature | Yes | No | Please refer to signature algorithm |
version | API Version | No | Yes | '1.0.0' |
Depending on whether merchants need double confirmation, if not needed then this parameter can be omitted.
If double confirmation is needed, then a callback URL address needs to be provided. When merchants submit payout order API, this address will be called back with merchant order ID, payout amount, and payout address.
{ "orderId": "1234567890", "amount": "10.0000", "address": "TYour_TRC20_Address_Here" }
Corresponding return value:
{ "code": 10001, "message": "Order has been maliciously modified." } or { "code": 10000, "message": "Order verification passed." }
If order verification passes, payout operation continues. Otherwise, returns order maliciously modified and payout order will not be processed by the platform.
Double confirmation callback address needs to be provided by merchants and must be publicly accessible.
Double confirmation callback address needs to support POST requests and return JSON data.
Double confirmation callback address needs to support cross-domain requests.
Double confirmation callback address needs to support HTTPS requests.
Parameter Name | Parameter Description | Parameter Notes |
---|---|---|
code | Result Code | success: Success, 0: Failed |
msg | Result Message | API return message description |
data | Return Data | JSON object containing order details |
data.orderid | Merchant Order ID | Original order ID submitted by merchant |
data.platform_orderid | Platform Order ID | System generated platform internal order ID (starts with DFS) |
data.amount | Order Amount | Payout amount in USDT |
data.poundage | Service Fee | Payout service fee in USDT |
data.address | Payout Address | USDT receiving address |
data.create_time | Creation Time | Order creation time, format: yyyy-mm-dd HH:ii:ss |
data.network | Network | 1: mainnet, 2: testnet |
data.pay_code | Payment Type | ERC20: Ethereum, TRC20: Tron |
data.pay_type | Currency | USDT: USDT token |
data.status | Order Status | 0: Unpaid, 1: Processing, 2: Paid, 3: Order timeout, 4: Failed, 5: Rejected |
data.status_desc | Status Description | Text description of order status |
POST /payout.html HTTP/1.1 Content-Type: application/x-www-form-urlencoded merchantid=1&network=1&orderid=202503281035406411&create_time=1626373569&pay_type=1¬ifyurl=https://yourdomain.com/notify.php&pay_code=2&amount=10.0000&address=TYour_TRC20_Address_Here&sign=A1B2C3D4E5F6G7H8I9J0&version=1.0.0
{ "code": "success", "msg": "Payout order submitted successfully", "data": { "orderid": "202503281035406411", "platform_orderid": "DFS2025032885781", "amount": "10.0000", "poundage": "1.00", "address": "TYour_TRC20_Address_Here", "create_time": "2025-03-28 10:35:40", "network": "1", "pay_code": "TRC20", "pay_type": "USDT", "status": 1, "status_desc": "Payout processing" } }
Submit Method: POST
Parameter Name | Parameter Description | Required | Include in Signature | Parameter Notes |
---|---|---|---|---|
merchantid | Merchant ID | Yes | Yes | Platform assigned merchant number |
orderid | System Order ID | Yes | Yes | System generated unique order ID (starts with DF) |
out_trade_id | Merchant Order ID | Yes | Yes | Original order ID submitted by merchant |
amount | Order Amount | Yes | Yes | Payout amount in USDT |
status | Order Status | Yes | Yes | 0: Unpaid, 1: Processing, 2: Paid, 3: Order timeout, 4: Failed, 5: Rejected |
time | Notification Time | Yes | Yes | Unix timestamp |
sign | MD5 Signature | Yes | No | Please refer to signature algorithm |
{ "code": 1, "msg": "success", "data": { "merchantid": 1, "orderid": "DFS2025032846917", "out_trade_id": "202503281034025239", "amount": "10.0000", "transaction_id": "", "status": 2, "time": 1743944210, "remark": "Paid", "sign": "DE987378BAC0AC03976A79AD17060310" } }
Submit Method: POST
URL: /balance.html
Parameter Name | Parameter Description | Required | Include in Signature | Parameter Notes |
---|---|---|---|---|
merchantid | Merchant ID | Yes | Yes | Platform assigned merchant ID |
timestamp | Timestamp | Yes | Yes | Unix timestamp, valid for 5 minutes |
sign | MD5 Signature | Yes | No | Please refer to signature algorithm |
Parameter Name | Parameter Description | Parameter Notes |
---|---|---|
code | Status Code | 1: Success, 0: Failed |
msg | Return Message | Status description |
data | Return Data | JSON object containing balance information |
data.merchantid | Merchant ID | Unique merchant identifier |
data.username | Merchant Name | Merchant account name |
data.balance | Account Balance | Merchant current available balance in USDT |
data.currency | Currency Type | Balance currency type, fixed as USDT |
data.query_time | Query Time | Format: yyyy-mm-dd HH:ii:ss |
POST /balance.html HTTP/1.1 Content-Type: application/x-www-form-urlencoded merchantid=1×tamp=1711603200&sign=A1B2C3D4E5F6G7H8I9J0
{ "code": 1, "msg": "Balance query successful", "data": { "merchantid": "1", "username": "merchant_demo", "balance": "1000.0000", "currency": "USDT", "query_time": "2025-03-28 10:35:40" } }
The general steps for signature generation are as follows:
Step 1: Set all sent or received data as array M, sort the non-empty parameter values in array M by parameter name ASCII code from small to large (dictionary order), and concatenate them into a string stringA using URL key-value pair format (i.e., key1+value1+key2+value2...).
Step 2: Append the application private_key to the end of stringA to get stringSignTemp string, perform MD5 operation on stringSignTemp, and convert all characters in the resulting string to uppercase to get the sign value signValue.
Original parameters:
{ "amount": "300.0000", "callbackurl": "http://www.baidu.com/callbackurl.html", "cashier": "2", "create_time": "1626376050", "default_currency": "cny", "merchantid": "2", "network": "1", "notifyurl": "http://www.baidu.com/notifyurl.html", "orderid": "out2021071587481", "pay_code": "1", "pay_type": "1", "productname": "Test Product", "version": "1.0.0" }
Private key:
K0d8F434vUjVc88vxkDxmC0z8cj0UZ
Step 1: Sort by parameter name ASCII code from small to large
amount300.0000callbackurlhttp://www.baidu.com/callbackurl.htmlcashier2create_time1626376050default_currencycnymerchantid2network1notifyurlhttp://www.baidu.com/notifyurl.htmlorderidout2021071587481pay_code1pay_type1productnameTest Productversion1.0.0
Step 2: Append private key
stringSignTemp="amount300.0000callbackurlhttp://www.baidu.com/callbackurl.htmlcashier2create_time1626376050default_currencycnymerchantid2network1notifyurlhttp://www.baidu.com/notifyurl.htmlorderidout2021071587481pay_code1pay_type1productnameTest Productversion1.0.0K0d8F434vUjVc88vxkDxmC0z8cj0UZ"
Step 3: Generate MD5 and convert to uppercase
sign=MD5(stringSignTemp).toUpperCase()
import java.security.MessageDigest; import java.util.*; public class WeePaySignUtil { private static final String CHARSET = "UTF-8"; /** * Generate signature * @param params Request parameters * @param privateKey Merchant private key * @return Signature result */ public static String generateSign(Mapparams, String privateKey) { try { // 1. Filter empty values and sign parameter Map filteredParams = new TreeMap<>(); for (Map.Entry entry : params.entrySet()) { if (entry.getValue() != null && !entry.getValue().isEmpty() && !"sign".equals(entry.getKey())) { filteredParams.put(entry.getKey(), entry.getValue()); } } // 2. Sort by parameter name ASCII code from small to large StringBuilder stringA = new StringBuilder(); for (Map.Entry entry : filteredParams.entrySet()) { stringA.append(entry.getKey()).append(entry.getValue()); } // 3. Append private key String stringSignTemp = stringA.toString() + privateKey; // 4. MD5 encryption and convert to uppercase return md5(stringSignTemp).toUpperCase(); } catch (Exception e) { throw new RuntimeException("Signature generation failed", e); } } /** * MD5 encryption * @param text Text to be encrypted * @return Encryption result */ private static String md5(String text) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] bytes = md.digest(text.getBytes(CHARSET)); return bytesToHex(bytes); } /** * Convert byte array to hex string */ private static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } /** * Usage example */ public static void main(String[] args) { // Configuration String merchantId = "1"; String privateKey = "K0d8F434vUjVc88vxkDxmC0z8cj0UZ"; // Build request parameters Map params = new HashMap<>(); params.put("merchantid", merchantId); params.put("network", "1"); params.put("orderid", "TEST" + System.currentTimeMillis()); params.put("create_time", String.valueOf(System.currentTimeMillis() / 1000)); params.put("cashier", "1"); params.put("notifyurl", "https://yourdomain.com/notify.php"); params.put("amount", "10.0000"); params.put("productname", "Test Product"); // Generate signature String sign = generateSign(params, privateKey); params.put("sign", sign); // Print request parameters System.out.println("Request parameters:"); for (Map.Entry entry : params.entrySet()) { System.out.println(entry.getKey() + " = " + entry.getValue()); } // Send HTTP request example try { String response = sendHttpRequest(params); System.out.println("Response result: " + response); } catch (Exception e) { e.printStackTrace(); } } /** * Send HTTP request example */ private static String sendHttpRequest(Map params) throws Exception { // Here use HttpClient to send request, need to add related dependencies // It is recommended to use OkHttp or Apache HttpClient for actual projects StringBuilder urlParams = new StringBuilder(); for (Map.Entry entry : params.entrySet()) { if (urlParams.length() > 0) { urlParams.append("&"); } urlParams.append(entry.getKey()).append("=") .append(java.net.URLEncoder.encode(entry.getValue(), CHARSET)); } // This is just an example, actual projects need to implement according to specific circumstances return "HTTP request implementation code"; } }
/** * Generate signature * * @param array $data Request parameters * @param string $privateKey Merchant private key * @return array Contains signature and signature string */ function makeSign($data, $privateKey) { // Remove empty values and signature parameters from array $para_filter = array(); foreach ($data as $key => $val) { if ($key == "sign" || $val === "" || $val === null) { continue; } $para_filter[$key] = $val; } // Sort by key name in dictionary order ksort($para_filter); reset($para_filter); // Concatenate string $str_sign = ""; foreach ($para_filter as $key => $val) { $str_sign .= $key . $val; } // Add private key $str_sign .= $privateKey; // MD5 encryption and convert to uppercase $sign = strtoupper(md5($str_sign)); return [ 'sign' => $sign, 'str_sign' => $str_sign ]; }
// Configuration information $config = [ 'merchant_id' => 1, 'private_key' => 'your_private_key', 'notify_url' => 'https://yourdomain.com/notify.php', 'gateway_url' => 'https://payment-domain/getway.html', ]; // Assemble order parameters $timestamp = time(); $orderid = date('YmdHis') . mt_rand(1000, 9999); $params = [ 'merchantid' => $config['merchant_id'], 'network' => 1, 'orderid' => $orderid, 'create_time' => $timestamp, 'cashier' => 1, 'notifyurl' => $config['notify_url'], 'amount' => '10.0000', 'productname' => 'Test Product', ]; // Generate signature $sign_data = makeSign($params, $config['private_key']); $params['sign'] = $sign_data['sign']; // Send HTTP request $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $config['gateway_url']); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); // Handle response $result = json_decode($response, true); print_r($result);
// Get all request parameters $data = $_POST; // Get merchant information (should be retrieved from database in actual application) $private_key = 'your_private_key'; // Verify signature $sign = $data['sign']; unset($data['sign']); // Signature verification $sign_data = makeSign($data, $private_key); if ($sign_data['sign'] === $sign) { // Verification successful, process order logic // ... // Return success identifier echo 'success'; } else { // Signature verification failed echo 'fail'; }
// Configuration information $config = [ 'merchant_id' => 1, 'private_key' => 'your_private_key', 'balance_url' => 'https://payment-domain/balance.html', ]; // Assemble parameters $timestamp = time(); $params = [ 'merchantid' => $config['merchant_id'], 'timestamp' => $timestamp, ]; // Generate signature $sign_data = makeSign($params, $config['private_key']); $params['sign'] = $sign_data['sign']; // Send HTTP request $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $config['balance_url']); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); // Handle response $result = json_decode($response, true); if ($result['code'] == 1) { echo "Balance query successful: " . $result['data']['balance'] . " " . $result['data']['currency'] . "\n"; } else { echo "Query failed: " . $result['msg'] . "\n"; } print_r($result);