| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <?php
- namespace App\Module\OpenAPI\Validators;
- use App\Module\Fund\Enums\FUND_CURRENCY_TYPE;
- use App\Module\Fund\Services\CurrencyService;
- use UCore\Validator;
- /**
- * 钻石金额验证器
- *
- * 验证钻石金额的格式和精度
- */
- class DiamondAmountValidator extends Validator
- {
- /**
- * 验证钻石金额
- *
- * @param mixed $value 要验证的值
- * @param array $data 完整的数据数组
- * @return bool
- */
- public function validate(mixed $value, array $data): bool
- {
- // 检查是否为数字
- if (!is_numeric($value)) {
- $this->addError('金额必须为数字');
- return false;
- }
- $amount = (float)$value;
- // 检查金额是否为正数
- if ($amount <= 0) {
- $this->addError('金额必须大于0');
- return false;
- }
- // 获取钻石币种的精度
- $precision = FUND_CURRENCY_TYPE::ZUANSHI->getPrecision();
- // 验证金额精度
- if (!$this->validatePrecision($amount, $precision)) {
- $this->addError("金额精度不能超过{$precision}位小数");
- return false;
- }
- // 检查金额范围(最大值)
- $maxAmount = 999999999.9999999999; // 10位小数的最大合理值
- if ($amount > $maxAmount) {
- $this->addError("金额不能超过{$maxAmount}");
- return false;
- }
- // 格式化金额到正确的精度
- $formattedAmount = $this->formatAmountToPrecision($amount, $precision);
-
- // 将格式化后的金额设置到验证对象中
- if (isset($this->args['formattedAmount'])) {
- $this->validation->formattedAmount = $formattedAmount;
- }
- return true;
- }
- /**
- * 验证金额精度
- *
- * @param float $amount 金额
- * @param int $precision 允许的小数位数
- * @return bool
- */
- private function validatePrecision(float $amount, int $precision): bool
- {
- // 将金额转换为字符串以检查小数位数
- $amountStr = (string)$amount;
-
- // 如果包含小数点
- if (strpos($amountStr, '.') !== false) {
- $parts = explode('.', $amountStr);
- $decimalPart = $parts[1];
-
- // 移除末尾的0
- $decimalPart = rtrim($decimalPart, '0');
-
- // 检查小数位数
- if (strlen($decimalPart) > $precision) {
- return false;
- }
- }
- return true;
- }
- /**
- * 格式化金额到指定精度
- *
- * @param float $amount 原始金额
- * @param int $precision 精度
- * @return float
- */
- private function formatAmountToPrecision(float $amount, int $precision): float
- {
- // 使用 bcmath 进行高精度计算
- if (function_exists('bcadd')) {
- return (float)bcadd((string)$amount, '0', $precision);
- }
-
- // 如果没有 bcmath,使用 number_format
- return (float)number_format($amount, $precision, '.', '');
- }
- /**
- * 获取验证器描述
- *
- * @return string
- */
- public function getDescription(): string
- {
- return '验证钻石金额的格式和精度,确保符合系统要求';
- }
- }
|