Browse Source

Merge branch 'payBack'

shish 2 months ago
parent
commit
c03cd332b1

+ 65 - 1
app-ghs/controllers/ScanPayController.php

@@ -3,6 +3,7 @@
 namespace ghs\controllers;
 
 use bizGhs\order\classes\ScanPayClass;
+use bizGhs\order\classes\ScanPayRefundClass;
 use common\components\util;
 use Yii;
 
@@ -24,4 +25,67 @@ class ScanPayController extends BaseController
         util::success($list);
     }
 
-}
+    public function actionDetail()
+    {
+        $get = Yii::$app->request->get();
+        $id = $get['id'] ?? 0;
+        $detail = ScanPayClass::getDetail($id, $this->mainId);
+        util::success($detail);
+    }
+
+    public function actionRefund()
+    {
+        $shopAdmin = $this->shopAdmin;
+        if (!isset($shopAdmin['super']) || $shopAdmin['super'] != 1) {
+            util::fail('超管才能操作退款');
+        }
+
+        if (getenv('YII_ENV') == 'production') {
+            if ($this->mainId == 23390) {
+                if (!in_array($this->adminId, [23960, 77951, 4])) {
+                    util::fail('你不能售后哈。。');
+                }
+            }
+            if ($this->mainId == 7704) {
+                if (in_array($this->shopAdminId, [133727, 133545]) == false) {
+                    util::fail('无法操作。。');
+                }
+            }
+            if ($this->mainId == 42680) {
+                if (!in_array($this->adminId, [40144])) {
+                    util::fail('你不能售后哦。。');
+                }
+            }
+        }
+
+        $post = Yii::$app->request->post();
+        $id = $post['id'] ?? 0;
+        if (empty($id)) {
+            util::fail('参数错误');
+        }
+
+        $cacheKey = 'ghs_scan_pay_refund_' . $id;
+        $has = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+        if (!empty($has)) {
+            util::fail('请5秒之后再提交');
+        }
+        Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 5, 'has']);
+
+        $post['mainId'] = $this->mainId;
+        $post['shopAdminId'] = $this->shopAdminId;
+        $post['shopAdminName'] = $shopAdmin['name'] ?? '';
+
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
+        try {
+            $respond = ScanPayRefundClass::createRefund($id, $post);
+            $transaction->commit();
+            util::success($respond);
+        } catch (\Exception $exception) {
+            $transaction->rollBack();
+            Yii::info('收款码退款失败:' . $exception->getMessage());
+            util::fail($exception->getMessage() ?: '操作失败');
+        }
+    }
+
+}

+ 47 - 1
app-hd/controllers/ScanPayController.php

@@ -3,6 +3,7 @@
 namespace hd\controllers;
 
 use bizHd\order\classes\ScanPayClass;
+use bizHd\order\classes\ScanPayRefundClass;
 use common\components\util;
 use Yii;
 
@@ -24,4 +25,49 @@ class ScanPayController extends BaseController
         util::success($list);
     }
 
-}
+    public function actionDetail()
+    {
+        $get = Yii::$app->request->get();
+        $id = $get['id'] ?? 0;
+        $detail = ScanPayClass::getDetail($id, $this->mainId);
+        util::success($detail);
+    }
+
+    public function actionRefund()
+    {
+        $shopAdmin = $this->shopAdmin;
+        if (!isset($shopAdmin['super']) || $shopAdmin['super'] != 1) {
+            util::fail('超管才能操作退款');
+        }
+
+        $post = Yii::$app->request->post();
+        $id = $post['id'] ?? 0;
+        if (empty($id)) {
+            util::fail('参数错误');
+        }
+
+        $cacheKey = 'hd_scan_pay_refund_' . $id;
+        $has = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+        if (!empty($has)) {
+            util::fail('请5秒之后再提交');
+        }
+        Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 5, 'has']);
+
+        $post['mainId'] = $this->mainId;
+        $post['shopAdminId'] = $this->shopAdminId;
+        $post['shopAdminName'] = $shopAdmin['name'] ?? '';
+
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
+        try {
+            $respond = ScanPayRefundClass::createRefund($id, $post);
+            $transaction->commit();
+            util::success($respond);
+        } catch (\Exception $exception) {
+            $transaction->rollBack();
+            Yii::info('收款码退款失败:' . $exception->getMessage());
+            util::fail($exception->getMessage() ?: '操作失败');
+        }
+    }
+
+}

+ 34 - 1
biz-ghs/order/classes/ScanPayClass.php

@@ -2,7 +2,8 @@
 
 namespace bizGhs\order\classes;
 
