文章目录[隐藏]
网络传媒WordPress柔性广告智能合约插件开发指南
概述
在当今数字化媒体时代,网络传媒平台面临着广告管理复杂、交易不透明、结算效率低下等挑战。本文将详细介绍如何开发一个基于WordPress的柔性广告智能合约插件,通过区块链技术实现广告交易的自动化、透明化和智能化管理。
技术架构设计
系统架构概览
本插件采用三层架构设计:
- 表示层:WordPress前端界面
- 业务逻辑层:PHP智能合约管理模块
- 区块链层:以太坊智能合约交互
开发环境配置
<?php
/**
* WordPress柔性广告智能合约插件 - 主文件
* Plugin Name: Flexible Ad Smart Contract
* Description: 基于区块链的智能广告合约管理插件
* Version: 1.0.0
* Author: 网络传媒技术团队
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('FASC_VERSION', '1.0.0');
define('FASC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('FASC_PLUGIN_URL', plugin_dir_url(__FILE__));
// 引入必要文件
require_once FASC_PLUGIN_DIR . 'includes/class-smart-contract-manager.php';
require_once FASC_PLUGIN_DIR . 'includes/class-ad-campaign.php';
require_once FASC_PLUGIN_DIR . 'includes/class-blockchain-connector.php';
?>
智能合约开发
以太坊智能合约代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title FlexibleAdContract
* @dev 柔性广告智能合约,管理广告展示、点击和结算
*/
contract FlexibleAdContract {
// 合约所有者
address public owner;
// 广告活动结构
struct AdCampaign {
uint256 id;
address advertiser;
string title;
uint256 budget;
uint256 spent;
uint256 cpc; // 每次点击成本(wei)
bool isActive;
uint256 startTime;
uint256 endTime;
uint256 maxImpressions;
uint256 impressionCount;
uint256 clickCount;
}
// 事件定义
event CampaignCreated(uint256 campaignId, address advertiser);
event AdDisplayed(uint256 campaignId, uint256 impressionId);
event AdClicked(uint256 campaignId, uint256 clickId, address viewer);
event PaymentProcessed(uint256 campaignId, uint256 amount);
// 存储映射
mapping(uint256 => AdCampaign) public campaigns;
mapping(uint256 => mapping(address => bool)) public hasClicked;
uint256 public campaignCounter;
// 修饰符:仅所有者
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this");
_;
}
// 构造函数
constructor() {
owner = msg.sender;
campaignCounter = 0;
}
/**
* @dev 创建新的广告活动
* @param _title 广告标题
* @param _budget 总预算(wei)
* @param _cpc 每次点击成本
* @param _maxImpressions 最大展示次数
* @param _duration 活动持续时间(秒)
*/
function createCampaign(
string memory _title,
uint256 _budget,
uint256 _cpc,
uint256 _maxImpressions,
uint256 _duration
) external payable returns (uint256) {
require(msg.value >= _budget, "Insufficient funds");
require(_cpc > 0, "CPC must be greater than 0");
campaignCounter++;
campaigns[campaignCounter] = AdCampaign({
id: campaignCounter,
advertiser: msg.sender,
title: _title,
budget: _budget,
spent: 0,
cpc: _cpc,
isActive: true,
startTime: block.timestamp,
endTime: block.timestamp + _duration,
maxImpressions: _maxImpressions,
impressionCount: 0,
clickCount: 0
});
emit CampaignCreated(campaignCounter, msg.sender);
return campaignCounter;
}
/**
* @dev 记录广告展示
* @param _campaignId 广告活动ID
*/
function recordImpression(uint256 _campaignId) external {
AdCampaign storage campaign = campaigns[_campaignId];
require(campaign.isActive, "Campaign is not active");
require(block.timestamp <= campaign.endTime, "Campaign has ended");
require(campaign.impressionCount < campaign.maxImpressions, "Max impressions reached");
require(campaign.spent + campaign.cpc <= campaign.budget, "Budget exceeded");
campaign.impressionCount++;
uint256 impressionId = campaign.impressionCount;
emit AdDisplayed(_campaignId, impressionId);
}
/**
* @dev 记录广告点击并处理支付
* @param _campaignId 广告活动ID
*/
function recordClick(uint256 _campaignId) external {
AdCampaign storage campaign = campaigns[_campaignId];
require(campaign.isActive, "Campaign is not active");
require(block.timestamp <= campaign.endTime, "Campaign has ended");
require(!hasClicked[_campaignId][msg.sender], "Already clicked this ad");
require(campaign.spent + campaign.cpc <= campaign.budget, "Budget exceeded");
// 更新统计数据
campaign.clickCount++;
campaign.spent += campaign.cpc;
hasClicked[_campaignId][msg.sender] = true;
// 向点击者支付奖励(90%给点击者,10%作为平台费用)
uint256 userReward = (campaign.cpc * 90) / 100;
uint256 platformFee = campaign.cpc - userReward;
payable(msg.sender).transfer(userReward);
payable(owner).transfer(platformFee);
emit AdClicked(_campaignId, campaign.clickCount, msg.sender);
emit PaymentProcessed(_campaignId, campaign.cpc);
// 检查预算是否用完
if (campaign.spent >= campaign.budget) {
campaign.isActive = false;
}
}
/**
* @dev 获取广告活动详情
* @param _campaignId 广告活动ID
*/
function getCampaignDetails(uint256 _campaignId) external view returns (
uint256 id,
address advertiser,
string memory title,
uint256 budget,
uint256 spent,
uint256 cpc,
bool isActive,
uint256 impressions,
uint256 clicks
) {
AdCampaign memory campaign = campaigns[_campaignId];
return (
campaign.id,
campaign.advertiser,
campaign.title,
campaign.budget,
campaign.spent,
campaign.cpc,
campaign.isActive,
campaign.impressionCount,
campaign.clickCount
);
}
}
WordPress插件核心模块
广告活动管理类
<?php
/**
* 广告活动管理类
*/
class FASC_Ad_Campaign {
private $campaign_id;
private $blockchain_connector;
public function __construct($campaign_id = null) {
$this->campaign_id = $campaign_id;
$this->blockchain_connector = new FASC_Blockchain_Connector();
}
/**
* 创建新的广告活动
*/
public function create_campaign($data) {
$campaign_data = array(
'title' => sanitize_text_field($data['title']),
'budget' => floatval($data['budget']),
'cpc' => floatval($data['cpc']),
'max_impressions' => intval($data['max_impressions']),
'duration_days' => intval($data['duration_days']),
'ad_content' => wp_kses_post($data['ad_content']),
'target_url' => esc_url_raw($data['target_url']),
'status' => 'pending',
'created_at' => current_time('mysql'),
'advertiser_id' => get_current_user_id()
);
// 保存到数据库
global $wpdb;
$table_name = $wpdb->prefix . 'fasc_campaigns';
$wpdb->insert($table_name, $campaign_data);
$local_campaign_id = $wpdb->insert_id;
// 部署到区块链
$blockchain_data = array(
'title' => $campaign_data['title'],
'budget' => $this->convert_to_wei($campaign_data['budget']),
'cpc' => $this->convert_to_wei($campaign_data['cpc']),
'maxImpressions' => $campaign_data['max_impressions'],
'duration' => $campaign_data['duration_days'] * 24 * 60 * 60
);
$contract_response = $this->blockchain_connector->create_campaign($blockchain_data);
if ($contract_response['success']) {
// 更新本地记录
$wpdb->update(
$table_name,
array(
'contract_address' => $contract_response['contract_address'],
'campaign_id' => $contract_response['campaign_id'],
'status' => 'active',
'transaction_hash' => $contract_response['transaction_hash']
),
array('id' => $local_campaign_id)
);
return array(
'success' => true,
'local_id' => $local_campaign_id,
'blockchain_id' => $contract_response['campaign_id']
);
}
return array('success' => false, 'error' => $contract_response['error']);
}
/**
* 显示广告
*/
public function display_ad() {
if (!$this->campaign_id) {
return false;
}
// 获取广告内容
$campaign = $this->get_campaign_details();
if (!$campaign || $campaign->status !== 'active') {
return false;
}
// 记录展示到区块链
$this->blockchain_connector->record_impression($campaign->campaign_id);
// 生成广告HTML
$ad_html = $this->generate_ad_html($campaign);
return $ad_html;
}
/**
* 处理广告点击
*/
public function handle_click() {
if (!$this->campaign_id) {
return false;
}
$campaign = $this->get_campaign_details();
if (!$campaign) {
return false;
}
// 调用智能合约记录点击
$result = $this->blockchain_connector->record_click($campaign->campaign_id);
if ($result['success']) {
// 记录点击到本地数据库
$this->log_click($campaign->id);
// 重定向到目标URL
wp_redirect($campaign->target_url);
exit;
}
return $result;
}
/**
* 生成广告HTML代码
*/
private function generate_ad_html($campaign) {
$click_url = add_query_arg(
array(
'fasc_action' => 'click',
'campaign_id' => $campaign->id,
'nonce' => wp_create_nonce('fasc_click_' . $campaign->id)
),
home_url('/')
);
ob_start();
?>
<div class="fasc-ad-container" data-campaign-id="<?php echo esc_attr($campaign->id); ?>">
<div class="fasc-ad-content">
<?php echo wp_kses_post($campaign->ad_content); ?>
</div>
<a href="<?php echo esc_url($click_url); ?>"
class="fasc-ad-link"
onclick="fascTrackClick(<?php echo esc_attr($campaign->id); ?>)">
<span class="fasc-ad-cta">了解更多</span>
</a>
<div class="fasc-ad-disclaimer">
此广告由智能合约驱动,点击可获得奖励
</div>
</div>
<script>
function fascTrackClick(campaignId) {
// 发送异步点击统计
fetch('<?php echo admin_url('admin-ajax.php'); ?>', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'action=fasc_track_click&campaign_id=' + campaignId
});
}
</script>
<?php
return ob_get_clean();
}
/**
* 转换ETH到Wei
*/
private function convert_to_wei($eth_amount) {
// 1 ETH = 10^18 Wei
return bcmul($eth_amount, '1000000000000000000', 0);
}
/**
* 获取活动详情
*/
private function get_campaign_details() {
global $wpdb;
$table_name = $wpdb->prefix . 'fasc_campaigns';
return $wpdb->get_row(
$wpdb->prepare("SELECT * FROM $table_name WHERE id = %d", $this->campaign_id)
);
}
/**
* 记录点击到本地数据库
*/
private function log_click($campaign_id) {
global $wpdb;
$table_name = $wpdb->prefix . 'fasc_clicks';
$click_data = array(
'campaign_id' => $campaign_id,
'user_id' => get_current_user_id(),
'ip_address' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'clicked_at' => current_time('mysql')
);
$wpdb->insert($table_name, $click_data);
}
}
?>
数据库设计
数据表结构
-- 广告活动表
CREATE TABLE `wp_fasc_campaigns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`advertiser_id` int(11) NOT NULL,
`budget` decimal(20,8) NOT NULL,
`cpc` decimal(20,8) NOT NULL,
`max_impressions` int(11) NOT NULL,
`duration_days` int(11) NOT NULL,
`ad_content` text NOT NULL,
`target_url` varchar(500) NOT NULL,
`contract_address` varchar(42) DEFAULT NULL,
`campaign_id` int(11) DEFAULT NULL,
`transaction_hash` varchar(66) DEFAULT NULL,
`status` enum('pending','active','paused','completed','cancelled') DEFAULT 'pending',
`created_at` datetime NOT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `advertiser_id` (`advertiser_id`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 广告展示记录表
CREATE TABLE `wp_fasc_impressions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`user_id` int(11) DEFAULT NULL,
`page_url` varchar(500) NOT NULL,
`ip_address` varchar(45) DEFAULT NULL,
`user_agent` text,
`impressed_at` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `campaign_id` (`campaign_id`),
KEY `impressed_at` (`impressed_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 广告点击记录表
CREATE TABLE `wp_fasc_clicks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`user_id` int(11) DEFAULT NULL,
`ip_address` varchar(45) DEFAULT NULL,
`user_agent` text,
`clicked_at` datetime NOT NULL,
`blockchain_tx_hash` varchar(66) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `campaign_id` (`campaign_id`),
KEY `clicked_at` (`clicked_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 支付记录表
CREATE TABLE `wp_fasc_payments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`campaign_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`amount` decimal(20,8) NOT NULL,
`transaction_hash` varchar(66) NOT NULL,
`payment_type` enum('click_reward','refund','withdrawal') NOT NULL,
`status` enum('pending','completed','failed') DEFAULT 'pending',
`created_at` datetime NOT NULL,
`completed_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `campaign_id` (`campaign_id`),
KEY `user_id` (`user_id`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
前端集成与用户体验
短代码实现
<?php
/**
* 广告展示短代码
*/
add_shortcode('flexible_ad', 'fasc_ad_shortcode');
function fasc_ad_shortcode($atts) {
$atts = shortcode_atts(array(
'campaign_id' => 0,
'position' => 'inline',
'max_width' => '300px'
), $atts, 'flexible_ad');
$campaign_id = intval($atts['campaign_id']);
if (!$campaign_id) {
// 自动选择活动
前端集成与用户体验(续)
短代码实现(续)
<?php
/**
* 广告展示短代码
*/
add_shortcode('flexible_ad', 'fasc_ad_shortcode');
function fasc_ad_shortcode($atts) {
$atts = shortcode_atts(array(
'campaign_id' => 0,
'position' => 'inline',
'max_width' => '300px'
), $atts, 'flexible_ad');
$campaign_id = intval($atts['campaign_id']);
if (!$campaign_id) {
// 自动选择活动
$campaign_id = fasc_get_available_campaign();
}
if (!$campaign_id) {
return '<div class="fasc-no-ad">暂无可用广告</div>';
}
$ad_campaign = new FASC_Ad_Campaign($campaign_id);
$ad_html = $ad_campaign->display_ad();
// 添加样式
$style = sprintf(
'max-width: %s; margin: 20px auto;',
esc_attr($atts['max_width'])
);
if ($atts['position'] === 'float_left') {
$style .= 'float: left; margin-right: 20px;';
} elseif ($atts['position'] === 'float_right') {
$style .= 'float: right; margin-left: 20px;';
}
return sprintf(
'<div class="fasc-ad-wrapper" style="%s">%s</div>',
$style,
$ad_html
);
}
/**
* 获取可用广告活动
*/
function fasc_get_available_campaign() {
global $wpdb;
$table_name = $wpdb->prefix . 'fasc_campaigns';
// 获取活跃且未超预算的活动
$campaign = $wpdb->get_row(
$wpdb->prepare(
"SELECT id FROM $table_name
WHERE status = 'active'
AND (max_impressions = 0 OR impression_count < max_impressions)
AND (end_time IS NULL OR end_time > %s)
ORDER BY RAND()
LIMIT 1",
current_time('mysql')
)
);
return $campaign ? $campaign->id : 0;
}
?>
小工具实现
<?php
/**
* 广告小工具类
*/
class FASC_Ad_Widget extends WP_Widget {
public function __construct() {
parent::__construct(
'fasc_ad_widget',
__('柔性广告', 'fasc'),
array('description' => __('显示智能合约驱动的广告', 'fasc'))
);
}
public function widget($args, $instance) {
echo $args['before_widget'];
if (!empty($instance['title'])) {
echo $args['before_title'] . apply_filters('widget_title', $instance['title']) . $args['after_title'];
}
$campaign_id = !empty($instance['campaign_id']) ? $instance['campaign_id'] : 0;
$ad_campaign = new FASC_Ad_Campaign($campaign_id);
echo $ad_campaign->display_ad();
echo $args['after_widget'];
}
public function form($instance) {
$title = !empty($instance['title']) ? $instance['title'] : __('推荐广告', 'fasc');
$campaign_id = !empty($instance['campaign_id']) ? $instance['campaign_id'] : 0;
// 获取所有活跃广告活动
global $wpdb;
$table_name = $wpdb->prefix . 'fasc_campaigns';
$campaigns = $wpdb->get_results(
"SELECT id, title FROM $table_name WHERE status = 'active' ORDER BY created_at DESC"
);
?>
<p>
<label for="<?php echo esc_attr($this->get_field_id('title')); ?>">
<?php _e('标题:', 'fasc'); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr($this->get_field_id('title')); ?>"
name="<?php echo esc_attr($this->get_field_name('title')); ?>"
type="text"
value="<?php echo esc_attr($title); ?>">
</p>
<p>
<label for="<?php echo esc_attr($this->get_field_id('campaign_id')); ?>">
<?php _e('选择广告活动:', 'fasc'); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr($this->get_field_id('campaign_id')); ?>"
name="<?php echo esc_attr($this->get_field_name('campaign_id')); ?>">
<option value="0"><?php _e('自动选择', 'fasc'); ?></option>
<?php foreach ($campaigns as $campaign): ?>
<option value="<?php echo esc_attr($campaign->id); ?>"
<?php selected($campaign_id, $campaign->id); ?>>
<?php echo esc_html($campaign->title); ?>
</option>
<?php endforeach; ?>
</select>
</p>
<?php
}
public function update($new_instance, $old_instance) {
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
$instance['campaign_id'] = (!empty($new_instance['campaign_id'])) ? intval($new_instance['campaign_id']) : 0;
return $instance;
}
}
// 注册小工具
add_action('widgets_init', function() {
register_widget('FASC_Ad_Widget');
});
?>
区块链连接器
Web3集成类
<?php
/**
* 区块链连接器类
*/
class FASC_Blockchain_Connector {
private $web3;
private $contract_address;
private $contract_abi;
private $account_address;
private $private_key;
public function __construct() {
// 从设置中获取配置
$this->contract_address = get_option('fasc_contract_address');
$this->account_address = get_option('fasc_account_address');
$this->private_key = get_option('fasc_private_key');
// 初始化Web3连接
$this->init_web3();
// 加载合约ABI
$this->load_contract_abi();
}
private function init_web3() {
// 使用Web3.php库
$provider_url = get_option('fasc_provider_url', 'https://mainnet.infura.io/v3/YOUR_INFURA_KEY');
try {
$this->web3 = new Web3Web3(new Web3ProvidersHttpProvider(new Web3RequestManagersHttpRequestManager($provider_url, 30)));
} catch (Exception $e) {
error_log('Web3初始化失败: ' . $e->getMessage());
}
}
private function load_contract_abi() {
// 从文件加载合约ABI
$abi_file = FASC_PLUGIN_DIR . 'contracts/FlexibleAdContract.json';
if (file_exists($abi_file)) {
$abi_content = file_get_contents($abi_file);
$abi_data = json_decode($abi_content, true);
$this->contract_abi = $abi_data['abi'];
}
}
/**
* 创建广告活动
*/
public function create_campaign($data) {
try {
// 构建合约调用
$contract = new Web3Contract($this->web3->provider, $this->contract_abi);
// 估算Gas费用
$gas_estimate = $this->estimate_gas('createCampaign', [
$data['title'],
$data['budget'],
$data['cpc'],
$data['maxImpressions'],
$data['duration']
]);
// 构建交易
$transaction = [
'from' => $this->account_address,
'to' => $this->contract_address,
'value' => '0x' . dechex($data['budget']),
'gas' => '0x' . dechex($gas_estimate * 2), // 2倍估算值作为安全边际
'gasPrice' => $this->get_gas_price(),
'data' => $contract->getData('createCampaign',
$data['title'],
$data['budget'],
$data['cpc'],
$data['maxImpressions'],
$data['duration']
)
];
// 签名并发送交易
$signed_tx = $this->sign_transaction($transaction);
$tx_hash = $this->send_raw_transaction($signed_tx);
// 等待交易确认
$receipt = $this->wait_for_transaction_receipt($tx_hash);
if ($receipt && $receipt['status'] === '0x1') {
// 从事件日志中提取活动ID
$campaign_id = $this->extract_campaign_id_from_logs($receipt['logs']);
return [
'success' => true,
'transaction_hash' => $tx_hash,
'campaign_id' => $campaign_id,
'contract_address' => $this->contract_address
];
}
return ['success' => false, 'error' => '交易失败'];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
/**
* 记录广告展示
*/
public function record_impression($campaign_id) {
try {
$contract = new Web3Contract($this->web3->provider, $this->contract_abi);
// 调用合约方法(不发送交易,只调用视图函数)
$contract->at($this->contract_address)->call('recordImpression', $campaign_id, [
'from' => $this->account_address
]);
return ['success' => true];
} catch (Exception $e) {
error_log('记录展示失败: ' . $e->getMessage());
return ['success' => false, 'error' => $e->getMessage()];
}
}
/**
* 记录广告点击
*/
public function record_click($campaign_id) {
try {
$contract = new Web3Contract($this->web3->provider, $this->contract_abi);
$gas_estimate = $this->estimate_gas('recordClick', [$campaign_id]);
$transaction = [
'from' => $this->account_address,
'to' => $this->contract_address,
'value' => '0x0',
'gas' => '0x' . dechex($gas_estimate * 2),
'gasPrice' => $this->get_gas_price(),
'data' => $contract->getData('recordClick', $campaign_id)
];
$signed_tx = $this->sign_transaction($transaction);
$tx_hash = $this->send_raw_transaction($signed_tx);
$receipt = $this->wait_for_transaction_receipt($tx_hash);
if ($receipt && $receipt['status'] === '0x1') {
return [
'success' => true,
'transaction_hash' => $tx_hash
];
}
return ['success' => false, 'error' => '点击记录失败'];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
/**
* 获取广告活动详情
*/
public function get_campaign_details($campaign_id) {
try {
$contract = new Web3Contract($this->web3->provider, $this->contract_abi);
$details = $contract->at($this->contract_address)->call('getCampaignDetails', $campaign_id, [
'from' => $this->account_address
]);
return [
'success' => true,
'data' => $details
];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
/**
* 估算Gas费用
*/
private function estimate_gas($method, $params) {
$contract = new Web3Contract($this->web3->provider, $this->contract_abi);
$data = $contract->getData($method, ...$params);
$gas = 0;
$this->web3->eth->estimateGas([
'from' => $this->account_address,
'to' => $this->contract_address,
'data' => $data
], function ($err, $result) use (&$gas) {
if ($err !== null) {
throw new Exception($err->getMessage());
}
$gas = hexdec($result->toString());
});
return $gas;
}
/**
* 获取当前Gas价格
*/
private function get_gas_price() {
$gas_price = '0x0';
$this->web3->eth->gasPrice(function ($err, $result) use (&$gas_price) {
if ($err === null) {
$gas_price = $result->toString();
}
});
return $gas_price;
}
/**
* 签名交易
*/
private function sign_transaction($transaction) {
// 使用以太坊PHP库进行签名
// 注意:实际生产环境中应使用更安全的方式管理私钥
$signed = '';
// 这里简化处理,实际应使用web3.php或ethereum-php的签名功能
// 或者使用MetaMask等浏览器扩展
return $signed;
}
/**
* 发送原始交易
*/
private function send_raw_transaction($signed_tx) {
$tx_hash = '';
$this->web3->eth->sendRawTransaction($signed_tx, function ($err, $result) use (&$tx_hash) {
if ($err === null) {
$tx_hash = $result;
}
});
return $tx_hash;
}
/**
* 等待交易确认
*/
private function wait_for_transaction_receipt($tx_hash, $timeout = 60) {
$start_time = time();
while (time() - $start_time < $timeout) {
$receipt = null;
$this->web3->eth->getTransactionReceipt($tx_hash, function ($err, $result) use (&$receipt) {
if ($err === null && $result !== null) {
$receipt = $result;
}
});
if ($receipt !== null) {
return $receipt;
}
sleep(3); // 等待3秒再检查
}
return null;
}
/**
* 从事件日志中提取活动ID
*/
private function extract_campaign_id_from_logs($logs) {
if (!empty($logs) && is_array($logs)) {
foreach ($logs as $log) {
if (isset($log['topics'][0]) &&
$log['topics'][0] === '0x' . bin2hex('CampaignCreated(uint256,address)')) {
// 解码事件数据
$campaign_id_hex = substr($log['data'], 2, 64);
return hexdec($campaign_id_hex);
}
}
}
return 0;
}
}
?>
管理界面
广告活动管理页面
<?php
/**
* 广告活动管理页面
*/
class FASC_Admin_Pages {
public function __construct() {
add_action('admin_menu', array($this, 'add_admin_menus'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
}
public function add_admin_menus() {
// 主菜单
add_menu_page(
__('柔性广告智能合约', 'fasc'),
__('柔性广告', 'fasc'),
'manage_options',
'fasc-dashboard',
array($this, 'render_dashboard_page'),
'dashicons-money-alt',
30
);
// 子菜单
add_submenu_page(
'fasc-dashboard',
__('广告活动', 'fasc'),
__('广告活动', 'fasc'),
'manage_options',
'fasc-campaigns',
array($this, 'render_campaigns_page')
);
add_submenu_page(
'fasc-dashboard',
__('创建广告', 'fasc'),
__('创建广告', 'fasc'),
'manage_options',
'fasc-create-campaign',
array($this, 'render_create_campaign_page')
);
add_submenu_page(
'fasc-dashboard',
__('统计数据', 'fasc'),
__('统计数据', 'fasc'),
'manage_options',
'fasc-statistics',
array($this, 'render_statistics_page')
);
add_submenu_page(
'fasc-dashboard',
__('设置', 'fasc'),
__('设置', 'fasc'),
'manage_options',
'fasc-settings',
array($this, 'render_settings_page')
);
}
public function render_dashboard_page() {
?>
<div class="wrap fasc-admin">
<h1><?php _e('柔性广告智能合约仪表板', 'fasc'); ?></h1>
<div class="fasc-dashboard-widgets">
<div class="fasc-widget">
<h3><?php _e('今日数据', 'fasc'); ?></h3>
<div class="fasc-stats">
