# 某大型项目应用本Redis类源码示例(含事务 乐观锁) ### 服务层源码 ~~~ /** * @description * @author Mikkle */ public function completeParkByBill($data){ $this->functionName = __FUNCTION__; $this->args = $data; //检验数据 if ( ! isset($data[OptionsCenter::$fieldChargeToken]) || ! $this->parseToken($data[OptionsCenter::$fieldChargeToken]) ){ $this->addError("登录Token参数缺失或已经失效"); return ShowCode::jsonCodeWithoutData(1003,$this->error); } if(! $this->checkArrayValueEmpty($data,[OptionsCenter::$fieldBillNum,OptionsCenter::$fieldPayMoney])){ $this->addError("信息中缺失必要的信息"); return ShowCode::jsonCodeWithoutData(1003,$this->error); } $billCenter = BillInfoCenter::instance($data[OptionsCenter::$fieldBillNum]); $data[OptionsCenter::$fieldSerialNum] = $billCenter->getParkCarSerialNum(); $data[OptionsCenter::$fieldParkMoney] = $billCenter->getInfoFieldValue(OptionsCenter::$fieldParkMoney); $data[OptionsCenter::$fieldBillMoney] = $billCenter->getInfoFieldValue(OptionsCenter::$fieldBillMoney); if (!is_numeric($data[OptionsCenter::$fieldBillMoney])|| !is_numeric($data[OptionsCenter::$fieldPayMoney]) ){ $this->addError("账单金额类型错误"); return ShowCode::jsonCodeWithoutData(1003,$this->error); }elseif ( $data[OptionsCenter::$fieldPayMoney]<=0){ $this->addError("付款金额不能小于等于0"); return ShowCode::jsonCodeWithoutData(1003,$this->error); }elseif ($data[OptionsCenter::$fieldBillMoney] != $data[OptionsCenter::$fieldPayMoney]){ if ($data[OptionsCenter::$fieldBillMoney]> $data[OptionsCenter::$fieldPayMoney]){ if (!$this->checkArrayValueEmpty($data,[ OptionsCenter::$fieldDebtType]) || $data[ OptionsCenter::$fieldDebtType] !=2 ){ $this->addError("付款金额小于订单金额时,缺失拒付类型正确参数"); return ShowCode::jsonCodeWithoutData(1003,$this->error); } }elseif ($data[OptionsCenter::$fieldBillMoney] < $data[OptionsCenter::$fieldPayMoney]){ $this->addError("付款金额不可以大于订单金额"); return ShowCode::jsonCodeWithoutData(1003,$this->error); } } //流水号信息验证 if ( ! isset($data[OptionsCenter::$fieldSerialNum]) || empty($data[OptionsCenter::$fieldSerialNum]) ){ $this->addError("信息中缺失必要的停车序号信息"); return ShowCode::jsonCodeWithoutData(1003,$this->error); } if (!AuthCenter::existParkSerialBySerialId($data[OptionsCenter::$fieldSerialNum])){ $this->addError("信息中的序号信息不正确"); return ShowCode::jsonCodeWithoutData(1003,$this->error); }; $carSerialCenter = CarSerialCenter::instance($data[OptionsCenter::$fieldSerialNum]); $parkingInfo = $carSerialCenter->getParkingInfo($this->options); if ($parkingInfo[OptionsCenter::$fieldBillNum] != $data[OptionsCenter::$fieldBillNum]){ $this->addError("你的Bill单号已经过期,请使用最新的Bill号"); return ShowCode::jsonCodeWithoutData(1003,$this->error); } //检测流水订单状态 if (!$this->checkParkSerialBillState($parkingInfo)){ return ShowCode::jsonCodeWithoutData(1003,$this->error); } //判断账单是否有5分钟内的结清账单 if ($this->checkBillPayState($parkingInfo)){ return ShowCode::jsonCode(1099,[OptionsCenter::$fieldSerialNum=>$data[OptionsCenter::$fieldSerialNum]]); } $endTime = $billCenter->getInfoFieldValue(OptionsCenter::$fieldEndTime); //附加上收费员信息和日报ID $data[OptionsCenter::$idCharge] = $this->chargeId; $data[OptionsCenter::$idDocument] = $this->terminalId; if ($data[OptionsCenter::$fieldBillMoney] == $data[OptionsCenter::$fieldPayMoney] ){ $status = 2; }elseif($data[OptionsCenter::$fieldBillMoney] > $data[OptionsCenter::$fieldPayMoney]){ $status = 1; }else{ $status = 0; } //获取已经付款金额 $alreadyPayMoney = $this->getAlreadyPayMoney($parkingInfo); if ($alreadyPayMoney>0){ } $billData =[ OptionsCenter::$fieldBillNum=>$data[OptionsCenter::$fieldBillNum], OptionsCenter::$fieldPayMoney => $data[OptionsCenter::$fieldPayMoney], OptionsCenter::$fieldBillTime =>$this->getTime($endTime), OptionsCenter::$fieldBillStatus =>$status , ]; $serialData= [ OptionsCenter::$prefixEnd . OptionsCenter::$idCharge => $this->chargeId, OptionsCenter::$prefixEnd . OptionsCenter::$nameCharge => $this->chargeName, OptionsCenter::$prefixEnd . OptionsCenter::$idTerminal => $this->terminalId, OptionsCenter::$fieldParkMoney => $data[OptionsCenter::$fieldParkMoney] , //总付款金额 OptionsCenter::$fieldPayMoney => $alreadyPayMoney+$data[OptionsCenter::$fieldPayMoney], OptionsCenter::$fieldPayStatus => $status , //已结清费用2 部分为1 OptionsCenter::$fieldEndTime => $this->getTime($endTime), OptionsCenter::$fieldCompleteTime => time(), OptionsCenter::$stringStatus => 2, ]; switch (true){ //全款结账账单 case($status==2): if ( !$carSerialCenter->completeBillSerialByAllCash($data,$serialData,$billData)){ return ShowCode::jsonCode(1008,"存储停车信息失败"); } //处理报表信息 DocumentInfoCenter::instance($this->documentId)->updateDocumentByParkSerialNum($data[OptionsCenter::$fieldSerialNum]); //清除泊位信息 if ($this->checkArrayValueEmpty($parkingInfo,OptionsCenter::$idPlace)){ $this->clearPlaceParkInfo($parkingInfo[OptionsCenter::$idPlace],$data[OptionsCenter::$fieldSerialNum]); } return ShowCode::jsonCode(1001, $carSerialCenter->getParkingInfo(),"",[OptionsCenter::$stringVersion=>ParkInfoCenter::instance($this->parkId)->updateVersion()]); break; //拒付部分订单 case($status==1): if ( !$carSerialCenter->completeBillSerialByPartCash($data,$serialData,$billData)){ return ShowCode::jsonCode(1008,"存储停车信息失败"); } //处理报表信息 DocumentInfoCenter::instance($this->documentId)->updateDocumentByParkSerialNum($data[OptionsCenter::$fieldSerialNum]); //清除泊位信息 if ($this->checkArrayValueEmpty($parkingInfo,OptionsCenter::$idPlace)){ $this->clearPlaceParkInfo($parkingInfo[OptionsCenter::$idPlace],$data[OptionsCenter::$fieldSerialNum]); } return ShowCode::jsonCode(1001, $carSerialCenter->getParkingInfo(),"",[OptionsCenter::$stringVersion=>ParkInfoCenter::instance($this->parkId)->updateVersion()]); break; } return ShowCode::jsonCode(1008,"你不应该看到这个"); } ~~~ ### 数据逻辑处理 ~~~ /** * @description * @author Mikkle */ public function completeBillSerialByPartCash($data, $serialData, $billData){ //获取当前的收费员的帐号余额和版本号 $chargeAmount = Db::table(OptionsCenter::$tableCharge) ->where([OptionsCenter::$pk =>$data[OptionsCenter::$idCharge]]) ->field([OptionsCenter::$stringAmount,OptionsCenter::$prefixAmount.OptionsCenter::$stringVersion])->find(); if (!is_numeric($chargeAmount[OptionsCenter::$stringAmount]) || !is_numeric($chargeAmount[OptionsCenter::$prefixAmount.OptionsCenter::$stringVersion]) ){ throw new Exception("收费员的余款数据不正确"); } $amount = (int)$chargeAmount[OptionsCenter::$stringAmount]; $newAmount = $amount-(int)$data[OptionsCenter::$fieldPayMoney]; $version = (int)$chargeAmount[OptionsCenter::$prefixAmount.OptionsCenter::$stringVersion]; //收费员账户流水表信息 $chargePriceDate = [ OptionsCenter::$fieldBillNum=>$data[OptionsCenter::$fieldBillNum], OptionsCenter::$stringType=>2, //金额的类型 (1为 充值 2为扣除) OptionsCenter::$stringMode=>2 , //充值方式(1 人工充值或扣除) 2 现金缴款扣除 OptionsCenter::$stringDesc=>"停车单:{$data[OptionsCenter::$fieldBillNum]}扣款", OptionsCenter::$stringPrice => $data[OptionsCenter::$fieldPayMoney], OptionsCenter::$stringAmount => $newAmount, ]; $serialInfo = $this->getInfoList(); //设置拒付信息 $debtData=[ OptionsCenter::$fieldDebtNum=>RandNumCenter::createDebtSerialNumber(), //欠费流水号 OptionsCenter::$fieldSerialNum=> $serialInfo[OptionsCenter::$fieldSerialNum], //停车流水号 OptionsCenter::$fieldCarCode=>$serialInfo[OptionsCenter::$fieldCarCode], OptionsCenter::$idPark=>$serialInfo[OptionsCenter::$idPark], OptionsCenter::$namePark=>$serialInfo[OptionsCenter::$namePark], OptionsCenter::$fieldDebtType=>2, //拒缴部分 OptionsCenter::$fieldStartTime=>$serialInfo[OptionsCenter::$fieldStartTime], OptionsCenter::$prefixStart.OptionsCenter::$idCharge=>$serialInfo[OptionsCenter::$prefixStart.OptionsCenter::$idCharge], OptionsCenter::$prefixStart.OptionsCenter::$nameCharge=>$serialInfo[OptionsCenter::$prefixStart.OptionsCenter::$nameCharge], OptionsCenter::$fieldEndTime=>$serialData[OptionsCenter::$fieldEndTime], OptionsCenter::$prefixEnd.OptionsCenter::$idCharge => $serialData[OptionsCenter::$prefixEnd.OptionsCenter::$idCharge], OptionsCenter::$prefixEnd.OptionsCenter::$nameCharge => $serialData[OptionsCenter::$prefixEnd.OptionsCenter::$nameCharge], OptionsCenter::$stringStatus=>1, OptionsCenter::$fieldCreateTime=>time(), OptionsCenter::$fieldParkMoney=>$serialData[OptionsCenter::$fieldParkMoney], OptionsCenter::$fieldPayMoney=>$serialData[OptionsCenter::$fieldPayMoney], OptionsCenter::$fieldDebtMoney => (int)($serialData[OptionsCenter::$fieldParkMoney] - $serialData[OptionsCenter::$fieldPayMoney]) , ]; //设置付款信息 $payDate=[ OptionsCenter::$fieldPayNum=>RandNumCenter::createPaySerialNumber(), OptionsCenter::$fieldBillNum=>$data[OptionsCenter::$fieldBillNum], OptionsCenter::$fieldSerialNum=>$this->infoId, OptionsCenter::$idPark=>$serialData[OptionsCenter::$idPark], OptionsCenter::$fieldPayType=>1, OptionsCenter::$fieldPayMoney=>$data[OptionsCenter::$fieldPayMoney], OptionsCenter::$fieldPayTime=>RandNumCenter::getTimeString(), OptionsCenter::$fieldCreateTime=>time(), OptionsCenter::$stringStatus=>1, ]; try{ //多表处理 开启事务 Db::startTrans(); //升级收费员余额 加入了乐观锁判断 if (!Db::table(OptionsCenter::$tableCharge) ->where([OptionsCenter::$pk=>$data[OptionsCenter::$idCharge],OptionsCenter::$prefixAmount.OptionsCenter::$stringVersion =>$version ]) ->update([OptionsCenter::$stringAmount=>$newAmount,OptionsCenter::$prefixAmount.OptionsCenter::$stringVersion=>$version+1]) ){ throw new Exception("操作员的余额信息已经变动,请重试"); } //插入欠费信息 if (!Db::table(OptionsCenter::$tableParkInfoDebt)->insert($debtData)){ throw new Exception("插入欠费信息失败"); } //插入付款流水信息 if (!Db::table(OptionsCenter::$tableParkInfoPay)->insert($payDate)){ throw new Exception("插入付款流水信息失败"); } //插入金额流水信息 if (!Db::table(OptionsCenter::$tableChargePrice)->insert($chargePriceDate)){ throw new Exception("插入金额流水信息失败"); } if (!Db::table(OptionsCenter::$tableParkInfoTemp)->where([OptionsCenter::$fieldSerialNum=>$this->infoId])->update($serialData)){ throw new Exception("保存订单流水信息失败"); } if (!Db::table(OptionsCenter::$tableParkInfoBill)->where([OptionsCenter::$fieldBillNum=>$data[OptionsCenter::$fieldBillNum]])->update($billData)){ throw new Exception("完成账单信息失败"); } $this->updateAllBillBySerialNumToComplete(); //更新流水信息 $this->setInfoArray($serialData); //更新账单信息 BillInfoCenter::instance($data[OptionsCenter::$fieldBillNum])->setInfoArray($billData); //设置7天 自动释放redis内存 BillInfoCenter::instance($data[OptionsCenter::$fieldBillNum])->setExpire(3600*24*7); //更新帐号余额 ChargeInfoCenter::instance($data[OptionsCenter::$idCharge])->refreshChargeAmount($newAmount); //处理泊位信息 $this->setExpire(3600*24*7); Db::commit(); return true; }catch (Exception $e){ Log::error($e->getMessage()); dump($e); Db::rollback(); return false; } } ~~~ 感谢大家关注 交流请加QQ群 321449759 ![](https://box.kancloud.cn/3499008a08e64306c68873288092a057_286x340.png)