-use Yii;
+use common\components\dict;
+use common\components\util;
 use bizGhs\base\classes\BaseClass;
 
 class ScanPayClass extends BaseClass
@@ -15,4 +16,36 @@ class ScanPayClass extends BaseClass
         return self::getList('*', $where, 'addTime DESC,id DESC');
     }
 
+    public static function getDetail($id, $mainId)
+    {
+        $order = self::getById($id, true);
+        if (empty($order)) {
+            util::fail('没有找到流水');
+        }
+        if ($order->mainId != $mainId) {
+            util::fail('没有权限');
+        }
+        $actPrice = $order->actPrice ?? 0;
+        $tkPrice = $order->tkPrice ?? 0;
+        $canRefundPrice = bcsub($actPrice, $tkPrice, 2);
+        if ($canRefundPrice < 0) {
+            $canRefundPrice = 0;
+        }
+        $refundList = ScanPayRefundClass::getAllByCondition(['scanPayId' => $id], 'id DESC', '*');
+        $payWay = $order->payWay ?? 0;
+        $payWayMap = dict::getDict('payWay');
+        $payWayName = '未知';
+        if ($payWay == ($payWayMap['wxPay'] ?? 0)) {
+            $payWayName = '微信';
+        } elseif ($payWay == ($payWayMap['alipay'] ?? 1)) {
+            $payWayName = '支付宝';
+        }
+        return [
+            'info' => $order,
+            'refundList' => $refundList ?: [],
+            'canRefundPrice' => floatval($canRefundPrice),
+            'payWayName' => $payWayName,
+        ];
+    }
+
 }

+ 140 - 0
biz-ghs/order/classes/ScanPayRefundClass.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace bizGhs\order\classes;
+
+use biz\shop\classes\ShopClass;
+use bizGhs\shop\classes\MainClass;
+use common\components\dict;
+use common\components\lakala\Lakala;
+use common\components\orderSn;
+use common\components\util;
+use Yii;
+use bizGhs\base\classes\BaseClass;
+
+class ScanPayRefundClass extends BaseClass
+{
+
+    public static $baseFile = '\bizGhs\order\models\ScanPayRefund';
+
+    const STATUS_COMPLETE = 1;
+
+    public static function createRefund($scanPayId, $post)
+    {
+        $refundPrice = round($post['price'] ?? 0, 2);
+        if ($refundPrice <= 0) {
+            util::fail('请填写退款金额');
+        }
+        $mainId = $post['mainId'] ?? 0;
+        $order = ScanPayClass::getLockById($scanPayId);
+        if (empty($order)) {
+            util::fail('没有找到流水');
+        }
+        if ($order->mainId != $mainId) {
+            util::fail('没有权限');
+        }
+        if ($order->status != 2 || $order->payStatus != 1) {
+            util::fail('仅已付款流水可退款');
+        }
+        $actPrice = $order->actPrice ?? 0;
+        $tkPrice = $order->tkPrice ?? 0;
+        $canRefund = bcsub($actPrice, $tkPrice, 2);
+        if ($refundPrice > $canRefund) {
+            util::fail('退款金额超过可退金额');
+        }
+        $payWay = $order->payWay ?? 0;
+        $wxPay = dict::getDict('payWay', 'wxPay');
+        $aliPay = dict::getDict('payWay', 'alipay');
+        if ($payWay != $wxPay && $payWay != $aliPay) {
+            util::fail('暂不支持该支付方式原路退款');
+        }
+        $returnCode = $order->returnCode ?? '';
+        if (empty($returnCode)) {
+            util::fail('缺少支付流水号,无法原路退款');
+        }
+
+        $shopId = $order->shopId ?? 0;
+        $shop = ShopClass::getById($shopId, true);
+        if (empty($shop)) {
+            util::fail('没有找到门店');
+        }
+        $main = MainClass::getLockById($mainId);
+        if (empty($main)) {
+            util::fail('没有找到资产信息');
+        }
+
+        $snData = [
+            'mainId' => $mainId,
+            'shopId' => $shopId,
+            'hdId' => $order->hdId ?? 0,
+            'customId' => $order->customId ?? 0,
+        ];
+        $refundOrderSn = orderSn::getScanPayRefundSn($snData);
+        $relateOrderSn = $order->orderSn ?? '';
+
+        $data = [
+            'orderSn' => $refundOrderSn,
+            'relateOrderSn' => $relateOrderSn,
+            'scanPayId' => $scanPayId,
+            'mainId' => $mainId,
+            'shopId' => $shopId,
+            'hdId' => $order->hdId ?? 0,
+            'customId' => $order->customId ?? 0,
+            'customName' => $order->customName ?? '',
+            'refundPrice' => $refundPrice,
+            'payWay' => $payWay,
+            'status' => self::STATUS_COMPLETE,
+            'shopAdminId' => $post['shopAdminId'] ?? 0,
+            'shopAdminName' => $post['shopAdminName'] ?? '',
+            'remark' => $post['remark'] ?? '',
+            'addTime' => date('Y-m-d H:i:s'),
+        ];
+        $refund = self::add($data, true);
+
+        $termNo = $shop->lklScanTermNo ?? '';
+        if ($payWay == $aliPay) {
+            $termNo = $shop->lklB2BTermNo ?? '';
+        }
+        if (empty($shop->lklSjNo) || empty($termNo)) {
+            util::fail('门店未配置拉卡拉商户信息');
+        }
+
+        $merchantPrivateKeyPath = Yii::getAlias('@vendor/lakala') . '/production/api_private_key.pem';
+        $lklCertificatePath = Yii::getAlias('@vendor/lakala') . '/production/lkl-apigw-v1.cer';
+        $params = [
+            'appid' => 'OP00002119',
+            'serial_no' => '018b08cfddbd',
+            'merchant_no' => $shop->lklSjNo,
+            'term_no' => $termNo,
+            'merchantPrivateKeyPath' => $merchantPrivateKeyPath,
+            'lklCertificatePath' => $lklCertificatePath,
+        ];
+        $laResource = new Lakala($params);
+        $refundFee = bcmul($refundPrice, 100);
+        $aliParams = [
+            'refundSn' => $refundOrderSn,
+            'orderSn' => $relateOrderSn,
+            'refundAmount' => $refundFee,
+            'refundReason' => $data['remark'],
+            'thirdNo' => $returnCode,
+        ];
+        $response = $laResource->refund($aliParams);
+        if (!isset($response['code']) || $response['code'] != 'BBS00000') {
+            $errMsg = $response['msg'] ?? '退款失败';
+            util::fail('退款失败:' . $errMsg);
+        }
+        $refundTradeNo = $response['resp_data']['trade_no'] ?? '';
+        $refund->thirdRefundNo = $refundTradeNo;
+        $refund->save();
+
+        $currentTkPrice = bcadd($tkPrice, $refundPrice, 2);
+        $order->tkPrice = $currentTkPrice;
+        $order->refundLog = 1;
+        $order->save();
+
+        $capitalType = dict::getDict('capitalType', 'scanPayRefund', 'id');
+        ShopClass::customScanPayRefundReduceBalance($main, $shop, $refundPrice, $order, $refund, $capitalType);
+
+        return $refund;
+    }
+
+}

