TransferBalanceValidator.php 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. <?php
  2. namespace App\Module\Transfer\Validators;
  3. use App\Module\Fund\Services\FundService;
  4. use App\Module\Transfer\Models\TransferApp;
  5. use UCore\Validator;
  6. /**
  7. * 转账余额验证器
  8. * 验证用户余额是否充足以支付转出金额
  9. */
  10. class TransferBalanceValidator extends Validator
  11. {
  12. /**
  13. * 验证用户余额是否充足
  14. *
  15. * @param mixed $value 转出金额
  16. * @param array $data 验证数据
  17. * @return bool
  18. */
  19. public function validate(mixed $value, array $data): bool
  20. {
  21. // 检查必需的参数
  22. if (!isset($data['user_id']) || !isset($data['transfer_app_id'])) {
  23. $this->addError('缺少必需的用户ID或应用ID参数', 'amount');
  24. return false;
  25. }
  26. $userId = $data['user_id'];
  27. $transferAppId = $data['transfer_app_id'];
  28. $inputAmount = (string) $value; // 输入金额
  29. // 验证金额是否为正数
  30. if (bccomp($inputAmount, '0', 10) <= 0) {
  31. $this->addError('转出金额必须大于0', 'amount');
  32. return false;
  33. }
  34. try {
  35. // 获取转账应用配置
  36. $transferApp = TransferApp::find($transferAppId);
  37. if (!$transferApp) {
  38. $this->addError('转账应用不存在', 'transfer_app_id');
  39. return false;
  40. }
  41. // 检查应用是否启用
  42. if (!$transferApp->is_enabled) {
  43. $this->addError('转账应用已禁用', 'transfer_app_id');
  44. return false;
  45. }
  46. // 检查是否允许转出
  47. if (!$transferApp->allow_transfer_out) {
  48. $this->addError('该应用不允许转出操作', 'transfer_app_id');
  49. return false;
  50. }
  51. // 获取用户资金服务
  52. $fundService = new FundService($userId, $transferApp->fund_id);
  53. // 检查用户账户是否存在
  54. if (!$fundService->getAccount()) {
  55. $this->addError('用户资金账户不存在', 'user_id');
  56. return false;
  57. }
  58. // 获取用户当前余额
  59. $userBalance = $fundService->balance();
  60. // 验证器接收到的金额统一为内部金额(调用方已经完成转换)
  61. $amountToCheck = $inputAmount;
  62. $amountDescription = "内部金额 {$inputAmount}";
  63. // 计算手续费(基于内部金额)
  64. $feeInfo = $transferApp->calculateOutFee($amountToCheck);
  65. $totalRequired = bcadd($amountToCheck, $feeInfo['fee_amount'], 10); // 总需要金额 = 转出金额 + 手续费
  66. // 验证余额是否充足
  67. if (bccomp((string) $userBalance, $totalRequired, 10) < 0) {
  68. $this->addError("余额不足,当前余额:{$userBalance},需要金额:{$totalRequired}({$amountDescription})", 'amount');
  69. return false;
  70. }
  71. // 将转账应用对象设置到验证器中,供后续使用
  72. if (property_exists($this->validation, 'transfer_app')) {
  73. $this->validation->transfer_app = $transferApp;
  74. }
  75. return true;
  76. } catch (\Exception $e) {
  77. $this->addError('余额验证失败:' . $e->getMessage(), 'amount');
  78. return false;
  79. }
  80. }
  81. }