Transfer模块的手续费事件系统允许其他模块监听手续费计算过程,并根据业务需求修改手续费数额。这提供了一个灵活的扩展机制,支持各种复杂的手续费策略。
在手续费计算过程中触发,允许监听器修改手续费数额。
事件属性:
app: TransferApp - 划转应用amount: string - 原始金额type: string - 手续费类型('in' 或 'out')feeRate: float - 手续费率feeAmount: string - 手续费金额actualAmount: string - 实际到账金额isModified: bool - 是否被修改过modificationReason: string - 修改原因modifiedBy: string - 修改者标识context: array - 额外的上下文数据可用方法:
modifyFeeAmount(newFeeAmount, reason, modifiedBy) - 修改手续费金额modifyFeeRate(newFeeRate, reason, modifiedBy) - 修改手续费率setFree(reason, modifiedBy) - 设置免手续费addFee(additionalFee, reason, modifiedBy) - 增加手续费reduceFee(discountFee, reason, modifiedBy) - 减少手续费在手续费计算完成后触发,用于记录日志、统计等。
事件属性:
<?php
namespace App\Module\YourModule\Listeners;
use App\Module\Transfer\Events\FeeCalculatingEvent;
class YourFeeListener
{
public function handle(FeeCalculatingEvent $event): void
{
// 检查业务条件
if ($this->shouldApplyDiscount($event)) {
// 应用折扣
$event->reduceFee(
discountFee: '1.0000',
reason: '特殊用户折扣',
modifiedBy: 'YourModule'
);
}
}
private function shouldApplyDiscount(FeeCalculatingEvent $event): bool
{
// 你的业务逻辑
return true;
}
}
在你的模块的ServiceProvider中注册监听器:
use Illuminate\Support\Facades\Event;
use App\Module\Transfer\Events\FeeCalculatingEvent;
use App\Module\YourModule\Listeners\YourFeeListener;
public function boot()
{
Event::listen(
FeeCalculatingEvent::class,
YourFeeListener::class
);
}
在调用手续费计算时传递上下文数据:
// 在创建订单时传递用户信息
$feeResult = TransferService::calculateOutFee(
transferAppId: 1,
amount: '100.00',
context: [
'user_id' => 12345,
'order_type' => 'premium',
'source' => 'mobile_app'
]
);
在监听器中使用上下文数据:
public function handle(FeeCalculatingEvent $event): void
{
$userId = $event->getContext('user_id');
$orderType = $event->getContext('order_type');
if ($orderType === 'premium') {
// 高级订单享受优惠
$event->reduceFee('0.5000', '高级订单优惠', 'PremiumService');
}
}
public function handle(FeeCalculatingEvent $event): void
{
$userId = $event->getContext('user_id');
if ($this->userService->isVip($userId)) {
// VIP用户50%折扣
$discount = bcmul($event->feeAmount, '0.5', 4);
$event->reduceFee($discount, 'VIP用户50%折扣', 'VipService');
}
}
public function handle(FeeCalculatingEvent $event): void
{
if (bccomp($event->amount, '1000.0000', 4) >= 0) {
// 大额交易手续费上限
if (bccomp($event->feeAmount, '10.0000', 4) > 0) {
$event->modifyFeeAmount('10.0000', '大额交易上限', 'LargeAmountService');
}
}
}
public function handle(FeeCalculatingEvent $event): void
{
$partnerAppIds = [1, 2, 3];
if (in_array($event->app->id, $partnerAppIds)) {
$event->setFree('合作伙伴免费', 'PartnerService');
}
}
public function handle(FeeCalculatingEvent $event): void
{
// 根据市场情况动态调整手续费率
$marketRate = $this->marketService->getCurrentFeeRate();
if ($marketRate !== $event->feeRate) {
$event->modifyFeeRate($marketRate, '市场动态调整', 'MarketService');
}
}
public function handle(FeeCalculatingEvent $event): void
{
$hour = now()->hour;
// 夜间时段优惠
if ($hour >= 22 || $hour <= 6) {
$discount = bcmul($event->feeAmount, '0.3', 4);
$event->reduceFee($discount, '夜间时段70%折扣', 'TimeDiscountService');
}
}
如果有多个监听器,注意处理顺序:
// 在监听器中检查是否已被修改
public function handle(FeeCalculatingEvent $event): void
{
if ($event->isModified) {
// 已经被其他监听器修改过,可以选择跳过或继续处理
return;
}
// 你的处理逻辑
}
记录手续费修改的详细信息:
public function handle(FeeCalculatingEvent $event): void
{
$originalFee = $event->feeAmount;
// 应用你的逻辑
$event->reduceFee('1.0000', '特殊优惠', 'YourService');
Log::info('手续费优惠应用', [
'app_id' => $event->app->id,
'amount' => $event->amount,
'original_fee' => $originalFee,
'final_fee' => $event->feeAmount,
'reason' => '特殊优惠',
]);
}
在监听器中添加错误处理:
public function handle(FeeCalculatingEvent $event): void
{
try {
// 你的业务逻辑
if ($this->shouldApplyDiscount($event)) {
$event->reduceFee('1.0000', '优惠', 'YourService');
}
} catch (\Exception $e) {
Log::error('手续费监听器错误', [
'error' => $e->getMessage(),
'app_id' => $event->app->id,
'amount' => $event->amount,
]);
// 不要重新抛出异常,避免影响主流程
}
}
避免在监听器中执行耗时操作:
public function handle(FeeCalculatingEvent $event): void
{
// 使用缓存避免重复查询
$userLevel = Cache::remember(
"user_level_{$event->getContext('user_id')}",
300, // 5分钟缓存
fn() => $this->userService->getUserLevel($event->getContext('user_id'))
);
if ($userLevel === 'premium') {
$event->reduceFee('0.5000', '高级用户优惠', 'UserLevelService');
}
}
这个事件系统提供了极大的扩展性: