|
|
@@ -0,0 +1,206 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Module\Mex\Listeners;
|
|
|
+
|
|
|
+use App\Module\Mex\Events\TransactionCreatedEvent;
|
|
|
+use Illuminate\Support\Facades\Log;
|
|
|
+use Illuminate\Support\Facades\Cache;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 成交记录创建监听器
|
|
|
+ *
|
|
|
+ * 处理成交记录创建后的相关操作
|
|
|
+ */
|
|
|
+class TransactionCreatedListener
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * 处理事件
|
|
|
+ */
|
|
|
+ public function handle(TransactionCreatedEvent $event): void
|
|
|
+ {
|
|
|
+ $transaction = $event->transaction;
|
|
|
+
|
|
|
+ // 记录详细日志
|
|
|
+ Log::info('Mex成交记录创建', [
|
|
|
+ 'transaction_id' => $transaction->id,
|
|
|
+ 'buyer_id' => $transaction->buyer_id,
|
|
|
+ 'seller_id' => $transaction->seller_id,
|
|
|
+ 'item_id' => $transaction->item_id,
|
|
|
+ 'quantity' => $transaction->quantity,
|
|
|
+ 'price' => $transaction->price,
|
|
|
+ 'total_amount' => $transaction->total_amount,
|
|
|
+ 'transaction_type' => $transaction->transaction_type->value,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ // 清除相关缓存
|
|
|
+ $this->clearRelatedCache($transaction);
|
|
|
+
|
|
|
+ // 更新市场统计
|
|
|
+ $this->updateMarketStats($transaction);
|
|
|
+
|
|
|
+ // 更新价格趋势
|
|
|
+ $this->updatePriceTrend($transaction);
|
|
|
+
|
|
|
+ // 检查异常交易
|
|
|
+ $this->checkAbnormalTransaction($transaction);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清除相关缓存
|
|
|
+ */
|
|
|
+ protected function clearRelatedCache($transaction): void
|
|
|
+ {
|
|
|
+ $cachePrefix = config('mex.cache.prefix', 'mex:');
|
|
|
+
|
|
|
+ // 清除商品相关缓存
|
|
|
+ Cache::forget($cachePrefix . "item_stats:{$transaction->item_id}");
|
|
|
+ Cache::forget($cachePrefix . "item_price_trend:{$transaction->item_id}");
|
|
|
+ Cache::forget($cachePrefix . "latest_price:{$transaction->item_id}");
|
|
|
+
|
|
|
+ // 清除用户交易缓存
|
|
|
+ Cache::forget($cachePrefix . "user_transactions:{$transaction->buyer_id}");
|
|
|
+ Cache::forget($cachePrefix . "user_transactions:{$transaction->seller_id}");
|
|
|
+
|
|
|
+ // 清除市场统计缓存
|
|
|
+ Cache::forget($cachePrefix . 'market_stats');
|
|
|
+ Cache::forget($cachePrefix . 'warehouse_stats');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新市场统计
|
|
|
+ */
|
|
|
+ protected function updateMarketStats($transaction): void
|
|
|
+ {
|
|
|
+ $cachePrefix = config('mex.cache.prefix', 'mex:');
|
|
|
+ $today = date('Y-m-d');
|
|
|
+
|
|
|
+ // 更新今日交易统计
|
|
|
+ $statsKey = $cachePrefix . "daily_stats:{$today}";
|
|
|
+ $stats = Cache::get($statsKey, [
|
|
|
+ 'total_transactions' => 0,
|
|
|
+ 'total_volume' => '0.00000',
|
|
|
+ 'total_quantity' => 0,
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $stats['total_transactions']++;
|
|
|
+ $stats['total_volume'] = bcadd($stats['total_volume'], $transaction->total_amount, 5);
|
|
|
+ $stats['total_quantity'] += $transaction->quantity;
|
|
|
+
|
|
|
+ Cache::put($statsKey, $stats, 86400); // 缓存24小时
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新价格趋势
|
|
|
+ */
|
|
|
+ protected function updatePriceTrend($transaction): void
|
|
|
+ {
|
|
|
+ $cachePrefix = config('mex.cache.prefix', 'mex:');
|
|
|
+
|
|
|
+ // 更新最新价格
|
|
|
+ $latestPriceKey = $cachePrefix . "latest_price:{$transaction->item_id}";
|
|
|
+ Cache::put($latestPriceKey, $transaction->price, 3600);
|
|
|
+
|
|
|
+ // 更新价格历史
|
|
|
+ $priceHistoryKey = $cachePrefix . "price_history:{$transaction->item_id}";
|
|
|
+ $history = Cache::get($priceHistoryKey, []);
|
|
|
+
|
|
|
+ $history[] = [
|
|
|
+ 'price' => $transaction->price,
|
|
|
+ 'quantity' => $transaction->quantity,
|
|
|
+ 'timestamp' => time(),
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 只保留最近100条记录
|
|
|
+ if (count($history) > 100) {
|
|
|
+ $history = array_slice($history, -100);
|
|
|
+ }
|
|
|
+
|
|
|
+ Cache::put($priceHistoryKey, $history, 3600);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查异常交易
|
|
|
+ */
|
|
|
+ protected function checkAbnormalTransaction($transaction): void
|
|
|
+ {
|
|
|
+ // 检查价格异常波动
|
|
|
+ $this->checkPriceFluctuation($transaction);
|
|
|
+
|
|
|
+ // 检查大额交易
|
|
|
+ $this->checkLargeTransaction($transaction);
|
|
|
+
|
|
|
+ // 检查频繁交易
|
|
|
+ $this->checkFrequentTrading($transaction);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查价格异常波动
|
|
|
+ */
|
|
|
+ protected function checkPriceFluctuation($transaction): void
|
|
|
+ {
|
|
|
+ $cachePrefix = config('mex.cache.prefix', 'mex:');
|
|
|
+ $historyKey = $cachePrefix . "price_history:{$transaction->item_id}";
|
|
|
+ $history = Cache::get($historyKey, []);
|
|
|
+
|
|
|
+ if (count($history) >= 2) {
|
|
|
+ $lastPrice = end($history)['price'];
|
|
|
+ $currentPrice = $transaction->price;
|
|
|
+
|
|
|
+ $fluctuation = abs(($currentPrice - $lastPrice) / $lastPrice * 100);
|
|
|
+ $threshold = config('mex.monitoring.price_fluctuation_threshold', 50);
|
|
|
+
|
|
|
+ if ($fluctuation > $threshold) {
|
|
|
+ Log::warning('Mex价格异常波动', [
|
|
|
+ 'item_id' => $transaction->item_id,
|
|
|
+ 'last_price' => $lastPrice,
|
|
|
+ 'current_price' => $currentPrice,
|
|
|
+ 'fluctuation_percent' => $fluctuation,
|
|
|
+ 'transaction_id' => $transaction->id,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查大额交易
|
|
|
+ */
|
|
|
+ protected function checkLargeTransaction($transaction): void
|
|
|
+ {
|
|
|
+ $maxAmount = config('mex.security.max_order_amount', '100000.00000');
|
|
|
+
|
|
|
+ if (bccomp($transaction->total_amount, $maxAmount, 5) > 0) {
|
|
|
+ Log::warning('Mex大额交易', [
|
|
|
+ 'transaction_id' => $transaction->id,
|
|
|
+ 'total_amount' => $transaction->total_amount,
|
|
|
+ 'max_amount' => $maxAmount,
|
|
|
+ 'buyer_id' => $transaction->buyer_id,
|
|
|
+ 'seller_id' => $transaction->seller_id,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查频繁交易
|
|
|
+ */
|
|
|
+ protected function checkFrequentTrading($transaction): void
|
|
|
+ {
|
|
|
+ $cachePrefix = config('mex.cache.prefix', 'mex:');
|
|
|
+ $userIds = [$transaction->buyer_id, $transaction->seller_id];
|
|
|
+
|
|
|
+ foreach ($userIds as $userId) {
|
|
|
+ $key = $cachePrefix . "user_transaction_count:{$userId}:" . date('Y-m-d-H');
|
|
|
+ $count = Cache::increment($key, 1);
|
|
|
+ Cache::expire($key, 3600);
|
|
|
+
|
|
|
+ $threshold = config('mex.security.max_orders_per_hour', 100);
|
|
|
+ if ($count > $threshold) {
|
|
|
+ Log::warning('Mex频繁交易', [
|
|
|
+ 'user_id' => $userId,
|
|
|
+ 'hourly_count' => $count,
|
|
|
+ 'threshold' => $threshold,
|
|
|
+ 'transaction_id' => $transaction->id,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|