conditionQuery($where)->select('*'); if ((int)$io === 1) { $query->andWhere('IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0'); } else { $query->andWhere(['isRefund' => 1]); } return self::getRechargePageList($query, 'addTime DESC,id DESC'); } private static function getRechargePageList($query, $order = '') { $get = Yii::$app->request->get(); $page = isset($get['page']) ? $get['page'] : 1; Yii::$app->params['page'] = $page; $pageSize = isset($get['pageSize']) && !empty($get['pageSize']) ? $get['pageSize'] : Yii::$app->params['pageSize']; $offset = ($page - 1) * $pageSize; $clone = clone $query; $count = $clone->count(); $totalPage = ceil($count / $pageSize); $data['totalNum'] = $count; $data['totalPage'] = $totalPage; $data['moreData'] = $totalPage > $page ? 1 : 0; if (!empty($order)) { $query->orderBy($order); } $data['list'] = $query->offset($offset)->limit($pageSize)->asArray()->all(); return $data; } public static function addRecharge($data) { //创建充值单时,要把过去的充值单和结账单取消掉 $customId = $data['customId'] ?? 0; if (empty($customId)) { util::fail('没有客户信息'); } $shopId = $data['shopId'] ?? 0; $hasList = self::getAllByCondition(['customId' => $customId, 'status' => 0], null, '*', null, true); if (!empty($hasList)) { $shop = \bizHd\merchant\classes\ShopClass::getById($shopId, true); if (empty($shop)) { util::fail('没有找到门店'); } foreach ($hasList as $k => $recharge) { $payRequest = $recharge->payRequest ?? 0; if ($payRequest == 1 || $payRequest == 2) { $closeOrderSn = $recharge->orderSn; $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' => $shop->lklScanTermNo, 'merchantPrivateKeyPath' => $merchantPrivateKeyPath, 'lklCertificatePath' => $lklCertificatePath, ]; $laResource = new Lakala($params); $closeParams = ['orderSn' => $closeOrderSn]; if ($payRequest == 1) { //聚合支付 $response = $laResource->close($closeParams); if (!isset($response['code']) || $response['code'] != 'BBS00000') { $msg = $response['msg'] ?? ''; noticeUtil::push('充值换单,聚合支付,没有成功,单号:' . $closeOrderSn . ',关单没有成功,编号966558,' . $msg, '15280215347'); //util::fail('老订单取消失败,请联系管理员'); } } else { //收银台支付 $response = $laResource->cashClose($closeParams); if (!isset($response['code']) || $response['code'] != '000000') { $msg = $response['msg'] ?? ''; noticeUtil::push('充值换单,收银台的单号:' . $closeOrderSn . ',关单没有成功,编号66996,' . $msg, '15280215347'); //util::fail('旧订单取消失败,请联系管理员'); } } } $recharge->status = 2; $recharge->save(); $settleId = $recharge->settleId ?? 0; $settle = SettleClass::getById($settleId, true); if (!empty($settle)) { $settle->status = 3; $settle->save(); } } } return self::add($data, true); } //第三支付后流程 ssh 2021.4.27 public static function thirdPay($payWay, $orderSn, $totalFee, $attach, $transactionId = '') { $recharge = RechargeClass::getByCondition(['orderSn' => $orderSn], true); if (empty($recharge)) { noticeUtil::push('充值付款成功,收到回调,但没有找到充值记录,orderSn:' . $orderSn, '15280215347'); return false; } if ($totalFee != $recharge->amount) { noticeUtil::push("充值付款成功,收到回调,但金额不一致 {$totalFee} {$recharge->amount},orderSn:" . $orderSn, '15280215347'); return false; } if ($recharge->payStatus == 1) { noticeUtil::push("充值付款成功,收到回调,但订单是已经支付过了,orderSn:" . $orderSn, '15280215347'); return false; } $id = $recharge->id; $recharge = RechargeClass::getLockById($id); $params = [ 'onlinePay' => 2, 'side' => 1, ]; $recharge->returnCode = $transactionId; $recharge->save(false); self::complete($recharge, $payWay, $params); return $recharge; } //处理充值流程 ssh 20250321 public static function complete($recharge, $payWay, $params) { $onlinePay = $params['onlinePay']; //0 花店端操作,1 客户端操作 $side = $params['side'] ?? 0; $recharge->onlinePay = $onlinePay; $recharge->payWay = $payWay; $recharge->payStatus = 1; $recharge->status = 1; $recharge->save(); $shopId = $recharge->shopId; $mainId = $recharge->mainId; $hdId = $recharge->hdId; $hdInfo = HdClass::getById($hdId, true); $hdName = $hdInfo->name ?? ""; $amount = $recharge->amount; $staffId = $recharge->staffId; $payWay = $recharge->payWay; $staffName = $recharge->staffName; $customId = $recharge->customId; $customName = $recharge->customName; $capitalType = dict::getDict('capitalType', 'xhRecharge', 'id'); $relateId = $recharge->id; $shOrderId = $recharge->shOrderId ?? 0; $shOrderSn = $recharge->shOrderSn ?? ''; $custom = CustomClass::getLockById($customId); if (empty($custom)) { $msg = '充值回调失败,没有找到客户'; util::fail($msg); } $hd = HdClass::getLockById($hdId); if (empty($hd)) { $msg = '充值回调失败,没有找到花店'; util::fail($msg); } $shop = ShopClass::getById($shopId, true); $rechargeWeal = $shop->rechargeWeal ?? 0; //充值赠送: 0未设置 2充值送红包--红包非余额支付可用,3充值送红包--红包非余额支付不可用 $balanceGive = 0; //如果客户有欠款、结账充值、售后充值、售后付款充值,不参与优惠 if ($custom->balance >= 0 && $recharge->settleId == 0 && $recharge->shOrderId == 0 && $recharge->refundOrderId == 0) { if ($rechargeWeal == 1) { $weal = RechargeSqClass::getAllByCondition(['shopId' => $shopId], 'recharge ASC', '*'); if (!empty($weal)) { //优惠方式2:充多少送多少 foreach ($weal as $k => $v) { $thisRecharge = $v['recharge'] ?? 0; $thisGive = $v['give'] ?? 0; if ($amount >= $thisRecharge) { $recharge->giveAmount = $thisGive; $recharge->save(); //增加赠送的金额 $balanceGive = $thisGive; } } } } elseif ($rechargeWeal == 2 || $rechargeWeal == 3) { //充值送红包 // 1.根据充值金额,查询符合条件的红包规则 $maxHbRule = RechargeShbClass::getByCondition(['shopId' => $shopId, 'amount<=' => $amount], false, 'allHbAmount DESC'); if (!empty($maxHbRule)) { $currentTime = time(); $rulesJson = $maxHbRule['rules'] ?? ''; $rulesArr = json_decode($rulesJson, true); if (is_array($rulesArr) && !empty($rulesArr)) { foreach ($rulesArr as $rule) { $hbAmount = $rule['hbAmount']; $hbNum = $rule['hbNum']; $miniCost = $rule['miniCost']; $duration = $rule['duration']; $effectiveType = $rule['effectiveType'] ?? 2; $effectiveDate = $rule['effectiveDate'] ?? ''; $effectiveDays = $rule['effectiveDays'] ?? 0; if ($effectiveType == 1 && !empty($effectiveDate) && $effectiveDate != '0000-00-00') { $beginTime = strtotime($effectiveDate); if (!$beginTime) { $beginTime = $currentTime; } } else { $beginTime = $currentTime + 86400 * $effectiveDays; } //给用户生成红包 $data = [ 'mainId' => $mainId, 'shopId' => $shopId, 'userId' => $recharge->userId, 'customId' => $customId, 'amount' => $hbAmount, 'minConsume' => $miniCost, 'beginTime' => $beginTime, 'endTime' => $duration == 0 ? 4102416000 : ($beginTime + 86400 * $duration), 'willTime' => $duration == 0 ? 4102416000 : ($beginTime + 86400 * $duration), 'duration' => $duration, 'getType' => 2, //取得方式 0新人领取 1门店发放 2充值赠送 'remark' => '充值赠送红包', ]; $manageData = [ 'getType' => 2, 'getTargetId' => 0, 'createStaffId' => 0, 'createStaffName' => '', 'remark' => $data['remark'] ?? '', ]; for ($i = 0; $i < $hbNum; $i++) { $hb = HbClass::add($data); $manageData['hbId'] = $hb['id']; HbManageClass::add($manageData); } } } } } else { //其他 } } //是否开启充值满多少成为 VIP $shopExt = ShopExtClass::getByCondition(['shopId' => $shopId], false, 'reachVip'); if (!empty($shopExt) && $shopExt['reachVip'] > 0.00 && bccomp($amount, $shopExt['reachVip'], 2) >= 0) { $custom->vip = 1; } $balancePay = $amount; if ($onlinePay == 2) { $event = $payWay == 0 ? '线上微信 充值' : '线上支付宝 充值'; } else { $payWayName = dict::getDict('payWayName'); $channel = $payWayName[$payWay] ?? '微信'; $event = "线下{$channel} 充值"; } $event .= floatval($balancePay); //赠送的余额 if ($balanceGive > 0) { $event .= "(送" . floatval($balanceGive) . ")"; $custom->balanceGive = bcadd($custom->balanceGive, $balanceGive, 2); $hd->balanceGive = bcadd($hd->balanceGive, $balanceGive, 2); } //充值的余额 $beforeBalancePay = $custom->balancePay; $custom->balancePay = bcadd($custom->balancePay, $balancePay, 2); $hd->balancePay = bcadd($hd->balancePay, $balancePay, 2); //总余额 $totalBalance = bcadd($balancePay, $balanceGive, 2); $custom->balance = bcadd($custom->balance, $totalBalance, 2); $hd->balance = bcadd($hd->balance, $totalBalance, 2); $changeAmount = bccomp($beforeBalancePay, 0, 2) === -1 ? $custom->balancePay : $balancePay; // 根据余额欠款,计算变化金额,用于计算积分与成长值 $addIntegralAndGrowth = bccomp($changeAmount, 0, 2) === 1; // 如果变化金额大于0,则计算积分与成长值 if ($addIntegralAndGrowth) { //积分与成长值 $custom->integral = bcadd($custom->integral, $changeAmount, 2); $custom->growth = bcadd($custom->growth, $changeAmount, 2); // 由于没有更新 buyAmount,所以得额外添加更新等级 $memberData = CustomClass::getCustomExpenseLevel($custom->growth, $mainId); // 设置等级多处需要同步修改的,请搜索:getCustomExpenseLevel CustomClass::updateById($customId, [ 'member' => (int) ($memberData['level'] ?? 0), 'memberName' => (string) ($memberData['name'] ?? ''), 'discount' => bcdiv(floatval($memberData['discount']), 10, 2) ]); } $custom->save(); $hd->save(); if ($hd->balance != $custom->balance) { $msg = '充值金额不一致。编号:' . floatval($hd->balance) . ' / ' . floatval($custom->balance); Yii::info($msg); util::fail($msg); } if ($hd->balancePay != $custom->balancePay) { $msg = '充值金额有异常。编号:' . floatval($hd->balancePay) . ' / ' . floatval($custom->balancePay); Yii::info($msg); util::fail($msg); } if ($hd->balanceGive != $custom->balanceGive) { $msg = '充值金额异常。编号:' . floatval($hd->balanceGive) . ' / ' . floatval($custom->balanceGive); Yii::info($msg); util::fail($msg); } $addBalance = bcadd($hd->balanceGive, $hd->balancePay, 2); if (floatval($hd->balance) != floatval($addBalance)) { util::fail('充值金额有问题哦,编号:' . $customId); } $settleId = $recharge->settleId; $settleAmount = 0; $settleNo = ''; $realClearAmount = 0; if (!empty($settleId)) { //如果有结账单,按结账单销账 $set = SettleClass::getById($settleId, true); $res = SettleClass::clearSettle($set, $recharge); $realClearAmount = $res['totalClearAmount'] ?? 0; $settleAmount = $set->actPrice ?? 0; $settleNo = $set->orderSn ?? ''; } else { //没有结账单,按顺序去销订单欠款 $orderList = OrderClass::getAllByCondition(['customId' => $customId, 'debt' => 1], 'id asc', '*', null, true); if (!empty($orderList)) { $lastRemainDebtAmount = 0; $needClearIdMap = []; $hasOver = false; foreach ($orderList as $order) { $orderId = $order->id ?? 0; $orderSn = $order->orderSn ?? ''; //销订单全部的欠款!!! $remainDebtPrice = $order->remainDebtPrice ?? 0; $currentTotalDebtAmount = bcadd($lastRemainDebtAmount, $remainDebtPrice, 2); if ($currentTotalDebtAmount > $totalBalance) { if (!$hasOver) { $lastClearOrderAmount = bcsub($totalBalance, $lastRemainDebtAmount, 2); if ($lastClearOrderAmount > 0) { //销订单部分的欠款!!! $lastClearOrderId = $orderId; $needClearIdMap[] = ['orderId' => $lastClearOrderId, 'clearAmount' => $lastClearOrderAmount, 'orderSn' => $orderSn]; } } $hasOver = true; continue; } $lastRemainDebtAmount = bcadd($lastRemainDebtAmount, $remainDebtPrice, 2); $needClearIdMap[] = ['orderId' => $orderId, 'clearAmount' => $remainDebtPrice, 'orderSn' => $orderSn]; } if (!empty($needClearIdMap)) { //创建结账单,并且销结账单 $staffId = $recharge->staffId ?? 0; $staffName = $recharge->staffName ?? ''; $settleParams = ['staffId' => $staffId, 'staffName' => $staffName]; $set = SettleClass::addSettle($needClearIdMap, $shop, $custom, $hd, $settleParams); $settleId = $set->id; $settleNo = $set->orderSn ?? ''; $settleAmount = $set->actPrice ?? 0; $res = SettleClass::clearSettle($set); $realClearAmount = $res['totalClearAmount'] ?? 0; } } } if ($settleId > 0) { if (floatval($totalBalance) != floatval($realClearAmount) && $hd->balance < 0) { $rechargeId = $recharge->id; noticeUtil::push("注意,充值单,结账金额不一致:getBalance:{$totalBalance} totalAmount:{$realClearAmount},recharge:{$rechargeId}", '15280215347'); util::fail('充值和结账金额异常哈'); } if (floatval($totalBalance) != floatval($settleAmount) && $hd->balance < 0) { $rechargeId = $recharge->id; noticeUtil::push("注意,充值单,结账单不一致:getBalance:{$totalBalance} settleAmount:{$settleAmount},settleId:{$settleId} recharge:{$rechargeId}", '15280215347'); util::fail('充值和结账金额异常呢'); } if (floatval($realClearAmount) != floatval($settleAmount)) { $rechargeId = $recharge->id; noticeUtil::push("注意,结账金额有问题,编号 settleId:{$settleId} recharge:{$rechargeId}", '15280215347'); util::fail('充值结账金额异常呢'); } } $recharge->settleId = $settleId; $recharge->settleAmount = $settleAmount; $recharge->settleNo = $settleNo; $recharge->save(); $remark = $recharge->remark; $change = [ 'customId' => $customId, 'customName' => $customName, 'relateId' => $relateId, 'onlinePay' => $onlinePay, 'capitalType' => $capitalType, 'giveAmount' => $balanceGive, 'amount' => $totalBalance, 'balance' => $hd->balance, 'io' => 1, 'side' => $side, 'payWay' => $payWay, 'event' => $event, 'staffId' => $staffId, 'staffName' => $staffName, 'shopId' => $shopId, 'mainId' => $mainId, 'settleId' => $settleId, 'settleNo' => $settleNo, 'settleAmount' => $settleAmount, 'remark' => $remark, 'shOrderId' => $shOrderId, 'shOrderSn' => $shOrderSn, 'hdId' => $hdId, 'hdName' => $hdName, ]; $returnChange = BalanceChangeClass::add($change, true); $payChange = [ 'customId' => $customId, 'customName' => $customName, 'relateId' => $relateId, 'onlinePay' => $onlinePay, 'capitalType' => $capitalType, 'amount' => $balancePay, 'balance' => $hd->balancePay, 'io' => 1, 'side' => $side, 'payWay' => $payWay, 'event' => $event, 'staffId' => $staffId, 'staffName' => $staffName, 'shopId' => $shopId, 'mainId' => $mainId, 'settleId' => $settleId, 'settleNo' => $settleNo, 'settleAmount' => $settleAmount, 'remark' => $remark, 'shOrderId' => $shOrderId, 'shOrderSn' => $shOrderSn, 'hdId' => $hdId, 'hdName' => $hdName, ]; BalancePayChangeClass::add($payChange, true); if ($balanceGive > 0) { $givChange = [ 'customId' => $customId, 'customName' => $customName, 'relateId' => $relateId, 'onlinePay' => $onlinePay, 'capitalType' => $capitalType, 'amount' => $balanceGive, 'balance' => $hd->balanceGive, 'io' => 1, 'side' => $side, 'payWay' => $payWay, 'event' => $event, 'staffId' => $staffId, 'staffName' => $staffName, 'shopId' => $shopId, 'mainId' => $mainId, 'remark' => $remark, 'hdId' => $hdId, 'hdName' => $hdName, ]; BalanceGiveChangeClass::add($givChange, true); } if ($recharge->onlinePay == 2) { //如果线上充值,门店余额增加 $shop = ShopClass::getLockById($shopId); $main = MainClass::getLockById($mainId); ShopClass::skRechargeAddBalance($main, $shop, $recharge); } else { if ($recharge->payWay == 4) { //现在现金充值要增加现金 $main = MainClass::getLockById($mainId); $cashData = []; $cashData['mainId'] = $mainId; $cashData['sjId'] = 0; $cashData['amount'] = $amount; $cashData['staffId'] = $staffId; $cashData['staffName'] = $staffName; $cashData['customName'] = $customName; $cashData['ptStyle'] = dict::getDict('ptStyle', 'hd'); ShopMoneyClass::skRecharge($cashData, $main); } } if ($addIntegralAndGrowth) { $createTime = date('Y-m-d H:i:s'); //成长值变动记录 $growthData = [ 'shopId' => $shopId, 'userId' => $custom->userId, 'userName' => $custom->name, 'event' => $event, 'relateId' => $relateId, 'relateType' => 0, 'num' => $changeAmount, 'growth' => $custom->growth, 'staffId' => $staffId, //操作人(员工id) 'staffName' => $staffName, //员工名称 'createTime' => $createTime, ]; UserGrowthClass::add($growthData); //积分变动记录 $integralData = [ 'shopId' => $shopId, 'userId' => $custom->userId, 'userName' => $custom->name, 'event' => $event, 'relateId' => $relateId, 'relateType' => 0, 'num' => $changeAmount, 'integral' => $custom->integral, 'staffId' => $staffId, //操作人(员工id) 'staffName' => $staffName, //员工名称 'createTime' => $createTime, ]; UserIntegralClass::add($integralData); } return $returnChange; } /** * 花店后台:对已付款客户充值单退款。线上原路退,线下扣减客户余额;xhRecharge.isRefund 标记退款状态。 */ public static function refundPaidRecharge($rechargeId, $shop, $staff) { $rechargeId = intval($rechargeId); if ($rechargeId <= 0) { util::fail('参数错误'); } $recharge = self::getLockById($rechargeId); if (empty($recharge)) { util::fail('没有找到充值记录'); } if (intval($recharge->mainId ?? 0) !== intval($shop->mainId ?? 0) || intval($recharge->shopId ?? 0) !== intval($shop->id ?? 0)) { util::fail('没有权限操作该充值记录'); } if (intval($recharge->payStatus ?? 0) !== 1 || intval($recharge->status ?? 0) !== 1) { util::fail('仅已付款的充值可退款'); } if (self::isRechargeRefunded($recharge)) { util::fail('该充值已退款'); } $amount = bcadd((string)($recharge->amount ?? '0'), '0', 2); if (bccomp($amount, '0', 2) <= 0) { util::fail('充值金额有误'); } $customId = intval($recharge->customId ?? 0); $hdId = intval($recharge->hdId ?? 0); $custom = CustomClass::getLockById($customId); $hd = HdClass::getLockById($hdId); if (empty($custom) || empty($hd)) { util::fail('没有找到客户余额账户'); } $isOnline = intval($recharge->onlinePay ?? 0) === 2; $payWay = intval($recharge->payWay ?? -1); $wxPay = intval(dict::getDict('payWay', 'wxPay')); $aliPay = intval(dict::getDict('payWay', 'alipay')); $cashPay = intval(dict::getDict('payWay', 'cash')); $onlineMain = null; if ($isOnline) { if ($payWay !== $wxPay && $payWay !== $aliPay) { util::fail('暂不支持该支付方式原路退款'); } $returnCode = trim((string)($recharge->returnCode ?? '')); if ($returnCode === '') { util::fail('缺少支付流水号,无法原路退款'); } $onlineMain = MainClass::getLockById($shop->mainId ?? 0); if (empty($onlineMain)) { util::fail('没有找到资产信息'); } if (bccomp((string)($onlineMain->balance ?? '0'), $amount, 2) < 0) { util::fail('门店余额不足,无法退款'); } self::refundOnlineByLakala($recharge, $shop, $amount, $returnCode); } $giveAmount = bcadd((string)($recharge->giveAmount ?? '0'), '0', 2); if (bccomp($giveAmount, '0', 2) < 0) { $giveAmount = '0.00'; } $currentGive = bcadd((string)($hd->balanceGive ?? '0'), '0', 2); $deductGive = '0.00'; if (bccomp($giveAmount, '0', 2) === 1 && bccomp($currentGive, '0', 2) === 1) { $deductGive = bccomp($currentGive, $giveAmount, 2) >= 0 ? $giveAmount : $currentGive; } $deductPay = bcadd($amount, bcsub($giveAmount, $deductGive, 2), 2); $totalDeduct = bcadd($deductPay, $deductGive, 2); $custom->balancePay = bcsub((string)($custom->balancePay ?? '0'), $deductPay, 2); $hd->balancePay = bcsub((string)($hd->balancePay ?? '0'), $deductPay, 2); if (bccomp($deductGive, '0', 2) === 1) { $custom->balanceGive = bcsub((string)($custom->balanceGive ?? '0'), $deductGive, 2); $hd->balanceGive = bcsub((string)($hd->balanceGive ?? '0'), $deductGive, 2); } $custom->balance = bcsub((string)($custom->balance ?? '0'), $totalDeduct, 2); $hd->balance = bcsub((string)($hd->balance ?? '0'), $totalDeduct, 2); $custom->save(false); $hd->save(false); if (floatval($custom->balance) != floatval($hd->balance) || floatval($custom->balancePay) != floatval($hd->balancePay) || floatval($custom->balanceGive) != floatval($hd->balanceGive)) { util::fail('账户余额有问题,请联系管理员'); } $staffId = intval($staff->id ?? 0); $staffName = (string)($staff->name ?? ''); $capitalType = dict::getDict('capitalType', 'customRechargeRefund', 'id'); $event = '充值退款(操作人:' . $staffName . ')单号:' . ($recharge->orderSn ?? ''); $changeBase = [ 'hdId' => $hdId, 'hdName' => $hd->name ?? ($recharge->hdName ?? ''), 'customId' => $customId, 'customName' => $custom->name ?? ($recharge->customName ?? ''), 'relateId' => $rechargeId, 'onlinePay' => $recharge->onlinePay ?? 1, 'capitalType' => $capitalType, 'side' => 0, 'payWay' => $payWay, 'event' => $event, 'staffId' => $staffId, 'staffName' => $staffName, 'shopId' => $recharge->shopId ?? 0, 'mainId' => $recharge->mainId ?? 0, 'remark' => '', ]; BalanceChangeClass::add(array_merge($changeBase, [ 'amount' => $totalDeduct, 'balance' => $hd->balance, 'io' => 0, ]), true); BalancePayChangeClass::add(array_merge($changeBase, [ 'amount' => $deductPay, 'balance' => $hd->balancePay, 'io' => 0, ]), true); if (bccomp($deductGive, '0', 2) === 1) { BalanceGiveChangeClass::add(array_merge($changeBase, [ 'amount' => $deductGive, 'balance' => $hd->balanceGive, 'io' => 0, ]), true); } if ($isOnline) { $main = $onlineMain ?: MainClass::getLockById($shop->mainId ?? 0); if (empty($main)) { util::fail('没有找到资产信息'); } ShopClass::customRechargeRefundReduceBalance($main, $shop, $recharge, dict::getDict('capitalType', 'xhRecharge', 'id'), $staffName); } elseif ($payWay === $cashPay) { self::cashRechargeRefundReduceMoney($recharge, $shop, $staffName, $amount); } self::markRechargeRefunded($recharge); $recharge->balance = $hd->balance; $recharge->save(false); return $recharge; } protected static function cashRechargeRefundReduceMoney($recharge, $shop, $staffName, $amount) { $main = MainClass::getLockById($shop->mainId ?? 0); if (empty($main)) { util::fail('没有找到现金账户'); } if (bccomp((string)($main->money ?? '0'), $amount, 2) < 0) { util::fail('现金不足' . floatval($amount) . '元'); } $main->money = bcsub((string)$main->money, $amount, 2); $main->save(false); ShopMoneyClass::addData([ 'mainId' => $shop->mainId ?? 0, 'sjId' => 0, 'amount' => $amount, 'balance' => $main->money, 'io' => 0, 'staffId' => $recharge->staffId ?? 0, 'staffName' => $staffName, 'customName' => $recharge->customName ?? '', 'ptStyle' => dict::getDict('ptStyle', 'hd'), 'capitalType' => dict::getDict('capitalType', 'xhRecharge', 'id'), 'event' => ($recharge->customName ?? '客户') . '现金充值退款' . floatval($amount) . '元', 'remark' => '操作人:' . $staffName, ]); } protected static function refundOnlineByLakala($recharge, $shop, $amount, $returnCode) { $termNo = $shop->lklScanTermNo ?? ''; if (intval($recharge->payWay ?? 0) === intval(dict::getDict('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'; $laResource = new Lakala([ 'appid' => 'OP00002119', 'serial_no' => '018b08cfddbd', 'merchant_no' => $shop->lklSjNo, 'term_no' => $termNo, 'merchantPrivateKeyPath' => $merchantPrivateKeyPath, 'lklCertificatePath' => $lklCertificatePath, ]); $response = $laResource->refund([ 'refundSn' => orderSn::getRechargeSn(), 'orderSn' => $recharge->orderSn ?? '', 'refundAmount' => bcmul($amount, 100), 'refundReason' => '充值退款', 'thirdNo' => $returnCode, ]); if (!isset($response['code']) || $response['code'] != 'BBS00000') { util::fail('原路退款失败:' . ($response['msg'] ?? '退款失败')); } } protected static function isRechargeRefunded($recharge) { if (empty($recharge)) { return true; } if (self::modelHasAttr($recharge, 'isRefund')) { return intval($recharge->isRefund ?? 0) === 1; } return false; } protected static function markRechargeRefunded($recharge) { if (empty($recharge) || !self::modelHasAttr($recharge, 'isRefund')) { return; } $recharge->isRefund = 1; $recharge->save(false, ['isRefund']); } protected static function modelHasAttr($model, $attr) { return is_object($model) && method_exists($model, 'hasAttribute') && $model->hasAttribute($attr); } /** * 售后付款单是否已经充值过了 ssh 20250801 */ public static function checkShOrderRecharge($order) { $orderId = $order->id; $has = self::getByCondition(['shOrderId' => $orderId, 'payStatus' => 1]); if (!empty($has)) { util::fail('已经充值过了,无需再次操作'); } } public static function getStatProfile($shopId, $params = []) { $searchTime = $params['searchTime'] ?? 'today'; $startTime = $params['startTime'] ?? ''; $endTime = $params['endTime'] ?? ''; $range = dateUtil::formatTime($searchTime, $startTime, $endTime); $start = $range['startTime']; $end = $range['endTime']; $cacheKey = 'hd_recharge_stat:' . $shopId . '_' . md5($start . '_' . $end); $cache = Yii::$app->redis->executeCommand('GET', [$cacheKey]); if (!empty($cache)) { $data = json_decode($cache, true); if (is_array($data)) { return $data; } } $summary = self::getRechargeStatSummary($shopId, $start, $end); $channelList = self::getRechargeStatChannelList($shopId, $start, $end); $customerList = self::getRechargeStatCustomerList($shopId, $start, $end); $data = [ 'summary' => $summary, 'channelList' => $channelList, 'customerList' => $customerList, 'startTime' => $start, 'endTime' => $end, ]; Yii::$app->redis->executeCommand('SETEX', [$cacheKey, self::STAT_CACHE_TTL, json_encode($data, JSON_UNESCAPED_UNICODE)]); return $data; } private static function getPaidQuery($shopId, $start, $end) { $model = self::getActiveRecord(); return $model::find() ->where([ 'shopId' => $shopId, 'payStatus' => 1, 'status' => 1, ]) ->andWhere(['between', 'addTime', $start, $end]); } private static function getRechargeStatSummary($shopId, $start, $end) { $row = self::getPaidQuery($shopId, $start, $end) ->select([ 'rechargeCount' => new Expression('SUM(CASE WHEN IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0 THEN 1 ELSE 0 END)'), 'reduceCount' => new Expression('SUM(CASE WHEN IFNULL(isRefund, 0) = 1 THEN 1 ELSE 0 END)'), 'realAmount' => new Expression('IFNULL(SUM(amount), 0)'), 'giveAmount' => new Expression('IFNULL(SUM(giveAmount), 0)'), 'reduceAmount' => new Expression('IFNULL(SUM(CASE WHEN IFNULL(isRefund, 0) = 1 THEN amount ELSE 0 END), 0)'), ]) ->asArray() ->one(); $realAmount = $row['realAmount'] ?? 0; $giveAmount = $row['giveAmount'] ?? 0; $reduceAmount = $row['reduceAmount'] ?? 0; return [ 'rechargeAmount' => self::moneyAdd($realAmount, $giveAmount), 'rechargeCount' => intval($row['rechargeCount'] ?? 0), 'reduceAmount' => self::moneyValue($reduceAmount), 'reduceCount' => intval($row['reduceCount'] ?? 0), 'realAmount' => self::moneyValue($realAmount), ]; } private static function getRechargeStatChannelList($shopId, $start, $end) { $rows = self::getPaidQuery($shopId, $start, $end) ->select([ 'channelKey' => new Expression("IF(onlinePay = 2, CONCAT('online_', payWay), CONCAT('pay_', payWay))"), 'rechargeCount' => new Expression('SUM(CASE WHEN IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0 THEN 1 ELSE 0 END)'), 'reduceCount' => new Expression('SUM(CASE WHEN IFNULL(isRefund, 0) = 1 THEN 1 ELSE 0 END)'), 'realAmount' => new Expression('IFNULL(SUM(amount), 0)'), 'giveAmount' => new Expression('IFNULL(SUM(giveAmount), 0)'), 'reduceAmount' => new Expression('IFNULL(SUM(CASE WHEN IFNULL(isRefund, 0) = 1 THEN amount ELSE 0 END), 0)'), ]) ->groupBy(new Expression("IF(onlinePay = 2, CONCAT('online_', payWay), CONCAT('pay_', payWay))")) ->asArray() ->all(); $payWayName = dict::getDict('payWayName'); $defaultList = [ 'online_0' => '线上微信', 'online_1' => '线上支付宝', 'pay_0' => '线下微信', 'pay_1' => '线下支付宝', 'pay_4' => '现金', 'pay_5' => '银行卡', ]; $map = []; foreach ($rows as $row) { $key = $row['channelKey'] ?? ''; $payWay = intval(str_replace('pay_', '', $key)); $map[$key] = self::buildStatRow( $defaultList[$key] ?? ($payWayName[$payWay] ?? '其它'), $row ); } $list = []; foreach ($defaultList as $key => $name) { $list[] = $map[$key] ?? self::emptyStatRow($name); unset($map[$key]); } foreach ($map as $item) { $list[] = $item; } return $list; } private static function getRechargeStatCustomerList($shopId, $start, $end) { $rows = self::getPaidQuery($shopId, $start, $end) ->select([ 'customId', 'customName', 'rechargeCount' => new Expression('SUM(CASE WHEN IFNULL(amount, 0) + IFNULL(giveAmount, 0) > 0 THEN 1 ELSE 0 END)'), 'reduceCount' => new Expression('SUM(CASE WHEN IFNULL(isRefund, 0) = 1 THEN 1 ELSE 0 END)'), 'realAmount' => new Expression('IFNULL(SUM(amount), 0)'), 'giveAmount' => new Expression('IFNULL(SUM(giveAmount), 0)'), 'reduceAmount' => new Expression('IFNULL(SUM(CASE WHEN IFNULL(isRefund, 0) = 1 THEN amount ELSE 0 END), 0)'), ]) ->groupBy(['customId', 'customName']) ->orderBy(new Expression('IFNULL(SUM(amount), 0) + IFNULL(SUM(giveAmount), 0) DESC')) ->limit(100) ->asArray() ->all(); $list = []; foreach ($rows as $row) { $list[] = self::buildStatRow($row['customName'] ?: '未命名', $row); } return $list; } private static function buildStatRow($name, $row) { $realAmount = $row['realAmount'] ?? 0; $giveAmount = $row['giveAmount'] ?? 0; return [ 'customId' => $row['customId'] ?? 0, 'name' => $name, 'rechargeAmount' => self::moneyAdd($realAmount, $giveAmount), 'rechargeCount' => intval($row['rechargeCount'] ?? 0), 'reduceAmount' => self::moneyValue($row['reduceAmount'] ?? 0), 'reduceCount' => intval($row['reduceCount'] ?? 0), 'realAmount' => self::moneyValue($realAmount), ]; } private static function emptyStatRow($name) { return [ 'name' => $name, 'rechargeAmount' => '0.00', 'rechargeCount' => 0, 'reduceAmount' => '0.00', 'reduceCount' => 0, 'realAmount' => '0.00', ]; } private static function moneyAdd($left, $right) { return self::moneyValue(bcadd((string)$left, (string)$right, 2)); } private static function moneyValue($amount) { return number_format((float)$amount, 2, '.', ''); } }