From d2b499d14a4ab43e42ae3a3116c0afac8632d600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=99=AF=E7=AB=8B?= Date: Sun, 1 Feb 2026 13:27:10 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BD=BF=E7=94=A8=20BC=20Math=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E6=B5=AE=E7=82=B9=E8=BF=90=E7=AE=97=E4=BB=A5?= =?UTF-8?q?=E6=8F=90=E9=AB=98=E7=B2=BE=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将多处基于浮点的数值计算替换为 BC Math 字符串运算以避免浮点精度问题,涉及支付、退款、转账、比较与统计逻辑的重构。主要改动包括: - 将比较与判断替换为 bccomp,累加与合并使用 bcadd,乘以 100 等使用 bcmul; - 将部分初始数值与统计结果从数值类型改为字符串形式(如 '0.00'),并调整相关返回类型(如 Payment::paidAmount 改为返回 string); - 修正订单/退款金额计算与超额校验逻辑以使用高精度算术; - 更新微信支付相关 SDK 调用中金额乘 100 的计算以避免精度误差; - 在若干插件中用高精度运算替换 floatval/int 转换(包括 SystemQueue、Wemall、Wuma 等); - 更新文档(readme)添加 BC Math/高精度计算等说明并统一版权年份至 2014-2026; - 新增 .copilot-commit-message-instructions.md(提交信息规范)。 此改动旨在增强金融/金额相关业务的计算正确性与一致性,避免因浮点运算导致的金额误差。 --- .copilot-commit-message-instructions.md | 4 ++++ plugin/think-library/readme.md | 4 ++++ plugin/think-library/src/model/SystemQueue.php | 2 +- plugin/think-plugs-account/readme.md | 9 +++++---- plugin/think-plugs-payment/readme.md | 5 ++++- .../src/service/Payment.php | 18 +++++++++--------- .../src/service/payment/BalancePayment.php | 2 +- .../src/service/payment/IntegralPayment.php | 2 +- .../service/payment/wechat/WechatPaymentV2.php | 4 ++-- .../service/payment/wechat/WechatPaymentV3.php | 2 +- .../src/service/PaymentService.php | 12 ++++++------ plugin/think-plugs-wemall/readme.md | 6 ++++-- .../think-plugs-wemall/src/command/Clear.php | 4 ++-- .../think-plugs-wemall/src/command/Trans.php | 2 +- .../src/controller/base/Agent.php | 2 +- plugin/think-plugs-wuma/readme.md | 6 ++++-- .../src/service/CodeService.php | 2 +- .../src/service/WhCoderService.php | 2 +- readme.md | 5 +++++ 19 files changed, 57 insertions(+), 36 deletions(-) create mode 100644 .copilot-commit-message-instructions.md diff --git a/.copilot-commit-message-instructions.md b/.copilot-commit-message-instructions.md new file mode 100644 index 000000000..ae24faf7b --- /dev/null +++ b/.copilot-commit-message-instructions.md @@ -0,0 +1,4 @@ +请用中文生成提交信息,遵循规范提交格式: +- 标题:类型:以业务内容为主简短描述 +- 正文:详细说明改动原因与内容 +- 类型:feat/fix/docs/style/refactor/test/chore \ No newline at end of file diff --git a/plugin/think-library/readme.md b/plugin/think-library/readme.md index e796f4236..123cab71f 100644 --- a/plugin/think-library/readme.md +++ b/plugin/think-library/readme.md @@ -21,6 +21,7 @@ - **表单验证机制**: 支持规则别名和自定义验证,确保数据输入安全 - **异步任务队列**: 支持延时执行和循环任务,提升系统响应性能 - **CSRF 令牌验证**: 内置表单安全验证,防止跨站请求伪造攻击 +- **高精度计算支持**: 集成 BC Math 高精度数学函数,确保金融计算的准确性 **技术特性:** - **PSR-12 标准**: 严格遵循 PHP-FIG 编码规范,确保代码质量和可维护性 @@ -28,6 +29,7 @@ - **高性能优化**: 针对高并发场景进行专门优化,支持缓存和数据库连接池 - **异常处理完善**: 完善的异常捕获和日志记录机制,便于问题排查 - **向后兼容**: 保持 API 稳定性,确保平滑升级 +- **数据完整性保障**: 通过数据库约束确保业务数据的一致性和有效性 ## 功能说明 @@ -117,6 +119,8 @@ * **Github** 仓库地址:https://github.com/zoujingli/ThinkLibrary * **Gitcode** 仓库地址: https://gitcode.com/ThinkAdmin/ThinkLibrary +版权所有 Copyright © 2014-2026 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 + ## 使用说明 1. **依赖管理**:ThinkLibrary 需要 Composer 支持进行安装和依赖管理。 diff --git a/plugin/think-library/src/model/SystemQueue.php b/plugin/think-library/src/model/SystemQueue.php index 02a09d745..9c45d92bb 100644 --- a/plugin/think-library/src/model/SystemQueue.php +++ b/plugin/think-library/src/model/SystemQueue.php @@ -64,7 +64,7 @@ class SystemQueue extends Model */ public function getEnterTimeAttr($value): string { - return floatval($value) > 0 ? format_datetime(intval($value)) : ''; + return bccomp(strval($value), '0.00', 2) > 0 ? format_datetime(intval($value)) : ''; } /** diff --git a/plugin/think-plugs-account/readme.md b/plugin/think-plugs-account/readme.md index be28a77e8..c6b54124c 100644 --- a/plugin/think-plugs-account/readme.md +++ b/plugin/think-plugs-account/readme.md @@ -38,7 +38,7 @@ ### 加入我们 -我们的代码仓库已移至 **Github**,而 **Gitee** 则仅作为国内镜像仓库,方便广大开发者获取和使用。若想提交 **PR** 或 **ISSUE** 请在 [ThinkAdminDeveloper](https://github.com/zoujingli/ThinkAdminDeveloper) 仓库进行操作,如果在其他仓库操作或提交问题将无法处理!。 +我们的代码仓库已移至 **Github**,而 **Gitee** 则仅作为国内镜像仓库,方便广大开发者获取和使用。若想提交 **PR** 或 **ISSUE** 请在 [ThinkAdminDeveloper](https://github.com/zoujingli/ThinkAdminDeveloper) 仓库进行操作,如果在其他仓库操作或提交问题将无法处理!. ### 开放接口 @@ -165,13 +165,14 @@ var_dump($types); - **动态通道注册**: 支持运行时动态注册新的登录通道类型,灵活扩展登录方式 - **手机号绑定验证**: 通过短信验证码实现手机号绑定,确保账号安全性和唯一性 - **账号解绑管理**: 支持终端账号与主账号的灵活绑定和解绑操作 - -**技术特性:** - **高并发安全**: 支持高并发场景下的账号创建和绑定操作 - **数据一致性保障**: 通过数据库事务确保账号数据的一致性 + +**技术特性:** - **缓存优化**: 集成缓存机制,提升账号信息查询性能 - **异常处理完善**: 完善的异常捕获和错误处理机制 - **扩展性设计**: 抽象的账号接口设计,便于扩展新的认证方式 +- **向后兼容**: 保持 API 稳定性,确保平滑升级 ### 插件数据 @@ -188,4 +189,4 @@ var_dump($types); 未获得此插件授权时仅供参考学习不可商用,了解商用授权请阅读 [《会员授权》](https://thinkadmin.top/vip-introduce)。 -版权所有 Copyright © 2014-2025 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 \ No newline at end of file +版权所有 Copyright © 2014-2026 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 diff --git a/plugin/think-plugs-payment/readme.md b/plugin/think-plugs-payment/readme.md index 458b8caed..b4e11fdb9 100644 --- a/plugin/think-plugs-payment/readme.md +++ b/plugin/think-plugs-payment/readme.md @@ -68,6 +68,7 @@ composer remove zoujingli/think-plugs-payment - **支付事件驱动**: 通过支付事件(审核、完成、取消、确认)实现业务逻辑解耦 - **退款管理**: 支持部分退款和全额退款,自动处理余额、积分的退回操作 - **支付配置管理**: 可视化配置各种支付通道参数,支持动态启用/禁用支付方式 +- **高精度金融计算**: 全面采用 BC Math 高精度数学函数,确保金融计算的准确性,避免浮点数精度丢失问题 **账户资金管理:** - **余额管理系统**: 完整的余额充值、消费、锁定、解锁、作废等操作 @@ -75,12 +76,14 @@ composer remove zoujingli/think-plugs-payment - **高精度计算**: 使用 BC Math 高精度数学函数,确保金融计算的准确性 - **资金流水追踪**: 完整的资金变动记录,支持来源追溯和审计 - **并发安全控制**: 支持高并发场景下的余额和积分操作,避免超支问题 +- **数据完整性保障**: 通过数据库约束确保业务数据的一致性和有效性 **技术特性:** - **支付接口抽象**: 统一的支付接口标准,便于扩展新的支付方式 - **数据库约束优化**: 添加金额非负约束、状态枚举约束,确保数据完整性 - **异常处理机制**: 完善的异常捕获和日志记录,便于问题排查 - **事务一致性**: 关键业务操作保证数据一致性,避免脏数据产生 +- **向后兼容**: 保持 API 稳定性,确保平滑升级 ### 插件数据 @@ -99,4 +102,4 @@ composer remove zoujingli/think-plugs-payment 未获得此插件授权时仅供参考学习不可商用,了解商用授权请阅读 [《会员授权》](https://thinkadmin.top/vip-introduce)。 -版权所有 Copyright © 2014-2025 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 \ No newline at end of file +版权所有 Copyright © 2014-2026 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 diff --git a/plugin/think-plugs-payment/src/service/Payment.php b/plugin/think-plugs-payment/src/service/Payment.php index 951bf27da..2ff4e90ed 100644 --- a/plugin/think-plugs-payment/src/service/Payment.php +++ b/plugin/think-plugs-payment/src/service/Payment.php @@ -3,7 +3,7 @@ // +---------------------------------------------------------------------- // | Payment Plugin for ThinkAdmin // +---------------------------------------------------------------------- -// | 版权所有 2014~2025 ThinkAdmin [ thinkadmin.top ] +// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ] // +---------------------------------------------------------------------- // | 官方网站: https://thinkadmin.top // +---------------------------------------------------------------------- @@ -427,11 +427,11 @@ abstract class Payment * @param string $orderNo 订单单号 * @param bool $realtime 有效金额 */ - public static function paidAmount(string $orderNo, bool $realtime = false): float + public static function paidAmount(string $orderNo, bool $realtime = false): string { $map = ['order_no' => $orderNo, 'payment_status' => 1]; $raw = new Raw($realtime ? 'payment_amount - refund_amount' : 'payment_amount'); - return round(PluginPaymentRecord::mk()->where($map)->sum($raw), 2); + return bcadd('0.00', strval(PluginPaymentRecord::mk()->where($map)->sum($raw)), 2); } /** @@ -451,7 +451,7 @@ abstract class Payment */ public static function totalPaymentAmount(string $orderNo): array { - $total = ['amount' => 0, 'payment' => 0, 'balance' => 0, 'integral' => 0]; + $total = ['amount' => '0.00', 'payment' => '0.00', 'balance' => '0.00', 'integral' => '0.00']; try { PluginPaymentRecord::mk()->where(['order_no' => $orderNo, 'payment_status' => 1])->field([ 'channel_type', @@ -460,12 +460,12 @@ abstract class Payment 'sum(used_balance-refund_balance)' => 'balance', 'sum(used_integral-refund_integral)' => 'integral', ])->group('channel_type')->select()->map(static function (PluginPaymentRecord $item) use (&$total) { - $total['amount'] = round($total['amount'] + $item->getAttr('amount'), 2); + $total['amount'] = bcadd($total['amount'], strval($item->getAttr('amount')), 2); $type = $item->getAttr('channel_type'); if (!in_array($type, [self::INTEGRAL, self::BALANCE])) { $type = 'payment'; } - $total[$type] = round($total[$type] + $item[$type] ?? 0, 2); + $total[$type] = bcadd($total[$type], strval($item[$type] ?? '0.00'), 2); }); } catch (\Exception $exception) { trace_file($exception); @@ -479,17 +479,17 @@ abstract class Payment */ public static function totalRefundAmount(string $pCode): array { - $total = ['amount' => 0, 'payment' => 0, 'balance' => 0, 'integral' => 0]; + $total = ['amount' => '0.00', 'payment' => '0.00', 'balance' => '0.00', 'integral' => '0.00']; try { PluginPaymentRefund::mk()->where(['record_code' => $pCode, 'refund_status' => [0, 1]])->field([ 'refund_account', 'sum(refund_amount) amount', 'sum(used_payment)' => 'payment', 'sum(used_balance)' => 'balance', 'sum(used_integral)' => 'integral', ])->group('refund_account')->select()->map(static function (PluginPaymentRefund $item) use (&$total) { - $total['amount'] = round($total['amount'] + $item->getAttr('amount'), 2); + $total['amount'] = bcadd($total['amount'], strval($item->getAttr('amount')), 2); $type = $item->getAttr('refund_account'); if (!in_array($type, [self::INTEGRAL, self::BALANCE])) { $type = 'payment'; } - $total[$type] = round($total[$type] + $item[$type] ?? 0, 2); + $total[$type] = bcadd($total[$type], strval($item[$type] ?? '0.00'), 2); }); } catch (\Exception $exception) { trace_file($exception); diff --git a/plugin/think-plugs-payment/src/service/payment/BalancePayment.php b/plugin/think-plugs-payment/src/service/payment/BalancePayment.php index 892d40a5c..5d3165893 100644 --- a/plugin/think-plugs-payment/src/service/payment/BalancePayment.php +++ b/plugin/think-plugs-payment/src/service/payment/BalancePayment.php @@ -85,7 +85,7 @@ class BalancePayment implements PaymentInterface { try { // 记录并退回 - if (floatval($amount) <= 0) { + if (bccomp(strval($amount), '0.00', 2) <= 0) { return [1, '无需退款!']; } $record = static::syncRefund($pcode, $rcode, $amount, $reason); diff --git a/plugin/think-plugs-payment/src/service/payment/IntegralPayment.php b/plugin/think-plugs-payment/src/service/payment/IntegralPayment.php index bded9a20a..9ef9eab30 100644 --- a/plugin/think-plugs-payment/src/service/payment/IntegralPayment.php +++ b/plugin/think-plugs-payment/src/service/payment/IntegralPayment.php @@ -85,7 +85,7 @@ class IntegralPayment implements PaymentInterface { try { // 记录并退回 - if (floatval($amount) <= 0) { + if (bccomp(strval($amount), '0.00', 2) <= 0) { return [1, '无需退款!']; } $record = static::syncRefund($pcode, $rcode, $amount, $reason); diff --git a/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV2.php b/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV2.php index 50e957fa0..74b918882 100644 --- a/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV2.php +++ b/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV2.php @@ -92,7 +92,7 @@ class WechatPaymentV2 extends WechatPayment 'attach' => $this->cfgCode, 'out_trade_no' => $payCode, 'trade_type' => static::tradeTypes[$this->cfgType] ?? '', - 'total_fee' => intval(floatval($payAmount) * 100), + 'total_fee' => intval(strval(bcmul(strval($payAmount), '100', 0))), 'notify_url' => $this->withNotifyUrl($payCode), 'spbill_create_ip' => $this->app->request->ip(), ]; @@ -203,7 +203,7 @@ class WechatPaymentV2 extends WechatPayment 'out_trade_no' => $pcode, 'out_refund_no' => $rcode, 'total_fee' => intval($record->getAttr('payment_amount') * 100), - 'refund_fee' => intval(floatval($amount) * 100), + 'refund_fee' => intval(strval(bcmul(strval($amount), '100', 0))), 'notify_url' => static::withNotifyUrl($rcode, 'refund'), ]; if (strlen($reason) > 0) { diff --git a/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV3.php b/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV3.php index d084798eb..463a0ed8e 100644 --- a/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV3.php +++ b/plugin/think-plugs-payment/src/service/payment/wechat/WechatPaymentV3.php @@ -206,7 +206,7 @@ class WechatPaymentV3 extends WechatPayment 'notify_url' => static::withNotifyUrl($rcode, 'refund'), 'amount' => [ 'total' => intval($record->getAttr('payment_amount') * 100), - 'refund' => intval(floatval($amount) * 100), + 'refund' => intval(strval(bcmul(strval($amount), '100', 0))), 'currency' => 'CNY', ], ]; diff --git a/plugin/think-plugs-wechat/src/service/PaymentService.php b/plugin/think-plugs-wechat/src/service/PaymentService.php index a91b8b986..2406d8e7c 100644 --- a/plugin/think-plugs-wechat/src/service/PaymentService.php +++ b/plugin/think-plugs-wechat/src/service/PaymentService.php @@ -84,8 +84,8 @@ class PaymentService return ['code' => 1, 'info' => '已完成支付!', 'data' => [], 'params' => []]; } // 检查剩余支付金额 - $pAmount = floatval(is_null($pAmount) ? (floatval($oAmount) - $oPayed) : $pAmount); - if ($oPayed + $pAmount > floatval($oAmount)) { + $pAmount = strval(is_null($pAmount) ? (bcsub(strval($oAmount), strval($oPayed), 2)) : $pAmount); + if (bccomp(bcadd(strval($oPayed), $pAmount, 2), strval($oAmount), 2) > 0) { return ['code' => 0, 'info' => '支付总额超出!', 'data' => [], 'params' => []]; } $config = WechatService::getConfig(true); @@ -218,7 +218,7 @@ class PaymentService if ($record->getAttr('refund_amount') >= $record->getAttr('payment_amount')) { return [1, '该订单已完成退款!']; } - if ($record->getAttr('refund_amount') + floatval($amount) > $record->getAttr('payment_amount')) { + if (bccomp(bcadd(strval($record->getAttr('refund_amount')), strval($amount), 2), strval($record->getAttr('payment_amount')), 2) > 0) { return [0, '退款大于支付金额!']; } // 创建支付退款申请 @@ -232,7 +232,7 @@ class PaymentService 'out_refund_no' => $rcode, 'notify_url' => static::withNotifyUrl($rcode, 'refund'), 'amount' => [ - 'refund' => intval(floatval($amount) * 100), + 'refund' => intval(strval(bcmul(strval($amount), '100', 0))), 'total' => intval($record->getAttr('payment_amount') * 100), 'currency' => 'CNY', ], @@ -372,10 +372,10 @@ class PaymentService protected static function createPaymentAction(string $openid, string $oCode, string $oName, string $oAmount, string $pType, string $pCode, string $pAmount): array { // 检查是否已经支付 - if (static::withPayed($oCode, $oPayed) >= floatval($oAmount)) { + if (bccomp(strval(self::withPayed($oCode, $oPayed)), strval($oAmount), 2) >= 0) { throw new Exception('已经完成支付', 1); } - if ($oPayed + floatval($pAmount) > floatval($oAmount)) { + if (bccomp(bcadd(strval($oPayed), strval($pAmount), 2), strval($oAmount), 2) > 0) { throw new Exception('总支付超出金额', 0); } $map = ['order_code' => $oCode, 'payment_status' => 1]; diff --git a/plugin/think-plugs-wemall/readme.md b/plugin/think-plugs-wemall/readme.md index 3d07f041f..14dd6af73 100644 --- a/plugin/think-plugs-wemall/readme.md +++ b/plugin/think-plugs-wemall/readme.md @@ -13,7 +13,7 @@ ### 加入我们 -我们的代码仓库已移至 **Github**,而 **Gitee** 则仅作为国内镜像仓库,方便广大开发者获取和使用。若想提交 **PR** 或 **ISSUE** 请在 [ThinkAdminDeveloper](https://github.com/zoujingli/ThinkAdminDeveloper) 仓库进行操作,如果在其他仓库操作或提交问题将无法处理!。 +我们的代码仓库已移至 **Github**,而 **Gitee** 则仅作为国内镜像仓库,方便广大开发者获取和使用。若想提交 **PR** 或 **ISSUE** 请在 [ThinkAdminDeveloper](https://github.com/zoujingli/ThinkAdminDeveloper) 仓库进行操作,如果在其他仓库操作或提交问题将无法处理!. ### 依赖插件 @@ -59,6 +59,7 @@ composer remove zoujingli/think-plugs-wemall - **订单全流程管理**: 从下单、支付、发货到售后的完整订单生命周期管理 - **推广海报管理**: 支持为不同用户等级生成个性化推广海报 - **团队业绩统计**: 实时统计团队销售业绩和返佣数据 +- **高精度计算保障**: 全面采用 BC Math 高精度计算,避免浮点数精度丢失问题 **技术特性:** - **高精度金融计算**: 使用 BC Math 高精度计算,避免浮点数精度丢失问题 @@ -66,6 +67,7 @@ composer remove zoujingli/think-plugs-wemall - **数据库约束优化**: 添加完整的外键约束、检查约束和索引优化 - **并发安全处理**: 支持高并发场景下的余额、积分、库存操作 - **数据完整性保障**: 通过数据库约束确保业务数据的一致性和有效性 +- **向后兼容**: 保持 API 稳定性,确保平滑升级 ### 插件数据 @@ -84,4 +86,4 @@ composer remove zoujingli/think-plugs-wemall 未获得此插件授权时仅供参考学习不可商用,了解商用授权请阅读 [《会员授权》](https://thinkadmin.top/vip-introduce)。 -版权所有 Copyright © 2014-2025 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 \ No newline at end of file +版权所有 Copyright © 2014-2026 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 diff --git a/plugin/think-plugs-wemall/src/command/Clear.php b/plugin/think-plugs-wemall/src/command/Clear.php index 65e70d456..5030ddfde 100644 --- a/plugin/think-plugs-wemall/src/command/Clear.php +++ b/plugin/think-plugs-wemall/src/command/Clear.php @@ -127,7 +127,7 @@ class Clear extends Command $this->queue->message(0, 0, '未启用订单自动取消功能!'); } else { try { - $time = time() - intval(floatval($this->config['cancel_time']) * 3600); + $time = time() - intval(strval($this->config['cancel_time']) * 3600); $remark = $this->config['cancel_text'] ?? '自动取消未完成支付'; $where = [['status', 'in', [1, 2, 3]], ['create_time', '<', date('Y-m-d H:i:s', $time)]]; [$count, $total] = [0, ($items = PluginWemallOrder::mk()->where($where)->select())->count()]; @@ -157,7 +157,7 @@ class Clear extends Command $this->queue->message(0, 0, '未启用订单自动清理功能!'); } else { try { - $time = time() - intval(floatval($this->config['remove_time']) * 3600); + $time = time() - intval(strval($this->config['remove_time']) * 3600); $remark = $this->config['remove_text'] ?? '系统自动清理已取消的订单!'; $where = [['status', '=', 0], ['deleted_status', '=', 0], ['create_time', '<', date('Y-m-d H:i:s', $time)]]; [$count, $total] = [0, ($items = PluginWemallOrder::mk()->where($where)->select())->count()]; diff --git a/plugin/think-plugs-wemall/src/command/Trans.php b/plugin/think-plugs-wemall/src/command/Trans.php index f5064f5a0..5db736b2f 100644 --- a/plugin/think-plugs-wemall/src/command/Trans.php +++ b/plugin/think-plugs-wemall/src/command/Trans.php @@ -112,7 +112,7 @@ class Trans extends Command */ private function createTransferV3(PluginWemallUserTransfer $model): array { - $amount = floatval($model->getAttr('amount')) - floatval($model->getAttr('charge_amount')); + $amount = strval(bcmul(bcsub(strval($model->getAttr('amount')), strval($model->getAttr('charge_amount')), 2), '100', 0)); return TransfersV3::instance($this->getConfig($model))->batchs([ 'out_batch_no' => "B{$model->getAttr('code')}", 'batch_name' => '微信余额提现', diff --git a/plugin/think-plugs-wemall/src/controller/base/Agent.php b/plugin/think-plugs-wemall/src/controller/base/Agent.php index d499e19b2..2a47ed1c8 100644 --- a/plugin/think-plugs-wemall/src/controller/base/Agent.php +++ b/plugin/think-plugs-wemall/src/controller/base/Agent.php @@ -126,7 +126,7 @@ class Agent extends Controller $key = "{$ats[0]}_{$ats[1]}_status"; if ($vo['number'] > 0) { isset($vo['extra'][$key]) || $vo['extra'][$key] = 0; - floatval($v) > 0 ? ++$count : ($vo['extra'][$key] = 0); + bccomp(strval($v), '0.00', 2) > 0 ? ++$count : ($vo['extra'][$key] = 0); } else { $vo['extra'][$k] = 0; $vo['extra'][$key] = 0; diff --git a/plugin/think-plugs-wuma/readme.md b/plugin/think-plugs-wuma/readme.md index 3bf0f65f5..a3314d05c 100644 --- a/plugin/think-plugs-wuma/readme.md +++ b/plugin/think-plugs-wuma/readme.md @@ -18,6 +18,7 @@ - **数据统计分析**: 提供扫码数据统计和分析,了解消费者行为 - **批量操作**: 支持物码的批量生成、导入、导出等操作 - **权限控制**: 完善的权限管理,确保数据安全 +- **高精度计算支持**: 集成 BC Math 高精度数学函数,确保金融计算的准确性 - **收费授权**: 作为收费授权插件,提供专业的技术支持和功能更新 **技术特性:** @@ -26,12 +27,13 @@ - **安全防护**: 内置数据加密和权限验证,确保系统安全 - **向后兼容**: 保持与现有 ThinkAdmin 版本的兼容性,确保平滑升级 - **专业支持**: 提供专业的技术支持和定期功能更新 +- **数据完整性保障**: 通过数据库约束确保业务数据的一致性和有效性 物码标签管理系统,此插件为收费授权插件,请联系作者获取授权,未授权不可商用。 ### 加入我们 -我们的代码仓库已移至 **Github**,而 **Gitee** 则仅作为国内镜像仓库,方便广大开发者获取和使用。若想提交 **PR** 或 **ISSUE** 请在 [ThinkAdminDeveloper](https://github.com/zoujingli/ThinkAdminDeveloper) 仓库进行操作,如果在其他仓库操作或提交问题将无法处理!。 +我们的代码仓库已移至 **Github**,而 **Gitee** 则仅作为国内镜像仓库,方便广大开发者获取和使用。若想提交 **PR** 或 **ISSUE** 请在 [ThinkAdminDeveloper](https://github.com/zoujingli/ThinkAdminDeveloper) 仓库进行操作,如果在其他仓库操作或提交问题将无法处理!. ### 安装插件 @@ -67,4 +69,4 @@ composer remove zoujingli/think-plugs-wuma 未获得此插件授权时仅供参考学习不可商用,了解商用授权请阅读 [《付费授权》](https://thinkadmin.top/fee-introduce.html)。 -版权所有 Copyright © 2014-2025 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 \ No newline at end of file +版权所有 Copyright © 2014-2026 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 diff --git a/plugin/think-plugs-wuma/src/service/CodeService.php b/plugin/think-plugs-wuma/src/service/CodeService.php index 9cf9c8e9d..ab54847c7 100644 --- a/plugin/think-plugs-wuma/src/service/CodeService.php +++ b/plugin/think-plugs-wuma/src/service/CodeService.php @@ -89,7 +89,7 @@ class CodeService public static function codever(string $code, int $full, int $size = 4): string { [$a, $b] = [base_convert($code, 10, $full - 1), base_convert(strrev($code), 10, $full - 2)]; - return substr(str_pad(strval(floatval($a) + floatval($b)), $size, '0', STR_PAD_LEFT), 0, $size); + return substr(str_pad(strval(bcadd(strval($a), strval($b), 2)), $size, '0', STR_PAD_LEFT), 0, $size); } /** diff --git a/plugin/think-plugs-wuma/src/service/WhCoderService.php b/plugin/think-plugs-wuma/src/service/WhCoderService.php index 5d18cc493..2d4f2ed06 100644 --- a/plugin/think-plugs-wuma/src/service/WhCoderService.php +++ b/plugin/think-plugs-wuma/src/service/WhCoderService.php @@ -276,7 +276,7 @@ class WhCoderService extends Service } elseif (in_array($attr[1], ['MAX', 'MID'])) { foreach ($rules['nums'] as $range => $num) { [$start, $after] = explode('-', $range); - if (floatval($start) <= floatval($attr[0]) && floatval($attr[0]) <= floatval($after)) { + if (bccomp(strval($start), strval($attr[0]), 2) <= 0 && bccomp(strval($attr[0]), strval($after), 2) <= 0) { $number = $num['mode'] === 1 ? $num['tomins'] : substr_count($strs, $code); $maps[$code] = $code . '#' . $number; $count += $number; diff --git a/readme.md b/readme.md index 661b78579..a79a4262b 100644 --- a/readme.md +++ b/readme.md @@ -21,6 +21,7 @@ - **自定义服务基类**: 提供依赖注入和实例化机制,支持服务的统一管理和扩展 - **全局函数库**: 包含数据处理、系统配置、HTTP 请求、JWT 认证等实用函数 - **PSR-12 标准**: 严格遵循 PHP-FIG 编码规范,确保代码质量和可维护性 +- **高精度计算支持**: 集成 BC Math 高精度数学函数,确保金融计算的准确性 **ThinkPlugsAccount 多端账号插件** - **三层账号模型**: 临时用户(usid) ↔ 绑定手机(bind) ↔ 正式用户(unid) 的完整账号生命周期 @@ -35,6 +36,7 @@ - **高精度金融计算**: 使用 BC Math 高精度数学函数,确保金融计算的准确性 - **支付事件驱动**: 通过支付事件(审核、完成、取消、确认)实现业务逻辑解耦 - **退款管理**: 支持部分退款和全额退款,自动处理余额、积分的退回操作 +- **数据库约束优化**: 添加金额非负约束、状态枚举约束,确保数据完整性 **ThinkPlugsWemall 微商城插件** - **多级分销体系**: 支持三级分销模式,可配置不同等级的代理返佣规则 @@ -43,6 +45,7 @@ - **代理等级管理**: 团队业绩统计,支持多维度的代理等级升级条件 - **商品管理系统**: 完整的商品分类、规格、库存、价格管理 - **订单全流程管理**: 从下单、支付、发货到售后的完整订单生命周期管理 +- **高精度计算保障**: 全面采用 BC Math 高精度计算,避免浮点数精度丢失问题 **其他插件** - **ThinkPlugsCenter**: 插件服务管理中心,提供插件注册、配置和管理功能 @@ -112,4 +115,6 @@ start http://127.0.0.1:8088 * 会员授权: [《会员尊享介绍》](https://thinkadmin.top/vip-introduce) * 收费授权:请通过文档中微信二维码联系作者。 +版权所有 Copyright © 2014-2026 by ThinkAdmin (https://thinkadmin.top) All rights reserved。 + \ No newline at end of file