Intégration des smart contracts sur TRON
Ce guide explique comment accepter des paiements crypto non dépositaires sur TRON avec les smart contracts de paiement de Volet.com et TronWeb.
Vos clients connectent leur portefeuille, approuvent les transactions et paient directement sur votre portefeuille de réception via un smart contract. Les fonds ne sont pas crédités sur un compte Volet.com.
Avant de continuer, consultez Intégration des smart contracts pour une présentation du parcours de paiement.
L’intégration en bref
- Connectez le portefeuille du client et vérifiez qu’il utilise TRON Mainnet.
- Configurez les contrats de paiement et votre portefeuille de réception.
- Créez une commande dans votre backend avant de lancer le paiement.
- Appelez
previewPayment()pour calculer le montant total du paiement. - Appelez
transfer()pour lancer le paiement. Pour l’USDT, vérifiez l’autorisation de dépense (allowance) du jeton et demandez une approbation si nécessaire. - Enregistrez le hash de la transaction de paiement (
txid) dans la commande. - Vérifiez la transaction sur votre backend à partir des données blockchain solidifiées avant de marquer la commande comme payée.
Avant de commencer
Vous aurez besoin :
- D’un portefeuille client : TronLink pour les paiements dans le navigateur.
- D’une bibliothèque : TronWeb pour interagir avec les portefeuilles et les smart contracts TRON.
- D’un portefeuille marchand : une adresse de portefeuille TRON que vous contrôlez pour recevoir les paiements.
- D’un backend et d’une base de données : pour créer les commandes, stocker les détails des transactions et vérifier les paiements.
- D’un accès à la blockchain : un nœud TRON ou un service hébergé, comme TronGrid, pour récupérer et vérifier les transactions.
Pour connecter des portefeuilles mobiles, il vous faudra aussi un Project ID WalletConnect et une intégration compatible avec les portefeuilles TRON.
Réseaux et actifs pris en charge
| Réseau | Actifs pris en charge |
|---|---|
| TRON Mainnet | TRX, USDT (TRC-20) |
TRX et USDT utilisent des contrats processeurs de paiement distincts.
Les montants en TRX sont exprimés en SUN, la plus petite unité du TRX. Un TRX équivaut à 1 000 000 SUN.
L’USDT TRC-20 utilise 6 décimales. Un USDT équivaut à 1 000 000 unités de base du jeton.
Les exemples de code ci-dessous contiennent les adresses des processeurs et des jetons issues de la configuration de l’intégration.
Les adresses des contrats, les décimales des jetons et les paramètres des fonctions figurent dans la Référence des smart contracts.
Avant d’utiliser les exemples en production, confirmez auprès de Volet.com les adresses des processeurs déployés et l’interface du contrat.
Étape 1. Connectez le portefeuille du client
Utilisez TronLink pour connecter le portefeuille de navigateur du client.
<button id="connect-tron">Connect TronLink</button>
<script>
let tronWeb;
document.getElementById('connect-tron').addEventListener('click', async () => {
if (!window.tronLink || !window.tronWeb) {
alert('Install and unlock TronLink.');
return;
}
const result = await window.tronLink.request({
method: 'tron_requestAccounts'
});
if (result?.code !== 200) {
throw new Error('Wallet connection rejected');
}
tronWeb = window.tronWeb;
document.getElementById('connect-tron').textContent =
tronWeb.defaultAddress.base58;
});
</script>
Le client doit se connecter à TRON Mainnet.
Vérifiez le réseau actif avant d’envoyer un paiement. Ne vous fiez pas uniquement à l’URL de l’endpoint RPC pour identifier le réseau, car les portefeuilles peuvent utiliser des nœuds personnalisés.
Votre application doit aussi détecter les changements de compte et de réseau dans le portefeuille et revalider la connexion avant de lancer une transaction.
Étape 2. Configurez les contrats de paiement
Ajoutez à votre application l’ABI du processeur de paiement et les fonctions du jeton.
const PROCESSOR_ABI = [
{
name: 'previewPayment',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'amount', type: 'uint256' },
{ name: 'buyerPaysCommission', type: 'bool' },
],
outputs: [
{ name: 'commission', type: 'uint256' },
{ name: 'totalPay', type: 'uint256' },
],
},
{
name: 'transfer',
type: 'function',
stateMutability: 'payable',
inputs: [
{ name: 'seller', type: 'address' },
{ name: 'amount', type: 'uint256' },
{ name: 'buyerPaysCommission', type: 'bool' },
{ name: 'optionalCommissionWallet', type: 'address' },
],
outputs: [],
},
];
const TOKEN_ABI = [
{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ type: 'uint256' }],
},
{
name: 'allowance',
type: 'function',
stateMutability: 'view',
inputs: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
],
outputs: [{ type: 'uint256' }],
},
{
name: 'approve',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint256' },
],
outputs: [{ type: 'bool' }],
},
];
const TRON_PROCESSOR_TRX = 'TSK9sgBTjvZa6x2yW1bXNWqvQ57WsVUQ3W';
const TRON_PROCESSOR_USDT = 'TDuE6VueULx5oivQd4MsYr9DEhNMgXNfTm';
const TRON_USDT = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
const TRON_ZERO = 'T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb';
const TRON_FEE_LIMIT = 500_000_000;
Le processeur de paiement expose deux fonctions principales :
previewPayment(amount, buyerPaysCommission)calcule les frais de traitement et le montant total que le client doit payer.transfer(seller, amount, buyerPaysCommission, optionalCommissionWallet)exécute le paiement et répartit les fonds selon le paramétrage des frais du contrat.
Le paramètre amount est exprimé dans les plus petites unités de l’actif : en SUN pour le TRX ou en unités de base du jeton pour l’USDT.
Le paramètre buyerPaysCommission détermine qui prend en charge les frais de traitement :
true: les frais s’ajoutent au paiement du client.false: les frais sont déduits du montant reçu par le marchand.
Utilisez TRON_ZERO pour optionalCommissionWallet s’il n’y a pas de portefeuille de commission partenaire.
Obtenez toujours le montant total du paiement via previewPayment(). Ne calculez pas les frais de traitement manuellement.
Le TRON_FEE_LIMIT de l’exemple est exprimé en SUN et représente une limite de frais maximale de 500 TRX, et non les frais attendus de la transaction. Avant la mise en production, estimez l’Energy nécessaire et définissez une limite de frais adaptée.
Les définitions complètes des paramètres figurent dans la Référence des smart contracts.
Étape 3. Acceptez le TRX
Les paiements en TRX natif nécessitent une seule transaction dans le portefeuille.
Utilisez previewPayment() pour calculer le montant exact de SUN à envoyer avec la transaction.
async function payTrx(tronWeb, seller, humanAmount, buyerPaysCommission = true) {
if (!tronWeb.isAddress(seller)) {
throw new Error('Invalid TRON seller address');
}
const processor = tronWeb.contract(
PROCESSOR_ABI,
TRON_PROCESSOR_TRX
);
const amount = tronWeb.toSun(humanAmount).toString();
const preview = await processor.previewPayment(
amount,
buyerPaysCommission
).call();
return processor.transfer(
seller,
amount,
buyerPaysCommission,
TRON_ZERO
).send({
callValue: preview.totalPay.toString(),
feeLimit: TRON_FEE_LIMIT
});
}
La callValue de la transaction doit être égale au totalPay renvoyé par previewPayment().
Le client doit aussi disposer d’assez de TRX pour couvrir les ressources blockchain et les frais de transaction.
La fonction renvoie le hash de la transaction de paiement (txid). Enregistrez-le dans la commande existante et vérifiez le paiement avant d’exécuter la commande.
Étape 4. Acceptez l’USDT
Les paiements en USDT TRC-20 passent par un contrat de jeton et peuvent nécessiter une transaction d’approbation supplémentaire.
Avant d’effectuer un paiement, votre application doit :
- Vérifier le solde USDT du client avec
balanceOf(). - Vérifier l’autorisation de dépense du processeur avec
allowance(). - Si l’autorisation est insuffisante, demander une approbation avec
approve(). - Attendre la confirmation de l’approbation.
- Appeler
transfer()pour exécuter le paiement.
async function payTronUsdt(tronWeb, seller, amountBaseUnits, buyerPaysCommission = true) {
if (!tronWeb.isAddress(seller)) {
throw new Error('Invalid TRON seller address');
}
if (!/^\d+$/.test(amountBaseUnits) || BigInt(amountBaseUnits) <= 0n) {
throw new Error('USDT amount must be a positive integer in base units');
}
const processor = tronWeb.contract(
PROCESSOR_ABI,
TRON_PROCESSOR_USDT
);
const token = tronWeb.contract(
TOKEN_ABI,
TRON_USDT
);
const owner = tronWeb.defaultAddress.base58;
const preview = await processor.previewPayment(
amountBaseUnits,
buyerPaysCommission
).call();
const total = BigInt(preview.totalPay.toString());
const balance = BigInt(
(await token.balanceOf(owner).call()).toString()
);
if (balance < total) {
throw new Error('Insufficient USDT');
}
const allowance = BigInt(
(await token.allowance(owner, TRON_PROCESSOR_USDT).call()).toString()
);
if (allowance < total) {
const approvalTxid = await token.approve(
TRON_PROCESSOR_USDT,
total.toString()
).send({ feeLimit: TRON_FEE_LIMIT });
return {
state: 'approval_pending',
approvalTxid
};
}
const paymentTxid = await processor.transfer(
seller,
amountBaseUnits,
buyerPaysCommission,
TRON_ZERO
).send({ feeLimit: TRON_FEE_LIMIT });
return {
state: 'payment_pending',
paymentTxid
};
}
Exigences d’approbation USDT
Selon l’autorisation existante, un paiement en USDT peut nécessiter :
| Autorisation existante | Transactions nécessaires |
|---|---|
| Suffisante | Paiement uniquement |
| Insuffisante | Approbation + paiement |
Si une approbation est nécessaire, la fonction renvoie approval_pending avec le hash de la transaction d’approbation.
Attendez la confirmation de l’approbation avant d’appeler de nouveau la fonction de paiement. Une fois l’autorisation suffisante, la fonction envoie le paiement et renvoie payment_pending avec le hash de la transaction de paiement.
Important :
- Une transaction
approve()n’est pas un paiement. - Le client a besoin d’assez de TRX pour couvrir les coûts d’Energy et de Bandwidth, même lorsqu’il paie en USDT.
- Les montants en USDT doivent être exprimés en entiers, en unités de base du jeton. Évitez les calculs à virgule flottante comme
Math.round(parseFloat(amount) * 1e6). - Suivez les transactions d’approbation séparément de la transaction de paiement finale.
Étape 5. Enregistrez la transaction de paiement
Votre backend doit créer une commande avant que le client envoie un paiement.
Chaque commande doit contenir les valeurs attendues suivantes :
- Identifiant de commande
- Réseau blockchain
- Actif et montant
- Portefeuille de réception du marchand (
seller) - Contrat processeur de paiement approuvé
- Portefeuille de l’acheteur, si votre page de paiement l’exige
- Paramétrage des frais de traitement (
buyerPaysCommission)
Une fois le paiement envoyé par le client :
- Récupérez le hash de la transaction de paiement (
txid) renvoyé par le portefeuille. - Envoyez le hash à votre backend.
- Enregistrez-le avec l’identifiant de commande et le réseau blockchain.
- Lancez la vérification du paiement côté serveur.
Chaque transaction de paiement doit être associée à une seule commande au maximum. Imposez-le avec une contrainte d’unicité (network, txid) dans votre base de données.
La fonction transfer() du smart contract n’accepte pas d’identifiant de commande. C’est à votre application de maintenir le lien entre la commande et sa transaction de paiement.
Si un client relance un paiement, conservez des tentatives de paiement distinctes au lieu d’écraser des enregistrements de transactions qui peuvent encore être en attente.
Étape 6. Vérifiez le paiement
La vérification du paiement est obligatoire avant de finaliser une commande.
Un hash de transaction renvoyé indique seulement qu’une transaction a été envoyée. Il ne prouve pas que le marchand a reçu le bon paiement.
Votre backend doit, de manière indépendante :
- Récupérer la transaction et le reçu d’exécution depuis la blockchain.
- Confirmer la réussite de l’exécution à l’aide d’un reçu TRON solidifié.
- Vérifier que la transaction a utilisé le processeur de paiement attendu.
- Comparer l’actif, le portefeuille du marchand, le montant et l’appel au contrat avec la commande.
- Confirmer que le marchand a reçu les fonds attendus.
- S’assurer que la transaction n’a pas déjà été utilisée pour une autre commande.
- Marquer la commande comme payée et ne l’exécuter qu’une seule fois.
Pour obtenir les données de transaction solidifiées, utilisez l’endpoint SolidityNode de TRON :
POST https://api.trongrid.io/walletsolidity/gettransactioninfobyid
Vérifiez que receipt.result === 'SUCCESS', puis comparez le corps de la transaction et les détails réels du paiement à la commande.
Un reçu réussi ne suffit pas. Une transaction peut s’exécuter correctement sans payer le bon marchand ni le bon montant.
Si le service blockchain est temporairement indisponible ou si la transaction n’est pas encore solidifiée, laissez la commande en attente et relancez la vérification.
Suivez Vérification des paiements et suivi des commandes pour l’implémentation complète côté backend, les exigences de confirmation TRON et la liste de contrôle de mise en production.
Vous pouvez aussi consulter TRON confirmation semantics.
Facultatif : prendre en charge les portefeuilles mobiles
Pour prendre en charge les portefeuilles mobiles via WalletConnect, utilisez une intégration compatible avec les portefeuilles TRON, comme @tronweb3/walletconnect-tron, avec TronWeb.
Cela nécessite un Project ID WalletConnect et une intégration capable de créer des transactions TRON, de demander des signatures aux portefeuilles mobiles et de diffuser les transactions signées.
L’exemple pour navigateur décrit ci-dessous prend en charge TronLink. Il n’implémente pas le parcours WalletConnect pour portefeuilles mobiles.
Exemple d’intégration
L’exemple example-tron.html illustre :
- La connexion de TronLink.
- Le calcul des montants de paiement avec
previewPayment(). - L’envoi de paiements en TRX et USDT TRC-20.
- L’affichage des hashs de transaction et le suivi du statut des transactions.
Vous pouvez ouvrir l’exemple dans votre navigateur ou télécharger le fichier HTML pour étudier et adapter le code :
- Ouvrir l’exemple en ligne — ouvre la démo interactive. Elle utilise TRON Mainnet : confirmer un paiement transfère donc des fonds réels.
- Télécharger example-tron.html — enregistre le fichier HTML sur votre ordinateur.
Les extensions de portefeuille de navigateur comme TronLink peuvent mal fonctionner avec les pages ouvertes directement depuis le disque (file://). Servez plutôt le fichier téléchargé depuis un serveur web local. Par exemple, lancez npx serve dans le dossier du fichier et ouvrez l’URL localhost qu’il affiche.
Essayer l’exemple
- Ouvrez l’exemple en ligne ou servez le fichier téléchargé localement, dans un navigateur où TronLink est installé.
- Sélectionnez Mainnet dans TronLink, puis cliquez sur Connect TronLink. La démo vous avertit si le portefeuille est connecté à un autre réseau.
- Sélectionnez le moyen de paiement : TRX ou USDT TRC-20.
- Saisissez le portefeuille TRON de réception dans Seller address.
- Saisissez le montant du paiement et choisissez qui paie les frais de traitement.
- Cliquez sur Preview pour afficher les frais de traitement et le montant total du paiement. Cliquez ensuite sur Pay et confirmez la transaction dans TronLink. Les paiements en USDT peuvent d’abord nécessiter une approbation distincte du jeton.
- La commande et le hash de transaction s’affichent dans le tableau Orders. La démo vérifie le statut de la transaction pendant 5 minutes au maximum.
Avant de payer :
- Utilisez deux portefeuilles différents. L’adresse du vendeur doit être différente du portefeuille payeur. Sinon, le contrat refuse le paiement avec
SellerIsBuyer.- Les transactions engagent des fonds réels. L’exemple est prérempli avec
1TRX. Vérifiez le montant du paiement, les frais de traitement et le coût des ressources du réseau TRON (Energy et Bandwidth) avant de confirmer.
Limites de la démo : cet exemple stocke l’historique des transactions dans le
localStoragedu navigateur et n’est pas une page de paiement de production. Il vérifie le dernier reçu de transaction avecgetTransactionInfo(), ce qui ne garantit pas la solidification sur TRON. La fenêtre de suivi de 5 minutes n’est qu’une limite de la démo, pas un délai de confirmation du paiement. Mettez en œuvre le processus complet de vérification des paiements avant d’accepter des commandes clients.
Voir aussi
- Intégration des smart contracts — présentation du parcours de paiement non dépositaire.
- Intégration Ethereum et BNB Smart Chain — acceptez ETH, BNB et USDT.
- Référence des smart contracts — adresses des processeurs, décimales des jetons et paramètres des contrats.
- Dépannage — erreurs courantes de portefeuilles et de transactions.