+ 12 - 0
biz-ghs/order/classes/ScanPayRefundSnClass.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace bizGhs\order\classes;
+
+use bizGhs\base\classes\BaseClass;
+
+class ScanPayRefundSnClass extends BaseClass
+{
+
+    public static $baseFile = '\bizGhs\order\models\ScanPayRefundSn';
+
+}

+ 15 - 0
biz-ghs/order/models/ScanPayRefund.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace bizGhs\order\models;
+
+use bizGhs\base\models\Base;
+
+class ScanPayRefund extends Base
+{
+
+    public static function tableName()
+    {
+        return 'xhScanPayRefund';
+    }
+
+}

+ 15 - 0
biz-ghs/order/models/ScanPayRefundSn.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace bizGhs\order\models;
+
+use bizGhs\base\models\Base;
+
+class ScanPayRefundSn extends Base
+{
+
+    public static function tableName()
+    {
+        return 'xhScanPayRefundSn';
+    }
+
+}

+ 33 - 0
biz-hd/order/classes/ScanPayClass.php

@@ -15,6 +15,7 @@ use bizGhs\stock\classes\StockRecordClass;
 use bizHd\custom\classes\CustomClass;
 use bizHd\item\classes\ItemClass;
 use bizHd\merchant\classes\SjClass;
+use bizHd\order\classes\ScanPayRefundClass;
 use bizHd\refund\classes\HdRefundClass;
 use bizHd\shop\classes\MainClass;
 use bizHd\shop\classes\ShopMoneyChangeClass;
@@ -42,6 +43,38 @@ class ScanPayClass extends BaseClass
         return self::getList('*', $where, 'addTime DESC,id DESC');
     }
 
