在构建区块链佣金结算系统时,核心难点在于如何保证结算的实时性与资金的安全性。为了降低链上计算成本并保证灵活性,本方案采用“链下计算、链上结算”的架构。智能合约仅负责记录销售事件和资金托管,后端服务负责监听链上事件、计算佣金比例并执行自动转账。这种架构既能避免复杂的数学运算上链消耗Gas,又能利用区块链的不可篡改性确保资金流向透明。
我们将使用Hardhat作为开发框架,Node.js作为后端运行环境。请确保本地已安装Node.js(版本建议v16以上)。首先创建项目目录并安装必要依赖包。
打开终端,依次执行以下命令:
```bash mkdir blockchain-commission-system cd blockchain-commission-system npm init -y npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox ethers npm install dotenv ```安装完成后,初始化Hardhat项目:
```bash npx hardhat init ```在初始化交互中,选择“Create a JavaScript project”,其他选项保持默认回车。项目结构生成后,我们需要配置hardhat.config.js文件以支持网络连接和私钥管理。
在项目根目录下创建.env文件,用于存储敏感信息。请勿将该文件提交至代码仓库。
```env PRIVATE_KEY=你的钱包私钥(不含0x前缀) INFURA_API_KEY=你的Infura项目ID ```接下来,修改hardhat.config.js,引入环境变量并配置Sepolia测试网(或其他EVM兼容网络):
```javascript require("@nomicfoundation/hardhat-toolbox"); require("dotenv").config(); module.exports = { solidity: "0.8.19", networks: { sepolia: { url: `https://sepolia.infura.io/v3/${process.env.INFURA_API_KEY}`, accounts: [process.env.PRIVATE_KEY] } } }; ```智能合约的核心功能是记录销售行为并触发佣金事件。我们在contracts目录下创建CommissionSystem.sol文件。该合约包含一个销售函数,买家支付ETH,合约记录推荐人地址并发出事件。
```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; contract CommissionSystem { address public owner; uint256 public totalSales; event SaleRecorded(address indexed buyer, address indexed referrer, uint256 amount, uint256 timestamp); constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "Not authorized"); _; } // 模拟销售行为,资金暂时存入合约或直接分发 function recordSale(address _referrer) external payable { require(msg.value > 0, "Amount must be greater than 0"); totalSales += msg.value; // 发出事件,通知后端服务进行结算 emit SaleRecorded(msg.sender, _referrer, msg.value, block.timestamp); } // 紧急提取资金功能 function withdraw() external onlyOwner { payable(owner).transfer(address(this).balance); } } ```上述合约中,recordSale函数接收买家支付的ETH和推荐人地址,并发出SaleRecorded事件。后端服务将监听此事件作为结算的触发信号。
在scripts目录下创建deploy.js,编写部署逻辑:
```javascript const hre = require("hardhat"); async function main() { const CommissionSystem = await hre.ethers.getContractFactory("CommissionSystem"); const commissionSystem = await CommissionSystem.deploy(); await commissionSystem.deployed(); console.log(`CommissionSystem deployed to: ${commissionSystem.address}`); } main().catch((error) => { console.error(error); process.exitCode = 1; }); ```执行部署命令,将合约部署至Sepolia测试网:
```bash npx hardhat run scripts/deploy.js --network sepolia ```执行成功后,终端会输出合约地址,请务必保存该地址,后续开发将用到。假设合约地址为:0x1234567890123456789012345678901234567890。

这是本系统的核心部分。我们将编写一个Node.js脚本,实时监听链上事件,一旦发生销售,自动计算佣金并向推荐人转账。在项目根目录下创建settlement-service.js。
在上述文件中继续添加distributeCommission函数。该函数负责计算佣金金额、构建交易并广播上链。
```javascript async function distributeCommission(wallet, referrerAddress, saleAmount) { try { // 1. 计算佣金 const commissionAmount = saleAmount.mul(COMMISSION_RATE).div(100); // 使用BigNumber运算避免精度丢失 const formattedCommission = ethers.utils.formatEther(commissionAmount); if (commissionAmount.isZero()) { console.log("佣金金额为0,跳过转账。"); return; } console.log(`正在向 ${referrerAddress} 结算佣金: ${formattedCommission} ETH...`); // 2. 构建交易对象 const tx = { to: referrerAddress, value: commissionAmount, // 可以根据网络状况动态调整gasPrice gasPrice: await wallet.provider.getGasPrice(), gasLimit: 21000 // 标准转账GasLimit }; // 3. 发送交易 const transactionResponse = await wallet.sendTransaction(tx); console.log(`交易已发送,Hash: ${transactionResponse.hash}`); // 4. 等待交易确认 await transactionResponse.wait(); console.log(`佣金结算成功!区块确认完成。`); } catch (error) { console.error("结算失败:", error); // 实际生产环境中,此处应加入重试机制或记录到数据库以便人工介入 } } // 启动服务 startSettlementService().catch(console.error); ```现在我们已经完成了合约部署和后端服务的编写。接下来进行全流程测试。
步骤1:启动结算服务
在终端中运行后端监听脚本:
```bash node settlement-service.js ```终端应显示“正在监听合约...”字样,保持该窗口运行。
步骤2:模拟销售触发
打开一个新的终端窗口,我们将编写一个简单的脚本来调用合约的recordSale函数,模拟用户购买行为。创建scripts/triggerSale.js:
```javascript const hre = require("hardhat"); async function main() { const address = "0x1234567890123456789012345678901234567890"; // 合约地址 const referrer = "0xABCDEF1234567890ABCDEF1234567890ABCDEF12"; // 替换为一个有效的推荐人地址 const Contract = await hre.ethers.getContractFactory("CommissionSystem"); const contract = Contract.attach(address); console.log("正在模拟购买,支付0.1 ETH..."); const tx = await contract.recordSale(referrer, { value: hre.ethers.utils.parseEther("0.1") }); await tx.wait(); console.log("购买交易成功!"); } main().catch((error) => { console.error(error); process.exitCode = 1; }); ```执行触发脚本:
```bash npx hardhat run scripts/triggerSale.js --network sepolia ```步骤3:观察结果
回到运行settlement-service.js的终端窗口。你应该能看到如下日志输出:
```text 捕获销售事件! 买家: 0x... 推荐人: 0x... 销售金额: 0.1 ETH 正在向 0x... 结算佣金: 0.01 ETH... 交易已发送,Hash: 0x... 佣金结算成功!区块确认完成。此时,你可以去Sepolia区块链浏览器(如Etherscan)查询推荐人地址的余额,应该已经增加了0.01 ETH。
以上代码实现了核心闭环,但在生产环境部署时,还需注意以下细节:
易频IT社区是综合性互联网IT技术门户网站,专注分享网络技术、服务器运维、网络安全、编程开发、系统架构、云计算、大数据等行业干货,实时更新IT行业资讯、零基础教程、实战案例,为IT从业者、技术爱好者提供专业的学习交流平台。
Copyright © 2021-2026 易频IT社区. All Rights Reserved. 备案号:闽ICP备2023013482号 网站地图