using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace UsdtPayment.SDK
{
///
/// USDT支付网关 C# SDK v3.2.0
///
/// 接口说明:
/// - /api/address/create 动态生成收款地址(支持多币种)
/// - /api/pay/create 创建支付订单
/// - /api/pay/query 查询订单状态
///
/// 支持币种:
/// - USDT-TRC20 (TRON网络USDT)
/// - USDC-TRC20 (TRON网络USDC)
/// - ETH (以太坊)
/// - USDT-ERC20 (ERC20 USDT)
/// - USDC-ERC20 (ERC20 USDC)
/// - BTC (比特币)
/// - BSC (币安链)
/// - USDT-BEP20 (BEP20 USDT)
/// - USDC-BEP20 (BEP20 USDC)
/// - POLYGON (Polygon网络)
/// - USDT-POLYGON(Polygon USDT)
/// - USDC-POLYGON(Polygon USDC)
///
public class UsdtPaySDK
{
private readonly string _baseUrl;
private readonly string _merchantNo;
private readonly string _apiKey;
private readonly string _apiSecret;
private readonly HttpClient _httpClient;
public UsdtPaySDK(string baseUrl, string merchantNo, string apiKey, string apiSecret)
{
_baseUrl = baseUrl.TrimEnd('/');
_merchantNo = merchantNo;
_apiKey = apiKey;
_apiSecret = apiSecret;
_httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
}
///
/// 动态生成收款地址
///
/// 地址别名(可选)
/// 币种类型: USDT-TRC20, ETH, USDT-ERC20, BTC, BSC, USDT-BEP20, POLYGON, USDT-POLYGON
/// 响应JSON字符串
public async Task CreateAddressAsync(string label = null, string coinType = "USDT-TRC20")
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var parameters = new Dictionary
{
{ "merchantNo", _merchantNo },
{ "timestamp", timestamp }
};
if (!string.IsNullOrEmpty(label))
{
parameters["label"] = label;
}
if (!string.IsNullOrEmpty(coinType))
{
parameters["coinType"] = coinType;
}
string sign = GenerateSign(parameters);
parameters["sign"] = sign;
return await RequestAsync("/api/address/create", parameters);
}
///
/// 创建支付订单
///
public async Task CreateOrderAsync(string payAddress, string productName, string productDescription = null)
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var parameters = new Dictionary
{
{ "merchantNo", _merchantNo },
{ "payAddress", payAddress },
{ "productName", productName },
{ "timestamp", timestamp }
};
if (!string.IsNullOrEmpty(productDescription))
{
parameters["productDescription"] = productDescription;
}
string sign = GenerateSign(parameters);
parameters["sign"] = sign;
return await RequestAsync("/api/pay/create", parameters);
}
///
/// 查询订单状态
///
public async Task QueryOrderAsync(string orderNo)
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var parameters = new Dictionary
{
{ "merchantNo", _merchantNo },
{ "orderNo", orderNo },
{ "timestamp", timestamp }
};
string sign = GenerateSign(parameters);
parameters["sign"] = sign;
return await RequestAsync("/api/pay/query", parameters);
}
///
/// 验证回调签名
///
public bool VerifyCallback(Dictionary data)
{
if (!data.ContainsKey("sign"))
return false;
string sign = data["sign"].ToString();
var signData = new Dictionary(data);
signData.Remove("sign");
string expectedSign = GenerateSign(signData);
return sign.Equals(expectedSign, StringComparison.OrdinalIgnoreCase);
}
///
/// 生成签名
/// 签名算法: SHA256(参数按键名排序拼接 + key=apiSecret)
/// 拼接格式: key1=value1&key2=value2&...&key=apiSecret
///
private string GenerateSign(Dictionary parameters)
{
// 按键名排序
var sortedParams = new SortedDictionary(parameters);
// 拼接参数
var sb = new StringBuilder();
foreach (var entry in sortedParams)
{
if (entry.Value != null && !string.IsNullOrEmpty(entry.Value.ToString()))
{
sb.Append(entry.Key).Append("=").Append(entry.Value).Append("&");
}
}
// 追加密钥
sb.Append("key=").Append(_apiSecret);
return Sha256Hex(sb.ToString());
}
private string Sha256Hex(string input)
{
using (var sha256 = SHA256.Create())
{
byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
private async Task RequestAsync(string path, Dictionary parameters)
{
string url = _baseUrl + path;
string json = JsonSerializer.Serialize(parameters);
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
};
request.Headers.Add("X-API-KEY", _apiKey);
var response = await _httpClient.SendAsync(request);
return await response.Content.ReadAsStringAsync();
}
}
// ==================== 使用示例 ====================
class Program
{
static async Task Main(string[] args)
{
var sdk = new UsdtPaySDK(
"https://xxxx.com",
"M203254xxxx1709440", // 商户编号
"AK_xxxxxxxx", // API Key
"AS_xxxxxxxx" // API Secret
);
// 1. 动态生成收款地址(默认USDT-TRC20)
string result = await sdk.CreateAddressAsync("用户充值-订单123");
Console.WriteLine("生成TRC20地址: " + result);
// 1.1 生成ETH地址
result = await sdk.CreateAddressAsync("用户充值-ETH", "ETH");
Console.WriteLine("生成ETH地址: " + result);
// 1.2 生成USDT-ERC20地址
result = await sdk.CreateAddressAsync("用户充值-ERC20", "USDT-ERC20");
Console.WriteLine("生成ERC20地址: " + result);
// 1.3 生成BTC地址
result = await sdk.CreateAddressAsync("用户充值-BTC", "BTC");
Console.WriteLine("生成BTC地址: " + result);
// 1.4 生成BSC USDT地址
result = await sdk.CreateAddressAsync("用户充值-BEP20", "USDT-BEP20");
Console.WriteLine("生成BEP20地址: " + result);
// 2. 创建支付订单
result = await sdk.CreateOrderAsync(
"T9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"购买VIP会员",
"购买1个月VIP会员服务"
);
Console.WriteLine("创建订单结果: " + result);
// 3. 查询订单状态
result = await sdk.QueryOrderAsync("P2032545595611709440");
Console.WriteLine("查询订单结果: " + result);
}
}
}
/*
===================== 完整对接流程 =====================
1. 从商户后台获取凭证:
- 商户编号 (merchantNo)
- API Key
- API Secret
2. 用户发起支付时:
a) 调用 CreateAddressAsync() 动态生成收款地址
b) 调用 CreateOrderAsync() 创建支付订单
c) 展示收款地址给用户进行转账
3. 用户转账后:
- 系统自动检测链上交易
- 支付成功后回调您的通知地址
4. 验证回调签名,更新订单状态
=====================================================
*/