+
+    public static function getDetail($id, $mainId)
+    {
+        $order = self::getById($id, true);
+        if (empty($order)) {
+            util::fail('没有找到流水');
+        }
+        if ($order->mainId != $mainId) {
+            util::fail('没有权限');
+        }
+        $actPrice = $order->actPrice ?? 0;
+        $tkPrice = $order->tkPrice ?? 0;
+        $canRefundPrice = bcsub($actPrice, $tkPrice, 2);
+        if ($canRefundPrice < 0) {
+            $canRefundPrice = 0;
+        }
+        $refundList = ScanPayRefundClass::getAllByCondition(['scanPayId' => $id], 'id DESC', '*');
+        $payWay = $order->payWay ?? 0;
+        $payWayMap = dict::getDict('payWay');
+        $payWayName = '未知';
+        if ($payWay == ($payWayMap['wxPay'] ?? 0)) {
+            $payWayName = '微信';
+        } elseif ($payWay == ($payWayMap['alipay'] ?? 1)) {
+            $payWayName = '支付宝';
+        }
+        return [
+            'info' => $order,
+            'refundList' => $refundList ?: [],
+            'canRefundPrice' => floatval($canRefundPrice),
+            'payWayName' => $payWayName,
+        ];
+    }
     public static function addOrder($data)
     {
         $mainId = $data['mainId'] ?? 0;

+ 140 - 0
biz-hd/order/classes/ScanPayRefundClass.php

@@ -0,0 +1,140 @@
+<?php
+
+namespace bizHd\order\classes;
+
+use biz\shop\classes\ShopClass;
+use bizHd\shop\classes\MainClass;
+use common\components\dict;
+use common\components\lakala\Lakala;
+use common\components\orderSn;
+use common\components\util;
+use Yii;
+use bizHd\base\classes\BaseClass;
+
+class ScanPayRefundClass extends BaseClass
+{
+
+    public static $baseFile = '\bizHd\order\models\ScanPayRefund';
+
+    const STATUS_COMPLETE = 1;
+
+    public static function createRefund($scanPayId, $post)
+    {
+        $refundPrice = round($post['price'] ?? 0, 2);
+        if ($refundPrice <= 0) {
+            util::fail('请填写退款金额');
+        }
+        $mainId = $post['mainId'] ?? 0;
+        $order = ScanPayClass::getLockById($scanPayId);
+        if (empty($order)) {
+            util::fail('没有找到流水');
+        }
+        if ($order->mainId != $mainId) {
+            util::fail('没有权限');
+        }
+        if ($order->status != 2 || $order->payStatus != 1) {
+            util::fail('仅已付款流水可退款');
+        }
+        $actPrice = $order->actPrice ?? 0;
+        $tkPrice = $order->tkPrice ?? 0;
+        $canRefund = bcsub($actPrice, $tkPrice, 2);
+        if ($refundPrice > $canRefund) {
+            util::fail('退款金额超过可退金额');
+        }
+        $payWay = $order->payWay ?? 0;
+        $wxPay = dict::getDict('payWay', 'wxPay');
+        $aliPay = dict::getDict('payWay', 'alipay');
+        if ($payWay != $wxPay && $payWay != $aliPay) {
+            util::fail('暂不支持该支付方式原路退款');
+        }
+        $returnCode = $order->returnCode ?? '';
+        if (empty($returnCode)) {
+            util::fail('缺少支付流水号,无法原路退款');
+        }
+
+        $shopId = $order->shopId ?? 0;
+        $shop = ShopClass::getById($shopId, true);
+        if (empty($shop)) {
+            util::fail('没有找到门店');
+        }
+        $main = MainClass::getLockById($mainId);
+        if (empty($main)) {
+            util::fail('没有找到资产信息');
+        }
+
+        $snData = [
+            'mainId' => $mainId,
+            'shopId' => $shopId,
+            'hdId' => $order->hdId ?? 0,
+            'customId' => $order->customId ?? 0,
+        ];
+        $refundOrderSn = orderSn::getScanPayRefundSn($snData);
+        $relateOrderSn = $order->orderSn ?? '';
+
+        $data = [
+            'orderSn' => $refundOrderSn,
+            'relateOrderSn' => $relateOrderSn,
+            'scanPayId' => $scanPayId,
+            'mainId' => $mainId,
+            'shopId' => $shopId,
+            'hdId' => $order->hdId ?? 0,
+            'customId' => $order->customId ?? 0,
+            'customName' => $order->customName ?? '',
+            'refundPrice' => $refundPrice,
+            'payWay' => $payWay,
+            'status' => self::STATUS_COMPLETE,
+            'shopAdminId' => $post['shopAdminId'] ?? 0,
+            'shopAdminName' => $post['shopAdminName'] ?? '',
+            'remark' => $post['remark'] ?? '',
+            'addTime' => date('Y-m-d H:i:s'),
+        ];
+        $refund = self::add($data, true);
+
+        $termNo = $shop->lklScanTermNo ?? '';
+        if ($payWay == $aliPay) {
+            $termNo = $shop->lklB2BTermNo ?? '';
+        }
+        if (empty($shop->lklSjNo) || empty($termNo)) {
+            util::fail('门店未配置拉卡拉商户信息');
+        }
+
+        $merchantPrivateKeyPath = Yii::getAlias('@vendor/lakala') . '/production/api_private_key.pem';
+        $lklCertificatePath = Yii::getAlias('@vendor/lakala') . '/production/lkl-apigw-v1.cer';
+        $params = [
+            'appid' => 'OP00002119',
+            'serial_no' => '018b08cfddbd',
+            'merchant_no' => $shop->lklSjNo,
+            'term_no' => $termNo,
+            'merchantPrivateKeyPath' => $merchantPrivateKeyPath,
+            'lklCertificatePath' => $lklCertificatePath,
+        ];
+        $laResource = new Lakala($params);
+        $refundFee = bcmul($refundPrice, 100);
+        $aliParams = [
+            'refundSn' => $refundOrderSn,
+            'orderSn' => $relateOrderSn,
+            'refundAmount' => $refundFee,
+            'refundReason' => $data['remark'],
+            'thirdNo' => $returnCode,
+        ];
+        $response = $laResource->refund($aliParams);
+        if (!isset($response['code']) || $response['code'] != 'BBS00000') {
+            $errMsg = $response['msg'] ?? '退款失败';
+            util::fail('退款失败:' . $errMsg);
+        }
+        $refundTradeNo = $response['resp_data']['trade_no'] ?? '';
+        $refund->thirdRefundNo = $refundTradeNo;
+        $refund->save();
+
+        $currentTkPrice = bcadd($tkPrice, $refundPrice, 2);
+        $order->tkPrice = $currentTkPrice;
+        $order->refundLog = 1;
+        $order->save();
+
+        $capitalType = dict::getDict('capitalType', 'scanPayRefund', 'id');
+        ShopClass::customScanPayRefundReduceBalance($main, $shop, $refundPrice, $order, $refund, $capitalType);
+
+        return $refund;
+    }
+
+}

+ 12 - 0
biz-hd/order/classes/ScanPayRefundSnClass.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace bizHd\order\classes;
+
+use bizHd\base\classes\BaseClass;
+
+class ScanPayRefundSnClass extends BaseClass
+{
+
+    public static $baseFile = '\bizHd\order\models\ScanPayRefundSn';
+
+}

+ 15 - 0
biz-hd/order/models/ScanPayRefund.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace bizHd\order\models;
+
+use bizHd\base\models\Base;
+
+class ScanPayRefund extends Base
+{
+
+    public static function tableName()
+    {
+        return 'xhScanPayRefund';
+    }
+
+}

+ 15 - 0
biz-hd/order/models/ScanPayRefundSn.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace bizHd\order\models;
+
+use bizHd\base\models\Base;
+
+class ScanPayRefundSn extends Base
+{
+
+    public static function tableName()
+    {
+        return 'xhScanPayRefundSn';
+    }
+
+}

+ 38 - 0
biz/shop/classes/ShopClass.php

@@ -522,6 +522,44 @@ class ShopClass extends BaseClass
         ShopYeChangeClass::addChange($change, true);
     }
 
