moonsflyer 5 сар өмнө
parent
commit
effd9d72f0

+ 19 - 2
app/common/logic/PaymentLogic.php

@@ -32,6 +32,7 @@ use app\common\model\User;
 use app\common\service\ConfigService;
 use app\common\service\ConfigService;
 use app\common\service\pay\AliPayService;
 use app\common\service\pay\AliPayService;
 use app\common\service\pay\BalancePayService;
 use app\common\service\pay\BalancePayService;
+use app\common\service\pay\MixedPayService;
 use app\common\service\pay\ToutiaoPayService;
 use app\common\service\pay\ToutiaoPayService;
 use app\common\service\pay\WeChatPayService;
 use app\common\service\pay\WeChatPayService;
 use app\common\service\RegionService;
 use app\common\service\RegionService;
@@ -112,8 +113,10 @@ class PaymentLogic extends BaseLogic
                 $result = [ 'pay_way' => PayEnum::OFFLINE_PAY ];
                 $result = [ 'pay_way' => PayEnum::OFFLINE_PAY ];
                 break;
                 break;
             case PayEnum::MIXED_PAY:
             case PayEnum::MIXED_PAY:
-                $payService = (new WeChatPayService($terminal, $order['user_id'] ?? null));
+                // 混合支付(余额+微信)
+                $payService = (new MixedPayService($terminal, $order['user_id'] ?? null));
                 $result = $payService->pay($from, $order);
                 $result = $payService->pay($from, $order);
+                // 混合支付中余额部分已经直接扣除,微信部分需要用户完成支付后才会触发回调
                 break;
                 break;
             default:
             default:
                 self::$error = '订单异常';
                 self::$error = '订单异常';
@@ -208,7 +211,9 @@ class PaymentLogic extends BaseLogic
             if (empty($order) || !isset($order)) {
             if (empty($order) || !isset($order)) {
                 throw new \Exception('待支付订单不存在');
                 throw new \Exception('待支付订单不存在');
             }
             }
-
+            // 获取用户余额
+            $user = User::findOrEmpty($userId);
+            $userBalance = $user['user_money'] ?? 0;
             // 获取订单剩余支付时间
             // 获取订单剩余支付时间
             $cancelUnpaidOrders = ConfigService::get('transaction', 'cancel_unpaid_orders');
             $cancelUnpaidOrders = ConfigService::get('transaction', 'cancel_unpaid_orders');
             $cancelUnpaidOrdersTimes = ConfigService::get('transaction', 'cancel_unpaid_orders_times');
             $cancelUnpaidOrdersTimes = ConfigService::get('transaction', 'cancel_unpaid_orders_times');
@@ -243,6 +248,18 @@ class PaymentLogic extends BaseLogic
                     $user_money = User::where(['id' => $userId])->value('user_money');
                     $user_money = User::where(['id' => $userId])->value('user_money');
                     $item['extra'] = '可用余额:'.$user_money;
                     $item['extra'] = '可用余额:'.$user_money;
                 }
                 }
