中文 English

TetherU USDT Payment API Documentation

Version: V1.0.3 - Last Updated:

Table of Contents

1. API Documentation Introduction

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.

2. Gateway Integration

Gateway URL: /getway.html

3. Unified Order API

3.1 API Description

Submit Method: POST

3.2 Request Parameters

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

3.3 Response Parameters

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

3.4 Request Example

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

3.5 Response Example

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:

4. Asynchronous Notification

Submit Method: POST

When receiving server point-to-point communication, output "success" on the page (without quotes, lowercase letters), otherwise point-to-point notification will be sent 3 times repeatedly.

4.1 Notification Parameters

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

4.2 Notification Example

{
    "code": 1,
    "msg": "success",
    "data": {
        "merchantid": "1",
        "orderid": "PYS2025032450595",
        "out_trade_id": "202503241012158778",
        "amount": "10.7300",
        "poundage": "0.1073",
        "status": 2,
        "sign": "63FB0B1B2340AB0E0801FE0F249012E4"
    }
}
Note: When order status (status) is 2, it indicates payment is successful. The merchant system needs to verify the signature and process business logic, then return "success" after completion.

5. Order Query API

5.1 API Description

Submit Method: POST

URL: /query.html

5.2 Request Parameters

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

5.3 Response Parameters

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

5.4 Request Example

POST /query.html HTTP/1.1
Content-Type: application/x-www-form-urlencoded

merchantid=1&orderid=TEST20230101000001&query_type=payment&sign=A1B2C3D4E5F6G7H8I9J0

5.5 Response Example

{
    "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"
    }
}
Order Status Description:
  • Payment Order Status:
    • SUCCESS: Order payment successful
    • NOTPAY: Order unpaid or payment failed
  • Payout Order Status:
    • SUCCESS: Payout successful
    • NOTPAY: Order unpaid
    • PAYING: Payout processing (indicates order status is unpaid, processing, or timeout)
    • PAY_FAILED: Payout failed (indicates order status is payout failed or rejected)

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.

6. Payout API

6.1 API Description

Submit Method: POST

URL: /payout.html

6.2 Request Parameters

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'
withdraw_query_url Description:

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.

6.3 Response Parameters

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

6.4 Request Example

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

6.5 Response Example

{
    "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"
    }
}

6.6 Payout Asynchronous Notification

Submit Method: POST

When receiving server point-to-point communication, output "success" on the page (without quotes, lowercase letters), otherwise point-to-point notification will be sent 3 times repeatedly.
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

6.7 Payout Asynchronous Notification Example

                {
                    "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"
                    }
                }
Note: When order status (status) is 2, it indicates payout is successful. The merchant system needs to verify the signature and process business logic, then return "success" after completion.
Payout Status Processing Description:
  • Status 2 (Paid): Indicates payout transaction completed successfully, can update order to success status.
  • Status 4 (Failed) or Status 5 (Rejected): Indicates payout failed, system will automatically refund merchant balance and generate corresponding callback notification.
  • Status 3 (Order timeout): Can be understood as processing status, manual intervention will occur at this time.
  • Note: code=0 does not necessarily indicate final order failure, please use the status field value to determine the final order status.

7. Balance Query API

7.1 API Description

Submit Method: POST

URL: /balance.html

7.2 Request Parameters

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

7.3 Response Parameters

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

7.4 Request Example

POST /balance.html HTTP/1.1
Content-Type: application/x-www-form-urlencoded

merchantid=1&timestamp=1711603200&sign=A1B2C3D4E5F6G7H8I9J0

7.5 Response Example

{
    "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"
    }
}
Note: For security reasons, the balance query API has added timestamp verification. Please ensure your server time is correctly synchronized. The timestamp validity period is 5 minutes.

8. Signature Algorithm

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.

Example:

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()

Java Code Example:

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(Map params, 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";
    }
}
Java Example Description:
  • Example code uses TreeMap to ensure parameters are sorted by ASCII code
  • Uses UTF-8 encoding to process strings
  • Provides complete signature generation process
  • Includes parameter filtering, sorting, concatenation, MD5 encryption steps
  • Provides main method as usage example
Notes:
  • Actual projects need to add appropriate exception handling
  • Recommend using thread-safe implementation
  • HTTP request part needs to choose appropriate HTTP client according to actual project
  • Recommend adding parameter validation and logging

9.1 PHP Code Example

/**
 * 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
    ];
}

9.2 Order Request Example

// 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);

9.3 Asynchronous Notification Processing Example

// 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';
}

9.4 Balance Query Example

// 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);