+
+    public static function customScanPayRefundReduceBalance($main, $shop, $amount, $order, $refund, $capitalType)
+    {
+        $mainId = $shop->mainId ?? 0;
+        $currentBalance = bcsub($main->balance, $amount, 2);
+        if ($currentBalance < 0) {
+            util::fail('余额不足,请稍后再操作');
+        }
+        $main->balance = $currentBalance;
+        $currentTx = bcsub($main->txBalance, $amount, 2);
+        if ($currentTx < 0) {
+            $currentTx = 0;
+        }
+        $main->txBalance = $currentTx;
+        $main->save();
+
+        $customName = $order->customName ?? '客户';
+        if (empty($customName)) {
+            $customName = '客户';
+        }
+        $refundSn = $refund->orderSn ?? '';
+        $event = $customName . '扫码付款退款' . floatval($amount) . '元(' . $refundSn . ')';
+        $change = [
+            'relateId' => $refund->id,
+            'capitalType' => $capitalType,
+            'amount' => $amount,
+            'balance' => $currentBalance,
+            'txBalance' => $currentTx,
+            'io' => 0,
+            'payWay' => $order->payWay ?? 0,
+            'event' => $event,
+            'mainId' => $mainId,
+            'tx' => 2,
+            'ptStyle' => $shop->ptStyle,
+            'fromType' => 1,
+        ];
+        ShopYeChangeClass::addChange($change, true);
+    }
     //门店充值增加余额 ssh 2021.2.21
     //$fix = true 余额只能在指定门店使用
     public static function rechargeAddBalance($shop, $amount, $order, $tx, $capitalType, $fix = false)