+
+                if ($item['pay_way'] == PayEnum::MIXED_PAY) {
+                    // 混合支付:当余额不足时显示
+                    if ($userBalance > 0 && $userBalance < $order['order_amount']) {
+                        $wechatAmount = $order['order_amount'] - $userBalance;
+                        $item['extra'] = "余额:{$userBalance}元 + 微信:{$wechatAmount}元";
+                    } else {
+                        // 余额充足或为0时,不显示混合支付选项
+                        unset($pay_way[$k]);
+                    }
+                }
+                
                 // 充值时去除余额支付
                 // 充值时去除余额支付
                 if ($params['from'] == 'recharge' && $item['pay_way'] == PayEnum::BALANCE_PAY) {
                 if ($params['from'] == 'recharge' && $item['pay_way'] == PayEnum::BALANCE_PAY) {
                     unset($pay_way[$k]);
                     unset($pay_way[$k]);

+ 186 - 0
app/common/service/pay/MixedPayService.php

@@ -0,0 +1,186 @@
+<?php
+// +----------------------------------------------------------------------
+// | likeshop100%开源免费商用商城系统
+// +----------------------------------------------------------------------
+// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
+// | 开源版本可自由商用,可去除界面版权logo
+// | 商业版本务必购买商业授权,以免引起法律纠纷
+// | 禁止对系统程序代码以任何目的,任何形式的再发布
+// | gitee下载:https://gitee.com/likeshop_gitee
+// | github下载:https://github.com/likeshop-github
+// | 访问官网:https://www.likeshop.cn
+// | 访问社区:https://home.likeshop.cn
+// | 访问手册:http://doc.likeshop.cn
+// | 微信公众号:likeshop技术社区
+// | likeshop团队 版权所有 拥有最终解释权
+// +----------------------------------------------------------------------
+// | author: likeshopTeam
+// +----------------------------------------------------------------------
+
+namespace app\common\service\pay;
+
+use app\common\enum\AccountLogEnum;
+use app\common\enum\PayEnum;
+use app\common\logic\AccountLogLogic;
+use app\common\model\User;
+use app\common\service\pay\base\BasePayService;
+use app\common\service\pay\base\StatusTrait;
+use think\facade\Db;
+
+/**
+ * 混合支付服务(余额+微信)
+ * Class MixedPayService
+ * @package app\common\service\pay
+ */
+class MixedPayService extends BasePayService
+{
+    use StatusTrait;
+
+    protected $wechatPayService;
+    protected $balancePayService;
+
+    public function __construct($terminal, $userId = null)
+    {
+        parent::__construct(['terminal' => $terminal]);
+        $this->wechatPayService = new WeChatPayService($terminal, $userId);
+        $this->balancePayService = new BalancePayService();
+    }
+
+   function realPay()
+    {
+        return $this->wechatPayService->realPay();
+    }
+
+    /**
+     * @notes 混合支付(余额+微信)
+     * @param $from 订单类型
+     * @param $order 订单信息
+     * @return array|false
+     * @author 系统
+     * @date 2024/12/19
+     */
+    public function pay($from, $order)
+    {
+        Db::startTrans();
+        try {
+            $user = User::findOrEmpty($order['user_id']);
+            if ($user->isEmpty()) {
+                throw new \Exception('用户不存在');
+            }
+
+            $userBalance = $user['user_money']; // 用户余额
+            $orderAmount = $order['order_amount']; // 订单金额
+
+            // 如果余额足够支付全部订单,直接使用余额支付
+            if ($userBalance >= $orderAmount) {
+                $result = $this->balancePayService->pay($from, $order);
+                if ($result === false) {
+                    throw new \Exception('余额支付失败');
+                }
+                Db::commit();
+                return $result;
+            }
+
+            // 余额不足,使用混合支付
+            $balanceAmount = $userBalance; // 使用全部余额
+            $wechatAmount = $orderAmount - $balanceAmount; // 剩余金额用微信支付
+
+            // 先扣除用户余额
+            if ($balanceAmount > 0) {
+                User::update([
+                    'user_money' => ['dec', $balanceAmount]
+                ], ['id' => $order['user_id']]);
+
+                // 记录余额流水
+                AccountLogLogic::add(
+                    $order['user_id'],
+                    AccountLogEnum::BNW_DEC_ORDER,
+                    AccountLogEnum::DEC,
+                    $balanceAmount,
+                    $order['sn'],
+                    '混合支付-余额部分'
+                );
+            }
+
+            // 创建微信支付订单(金额为剩余需要支付的金额)
+            $wechatOrder = $order;
+            $wechatOrder['order_amount'] = $wechatAmount;
+            $wechatOrder['balance_amount'] = $balanceAmount; // 记录已使用的余额金额
+
+            $result = $this->wechatPayService->pay($from, $wechatOrder);
+            if ($result === false) {
+                throw new \Exception('微信支付创建失败');
+            }
+
+            // 在返回结果中添加混合支付信息
+            $result['pay_way'] = PayEnum::MIXED_PAY;
+            $result['balance_amount'] = $balanceAmount;
+            $result['wechat_amount'] = $wechatAmount;
+            $result['total_amount'] = $orderAmount;
+
+            Db::commit();
+            return $result;
+
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->setStatus(false, $e->getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * @notes 混合支付退款
+     * @param $order 订单信息
+     * @param $refundAmount 退款金额
+     * @param $afterSaleId 售后ID
+     * @return bool
+     */
+    public function refund($order, $refundAmount, $afterSaleId)
+    {
+        try {
+            // 获取订单的余额支付金额和微信支付金额
+            $balanceAmount = $order['balance_amount'] ?? 0;
+            $wechatAmount = $order['order_amount'] - $balanceAmount;
+
+            // 按比例退款
+            if ($refundAmount >= $order['order_amount']) {
+                // 全额退款
+                $refundBalanceAmount = $balanceAmount;
+                $refundWechatAmount = $wechatAmount;
+            } else {
+                // 部分退款,按比例分配
+                $refundRatio = $refundAmount / $order['order_amount'];
+                $refundBalanceAmount = $balanceAmount * $refundRatio;
+                $refundWechatAmount = $wechatAmount * $refundRatio;
+            }
+
+            // 退回余额
+            if ($refundBalanceAmount > 0) {
+                $this->balancePayService->refund($order, $refundBalanceAmount, $afterSaleId);
+            }
+
+            // 微信退款
+            if ($refundWechatAmount > 0) {
+                // 这里需要调用微信退款接口
+                // $this->wechatPayService->refund($order['sn'], $refundWechatAmount, $afterSaleId);
+            }
+
+            return true;
+        } catch (\Exception $e) {
+            $this->setStatus(false, $e->getMessage());
+            return false;
+        }
+    }
+
+    // 实现抽象方法
+    public function payMnp() { return $this->wechatPayService->payMnp(); }
+    public function payOa() { return $this->wechatPayService->payOa(); }
+    public function payIos() { return $this->wechatPayService->payIos(); }
+    public function payAndroid() { return $this->wechatPayService->payAndroid(); }
+    public function payH5() { return $this->wechatPayService->payH5(); }
+    public function payPc() { return $this->wechatPayService->payPc(); }
+    public function payNotify() { return $this->wechatPayService->payNotify(); }
+    public function queryPay() { return $this->wechatPayService->queryPay(); }
+    public function queryRefund() { return $this->wechatPayService->queryRefund(); }
+
+}