如何使用PHP离线签名Tron API生成的USDT交易?
TRON USDT(TRC20)离线签名交易PHP实现
关键说明
USDT属于TRC20代币,不能使用原生TRX的createtransaction接口,需调用智能合约触发接口构造交易。以下是完整的离线签名流程实现:
1. 构造未签名的USDT转账交易
调用接口生成未签名交易结构,无需传入私钥:
public function createUnsignedUsdtTransaction() { $curl = curl_init(); // USDT主网合约地址 $usdtContractAddress = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'; $ownerAddress = 'OWNER_BASE58_ADDRESS'; // 你的钱包地址(Base58格式) $toAddress = 'TO_BASE58_ADDRESS'; // 收款地址(Base58格式) $amount = 1000000; // 转账1 USDT(最小单位为6位小数,1 USDT = 1000000) $postData = json_encode([ 'contract_address' => $usdtContractAddress, 'function_selector' => 'transfer(address,uint256)', 'parameter' => $this->encodeTrc20TransferParams($toAddress, $amount), 'owner_address' => $ownerAddress, 'visible' => true, 'fee_limit' => 100000000 // 手续费上限:1 TRX ]); curl_setopt_array($curl, [ CURLOPT_URL => "https://api.trongrid.io/wallet/triggersmartcontract", CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, CURLOPT_HTTPHEADER => [ "accept: application/json", "content-type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { die("cURL Error #:" . $err); } $result = json_decode($response, true); if ($result['result']['code'] != 0) { die("构造交易失败: " . $result['result']['message']); } return $result['transaction']; } // 编码TRC20 transfer方法的参数 private function encodeTrc20TransferParams($toAddress, $amount) { // Base58地址转十六进制(去掉前缀) $toHex = str_replace('0x', '', $this->base58ToHex($toAddress)); $toHex = str_pad($toHex, 64, '0', STR_PAD_LEFT); // 补全为64位十六进制 $amountHex = str_pad(dechex($amount), 64, '0', STR_PAD_LEFT); // 金额转64位十六进制 return $toHex . $amountHex; } // Base58地址转十六进制 private function base58ToHex($base58) { $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; $base = strlen($alphabet); $hex = '0'; for ($i = 0; $i < strlen($base58); $i++) { $char = $base58[$i]; $index = strpos($alphabet, $char); if ($index === false) { throw new Exception("无效的Base58字符"); } $hex = bcadd(bcmul($hex, $base), $index); } $hex = dechex(hexdec($hex)); return str_pad($hex, 40, '0', STR_PAD_LEFT); // 补全为40位十六进制 }
2. 离线签名交易
按照官方流程完成哈希计算、私钥签名、添加签名到交易:
public function signTransaction($unsignedTransaction, $privateKey) { // 1. 序列化交易并计算哈希(生产环境建议用官方Protobuf规则序列化) $transactionBytes = $this->serializeTransaction($unsignedTransaction); $hash = hash('sha256', $transactionBytes, true); // 2. 用私钥对哈希进行ECDSA签名(secp256k1曲线) $pemKey = "-----BEGIN PRIVATE KEY-----\n" . chunk_split(base64_encode(hex2bin($privateKey)), 64) . "-----END PRIVATE KEY-----"; $privateKeyResource = openssl_pkey_get_private($pemKey); openssl_sign($hash, $signature, $privateKeyResource, OPENSSL_ALGO_SHA256); openssl_free_key($privateKeyResource); // 3. 将签名添加到交易结构 $unsignedTransaction['signature'] = [bin2hex($signature)]; return $unsignedTransaction; } // 简化版交易序列化(生产环境请用官方Protobuf定义实现) private function serializeTransaction($tx) { $rawData = json_encode($tx['raw_data']); return hash('sha256', $rawData, true); }
注意:完整的TRON交易序列化需严格遵循Protobuf协议,上述简化版仅作示例。生产环境建议使用官方Protobuf文件生成序列化代码,避免签名失败。
3. 广播已签名交易
将签名后的交易广播到TRON网络:
public function broadcastSignedTransaction($signedTransaction) { $curl = curl_init(); $postData = json_encode($signedTransaction); curl_setopt_array($curl, [ CURLOPT_URL => "https://api.trongrid.io/wallet/broadcasttransaction", CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, CURLOPT_HTTPHEADER => [ "accept: application/json", "content-type: application/json" ], ]); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { die("cURL Error #:" . $err); } return json_decode($response, true); }
完整调用示例
// 替换为你的私钥(十六进制格式) $ownerPrivateKey = 'YOUR_PRIVATE_KEY_HEX'; // 1. 创建未签名交易 $unsignedTx = $this->createUnsignedUsdtTransaction(); // 2. 离线签名 $signedTx = $this->signTransaction($unsignedTx, $ownerPrivateKey); // 3. 广播交易 $result = $this->broadcastSignedTransaction($signedTx); print_r($result);
内容的提问来源于stack exchange,提问作者eren
相关产品推荐
相关产品推荐