+ 2 - 0
common/components/dict.php

@@ -420,6 +420,7 @@ class dict
             //如果涉及是系统处理和操作,都可以用这个流水类型
             'system' => ['id' => 78, 'name' => 'system'],
             'scanPay' => ['id' => 79, 'name' => 'scanPay'],
+            'scanPayRefund' => ['id' => 80, 'name' => 'scanPayRefund'],
         ],
         "capitalTypeList" => [//流水类型的对应链接,后台收支明细查看时跳转的链接
             0 => ['link' => '/capital/order-detail', 'name' => '网店', 'orderLink' => '/order/detail', 'id' => 0,],
@@ -471,6 +472,7 @@ class dict
             77 => ['link' => '', 'name' => '手动减少', 'id' => 77,],
             78 => ['link' => '', 'name' => '系统操作', 'id' => 78,],
             79 => ['link' => '', 'name' => '扫码付款', 'id' => 79,],
+            80 => ['link' => '', 'name' => '扫码退款', 'id' => 80,],
         ],
 
         //用户来源

+ 17 - 0
common/components/orderSn.php

@@ -21,6 +21,7 @@ use bizHd\express\classes\ExpressSnClass;
 use bizHd\goods\classes\GoodsCgSnClass;
 use bizHd\goods\classes\GoodsSnClass;
 use bizHd\ljh\classes\LjhSnClass;
+use bizHd\order\classes\ScanPayRefundSnClass;
 use bizHd\order\classes\ScanPaySnClass;
 use bizHd\order\classes\SettleSnClass;
 use bizHd\part\classes\PartSnClass;
@@ -200,6 +201,22 @@ class orderSn
     }
 
     //供货商采购单号 ssh 2021.1.19
+
+    public static function getScanPayRefundSn($params = [])
+    {
+        $params['id'] = null;
+        $params['addTime'] = date('Y-m-d H:i:s');
+        $prefix = 'SR_CS';
+        if (getenv('YII_ENV', 'local') == 'production') {
+            $prefix = 'SR';
+        }
+        $respond = ScanPayRefundSnClass::add($params);
+        $id = $respond['id'] ?? 0;
+        if (empty($id)) {
+            util::fail('退款单号没有生成');
+        }
+        return $prefix . $id;
+    }
     public static function getGhsPurchaseSn()
     {
         $prefix = 'PH_CS';

+ 6 - 0
sql/fix_scan_pay_refund_sn_addtime.php

@@ -0,0 +1,6 @@
+<?php
+$pdo = new PDO('mysql:host=118.178.193.23;dbname=huahuibao;charset=utf8mb4', 'root', 'zhh20250805', [
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+]);
+$pdo->exec("ALTER TABLE xhScanPayRefundSn MODIFY addTime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
+echo "alter ok\n";

+ 38 - 0
sql/payBack_scan_pay_refund.sql

@@ -0,0 +1,38 @@
+-- 收款码流水退款 payBack 分支
+ALTER TABLE xhScanPay
+  ADD COLUMN tkPrice decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '累计退款金额' AFTER actPrice,
+  ADD COLUMN refundLog tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否有退款记录' AFTER tkPrice;
+
+CREATE TABLE IF NOT EXISTS xhScanPayRefund (
+  id int(11) NOT NULL AUTO_INCREMENT,
+  orderSn varchar(32) NOT NULL COMMENT '退款单号 SR*',
+  relateOrderSn varchar(32) NOT NULL COMMENT '原收款单号 SC*',
+  scanPayId int(11) NOT NULL DEFAULT 0,
+  mainId int(11) NOT NULL DEFAULT 0,
+  shopId int(11) NOT NULL DEFAULT 0,
+  hdId int(11) NOT NULL DEFAULT 0,
+  customId int(11) NOT NULL DEFAULT 0,
+  customName varchar(64) NOT NULL DEFAULT '',
+  refundPrice decimal(10,2) NOT NULL DEFAULT 0.00,
+  payWay tinyint(1) NOT NULL DEFAULT 0 COMMENT '0微信 1支付宝',
+  status tinyint(1) NOT NULL DEFAULT 1 COMMENT '1已通过',
+  thirdRefundNo varchar(64) NOT NULL DEFAULT '' COMMENT '拉卡拉退款流水号',
+  shopAdminId int(11) NOT NULL DEFAULT 0,
+  shopAdminName varchar(32) NOT NULL DEFAULT '',
+  remark varchar(255) NOT NULL DEFAULT '',
+  addTime datetime NOT NULL,
+  PRIMARY KEY (id),
+  KEY idx_relateOrderSn (relateOrderSn),
+  KEY idx_mainId (mainId),
+  KEY idx_scanPayId (scanPayId)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收款码退款流水';
+
+CREATE TABLE IF NOT EXISTS xhScanPayRefundSn (
+  id int(11) NOT NULL AUTO_INCREMENT,
+  mainId int(11) NOT NULL DEFAULT 0,
+  shopId int(11) NOT NULL DEFAULT 0,
+  hdId int(11) NOT NULL DEFAULT 0,
+  customId int(11) NOT NULL DEFAULT 0,
+  addTime datetime NOT NULL,
+  PRIMARY KEY (id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

+ 68 - 0
sql/run_all_payBack_sql.php

@@ -0,0 +1,68 @@
+<?php
+$host = '118.178.193.23';
+$db = 'huahuibao';
+$user = 'root';
+$pass = 'zhh20250805';
+$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass, [
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+]);
+$results = [];
+function run(PDO $pdo, $sql, &$results, $label = '') {
+    try {
+        $pdo->exec($sql);
+        $results[] = ['status' => 'ok', 'label' => $label, 'sql' => preg_replace('/\s+/', ' ', trim($sql))];
+    } catch (Exception $e) {
+        $results[] = ['status' => 'err', 'label' => $label, 'sql' => preg_replace('/\s+/', ' ', trim($sql)), 'msg' => $e->getMessage()];
+    }
+}
+
+$cols = $pdo->query('DESCRIBE xhScanPay')->fetchAll(PDO::FETCH_COLUMN);
+if (!in_array('tkPrice', $cols, true)) {
+    run($pdo, "ALTER TABLE xhScanPay ADD COLUMN tkPrice decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '累计退款金额' AFTER actPrice", $results, 'add tkPrice');
+} else {
+    $results[] = ['status' => 'skip', 'label' => 'tkPrice exists'];
+}
+$cols = $pdo->query('DESCRIBE xhScanPay')->fetchAll(PDO::FETCH_COLUMN);
+if (!in_array('refundLog', $cols, true)) {
+    run($pdo, "ALTER TABLE xhScanPay ADD COLUMN refundLog tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否有退款记录' AFTER tkPrice", $results, 'add refundLog');
+} else {
+    $results[] = ['status' => 'skip', 'label' => 'refundLog exists'];
+}
+
+run($pdo, "CREATE TABLE IF NOT EXISTS xhScanPayRefund (
+  id int(11) NOT NULL AUTO_INCREMENT,
+  orderSn varchar(32) NOT NULL COMMENT '退款单号 SR*',
+  relateOrderSn varchar(32) NOT NULL COMMENT '原收款单号 SC*',
+  scanPayId int(11) NOT NULL DEFAULT 0,
+  mainId int(11) NOT NULL DEFAULT 0,
+  shopId int(11) NOT NULL DEFAULT 0,
+  hdId int(11) NOT NULL DEFAULT 0,
+  customId int(11) NOT NULL DEFAULT 0,
+  customName varchar(64) NOT NULL DEFAULT '',
+  refundPrice decimal(10,2) NOT NULL DEFAULT 0.00,
+  payWay tinyint(1) NOT NULL DEFAULT 0 COMMENT '0微信 1支付宝',
+  status tinyint(1) NOT NULL DEFAULT 1 COMMENT '1已通过',
+  thirdRefundNo varchar(64) NOT NULL DEFAULT '' COMMENT '拉卡拉退款流水号',
+  shopAdminId int(11) NOT NULL DEFAULT 0,
+  shopAdminName varchar(32) NOT NULL DEFAULT '',
+  remark varchar(255) NOT NULL DEFAULT '',
+  addTime datetime NOT NULL,
+  PRIMARY KEY (id),
+  KEY idx_relateOrderSn (relateOrderSn),
+  KEY idx_mainId (mainId),
+  KEY idx_scanPayId (scanPayId)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收款码退款流水'", $results, 'create xhScanPayRefund');
+
+run($pdo, "CREATE TABLE IF NOT EXISTS xhScanPayRefundSn (
+  id int(11) NOT NULL AUTO_INCREMENT,
+  mainId int(11) NOT NULL DEFAULT 0,
+  shopId int(11) NOT NULL DEFAULT 0,
+  hdId int(11) NOT NULL DEFAULT 0,
+  customId int(11) NOT NULL DEFAULT 0,
+  addTime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", $results, 'create xhScanPayRefundSn');
+
+run($pdo, "ALTER TABLE xhScanPayRefundSn MODIFY addTime datetime NOT NULL DEFAULT CURRENT_TIMESTAMP", $results, 'fix addTime default');
+
+echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . PHP_EOL;

+ 64 - 0
sql/run_payBack_migration.php

@@ -0,0 +1,64 @@
+<?php
+$host = '118.178.193.23';
+$db = 'huahuibao';
+$user = 'root';
+$pass = 'zhh20250805';
+$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass, [
+    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+]);
+$results = [];
+function runSql(PDO $pdo, $sql, &$results) {
+    try {
+        $pdo->exec($sql);
+        $results[] = ['status' => 'ok', 'sql' => trim($sql)];
+    } catch (Exception $e) {
+        $results[] = ['status' => 'err', 'sql' => trim($sql), 'msg' => $e->getMessage()];
+    }
+}
+$cols = $pdo->query('DESCRIBE xhScanPay')->fetchAll(PDO::FETCH_COLUMN);
+if (!in_array('tkPrice', $cols, true)) {
+    runSql($pdo, "ALTER TABLE xhScanPay ADD COLUMN tkPrice decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT '累计退款金额' AFTER actPrice", $results);
+} else {
+    $results[] = ['status' => 'skip', 'sql' => 'tkPrice column already exists'];
+}
+$cols = $pdo->query('DESCRIBE xhScanPay')->fetchAll(PDO::FETCH_COLUMN);
+if (!in_array('refundLog', $cols, true)) {
+    runSql($pdo, "ALTER TABLE xhScanPay ADD COLUMN refundLog tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否有退款记录' AFTER tkPrice", $results);
+} else {
+    $results[] = ['status' => 'skip', 'sql' => 'refundLog column already exists'];
+}
+$createRefund = "CREATE TABLE IF NOT EXISTS xhScanPayRefund (
+  id int(11) NOT NULL AUTO_INCREMENT,
+  orderSn varchar(32) NOT NULL COMMENT '退款单号 SR*',
+  relateOrderSn varchar(32) NOT NULL COMMENT '原收款单号 SC*',
+  scanPayId int(11) NOT NULL DEFAULT 0,
+  mainId int(11) NOT NULL DEFAULT 0,
+  shopId int(11) NOT NULL DEFAULT 0,
+  hdId int(11) NOT NULL DEFAULT 0,
+  customId int(11) NOT NULL DEFAULT 0,
+  customName varchar(64) NOT NULL DEFAULT '',
+  refundPrice decimal(10,2) NOT NULL DEFAULT 0.00,
+  payWay tinyint(1) NOT NULL DEFAULT 0 COMMENT '0微信 1支付宝',
+  status tinyint(1) NOT NULL DEFAULT 1 COMMENT '1已通过',
+  thirdRefundNo varchar(64) NOT NULL DEFAULT '' COMMENT '拉卡拉退款流水号',
+  shopAdminId int(11) NOT NULL DEFAULT 0,
+  shopAdminName varchar(32) NOT NULL DEFAULT '',
+  remark varchar(255) NOT NULL DEFAULT '',
+  addTime datetime NOT NULL,
+  PRIMARY KEY (id),
+  KEY idx_relateOrderSn (relateOrderSn),
+  KEY idx_mainId (mainId),
+  KEY idx_scanPayId (scanPayId)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收款码退款流水'";
+runSql($pdo, $createRefund, $results);
+$createSn = "CREATE TABLE IF NOT EXISTS xhScanPayRefundSn (
+  id int(11) NOT NULL AUTO_INCREMENT,
+  mainId int(11) NOT NULL DEFAULT 0,
+  shopId int(11) NOT NULL DEFAULT 0,
+  hdId int(11) NOT NULL DEFAULT 0,
+  customId int(11) NOT NULL DEFAULT 0,
+  addTime datetime NOT NULL,
+  PRIMARY KEY (id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
+runSql($pdo, $createSn, $results);
+echo json_encode($results, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);