userOperateLogger = new UserOperate([ 'fetchClass' => Withdraw::class, ]); } /** * @inheritdoc */ public function rules() { return [ [['id', 'userName', 'realName', 'idCard', 'regType', 'applyAmount', 'payPassword', 'planPaidAt', 'auditStatus', 'createdAt', 'remark', 'createRemark', 'selectedIds', 'sn', 'withdrawPeriodNum', 'paidAt', 'paidFailRemark', 'amount', 'bankRealName', 'bankNo'], 'trim'], [['id', 'userName', 'applyAmount', 'payPassword', 'auditStatus','withdrawCode','withdrawAudit'], 'required'], [['id'], 'exist', 'targetClass' => Withdraw::class, 'targetAttribute' => 'ID', 'message' => Yii::t('ctx', 'withdrawalApplyDoesNotExist')], [['userName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME', 'message' => Yii::t('ctx', 'memberDoesNotExist')], [['applyAmount'], 'price'], [['applyAmount'], 'isApplyAmount'], [['userName'], 'isUserName'], [['payPassword'], 'validatePassword'], [['withdrawCode'], 'validateCode'], [['withdrawAudit'], 'validateAuditCode'], [['planPaidAt'], 'isPlanPaidAt'], [['selectedIds'], 'isSelected'], [['sn'], 'isSn'], //[['auditStatus'], 'isStatus'], ]; } /** * 指定场景 * @return array */ public function scenarios() { $parentScenarios = parent::scenarios(); $customScenarios = [ 'addByAdmin' => ['userName', 'realName', 'idCard', 'regType', 'applyAmount', 'createRemark'], 'addByUser' => ['applyAmount', 'payPassword','withdrawCode'], 'addByAuto' => ['userName', 'applyAmount'], 'statusByAdmin' => ['selectedIds', 'auditStatus', 'createRemark','planPaidAt', 'paidAt','withdrawAudit'], 'editByAdmin' => ['id', 'planPaidAt', 'createRemark'], 'backByUser' => ['id', 'createRemark'], 'excelPaidFalse' => ['sn', 'withdrawPeriodNum', 'paidAt', 'paidFailRemark', 'userName', 'realName', 'amount', 'bankRealName', 'bankNo'], 'batchWithdraw' => ['userName', 'applyAmount'] ]; return array_merge($parentScenarios, $customScenarios); } /** * @return array */ public function attributeLabels() { return [ 'id' => '提现申请ID', 'userName' => '会员编号', 'applyAmount' => '申请提现的金额', 'withdrawCode' => '申请提现校验码', 'withdrawAudit' => '提现审核校验码', ]; } /** * 用户名是否正确 * @param $attributes * @throws Exception */ public function isUserName($attributes) { $userInfo = UserInfo::findOneAsArray(['USER_NAME' => $this->userName]); if ($userInfo) { if ($this->scenario == 'addByAdmin') { $baseInfo = Info::baseInfoZh($userInfo['USER_ID']); if ($baseInfo['REAL_NAME'] != $this->realName || $baseInfo['ID_CARD'] != $this->idCard) { $this->addError($attributes, Yii::t('ctx', 'memberNameOrNumberInconsistentSystem')); } if ($userInfo['REG_TYPE'] != $this->regType) { $this->addError($attributes, Yii::t('ctx', 'memberRegisterTypeInconsistentWithSystem')); } } $this->_userId = $userInfo['USER_ID']; } else { $this->addError($attributes, $this->userName . Yii::t('ctx', 'memberDoesNotExist')); } } /** * 校验申请金额是否小于当前余额并符合配置中的设置 * @param $attribute * @return bool */ public function isApplyAmount($attribute) { $config = Cache::getSystemConfig(); if ($this->applyAmount <= 0) { $this->addError('scenario', Yii::t('ctx', 'withdrawalMustGreaterThanZero')); } if ((int)($this->applyAmount)!=$this->applyAmount) { $this->addError('scenario', Yii::t('ctx', 'withdrawalAmountMustInteger')); } $minAmount = 0; $maxAmount = 0; if ($this->scenario == 'addByUser') { $minAmount = $config['manualWithdrawMinAmount']['VALUE']; // $maxAmount = $config['manualWithdrawMaxAmount']['VALUE']; $this->_userId = \Yii::$app->user->id; } elseif ($this->scenario == 'addByAdmin') { $userInfo = UserInfo::findOneAsArray(['USER_NAME' => $this->userName]); $this->_userId = $userInfo['USER_ID']; } else { $this->addError($attribute, Yii::t('ctx', 'sceneDoesNotExist')); return false; } if ($minAmount != 0 && $this->applyAmount < $minAmount) { $this->addError($attribute, Yii::t('ctx', 'withdrawalAmountCannotLessThan') . $minAmount . Yii::t('ctx', 'amountUnit')); } if ($maxAmount != 0 && $this->applyAmount > $maxAmount) { $this->addError($attribute, Yii::t('ctx', 'WithdrawalAmountCannotHigherThan') . $maxAmount . Yii::t('ctx', 'amountUnit')); } // 提现条件判断 $orderAmount = Order::find()->where('USER_ID=:USER_ID', [':USER_ID' => $this->_userId])->SUM('ORDER_AMOUNT'); $recNum = intval(DecOrder::find()->where('REC_USER_ID=:REC_USER_ID', [':REC_USER_ID' => $this->_userId])->count()); //$recNum = UserRelation::firstFloorChildNum($this->_userId); // if ($orderAmount < 300 && $recNum==0) { // $this->addError($attribute, '奖金不能提现'); // return null; // } // 获取当前提现用户的金额 if ($this->applyAmount > Balance::getAvailableBalance($this->_userId)) { $this->addError('scenario', Yii::t('ctx', 'withdrawalAmountMustLessThanAvailableBalance')); } } /** * 校验支付密码 * @param $attribute * @param $params */ public function validatePassword($attribute, $params) { if (!User::validatePayPassword($this->_userId, $this->payPassword)) { $this->addError($attribute, Yii::t('ctx', 'paymentPasswordIncorrect'));//支付密码不正确 } } public function validateCode($attribute) { $uid = \Yii::$app->user->id; $redisCode = \Yii::$app->redis->getset('withdrawCode_'.$uid,''); \Yii::$app->redis->del('withdrawCode_'.$uid); if ($this->withdrawCode!=$redisCode) { $this->addError($attribute, Yii::t('ctx', 'failedApplyWithdrawalVerify')); } } public function validateAuditCode($attribute) { $adminId = \Yii::$app->user->id; $redisCode = \Yii::$app->redis->getset('withdrawAudit_'.$adminId,''); if ($this->withdrawAudit!=$redisCode) { $this->addError($attribute, Yii::t('ctx', 'withdrawalAuditVerificationFailed')); } } /** * 批量数据 * @param $attributes */ public function isSelected($attributes) { if (!$this->selectedIds) { $this->addError($attributes, Yii::t('ctx', 'aPieceMustBeSelected')); // 必须选择一条数据 } if (!is_array($this->selectedIds)) { $this->selectedIds = [$this->selectedIds]; } } /** * 校验状态 * @param $attribute */ public function isStatus($attribute) { } /** * 计划付款日期 * @param $attribute */ public function isPlanPaidAt($attribute) { if (Date::utcToTime($this->planPaidAt) < Date::nowTime()) { $this->addError($attribute, Yii::t('ctx', 'cannotSelectDateInThePast')); } } /** * 判断信息是否一致 * @param $attribute * @throws Exception */ public function isSn($attribute) { $sn = $this->sn; if (!$oneWithdraw = Withdraw::findOneAsArray('SN=:SN AND AUDIT_STATUS=:AUDIT_STATUS', [':SN' => $sn, ':AUDIT_STATUS' => Withdraw::STATUS_PAID])) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormNoSn', ['sn' => $sn])); } if ($oneWithdraw) { $info = Info::baseInfo($oneWithdraw['USER_ID']); if ($this->userName != $info['USER_NAME']) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormUserNameInconsistent', ['excelName' => $this->userName, 'userName' => $info['USER_NAME']])); } if ($this->realName != $info['REAL_NAME']) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormRealNameInconsistent', [ 'sn' => $sn, 'excelName' => $this->realName, 'realName' => $info['REAL_NAME'] ])); } if ($this->withdrawPeriodNum != $oneWithdraw['WITHDRAW_PERIOD_NUM']) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormPeriodsInconsistent', [ 'sn' => $sn, 'withdrawPeriodNum' => $this->withdrawPeriodNum, 'systemWithdrawPeriodNum' => $oneWithdraw['WITHDRAW_PERIOD_NUM'] ])); } if (Date::convert(Date::utcToTime($this->paidAt)) != Date::convert($oneWithdraw['PAID_AT'])) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormPaidAtInconsistent', [ 'sn' => $sn, 'paidAt' => Date::convert(Date::utcToTime($this->paidAt)), 'systemPaidAt' => Date::convert($oneWithdraw['PAID_AT']) ])); } if ($this->amount != $oneWithdraw['AMOUNT']) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormAmountInconsistent', [ 'sn' => $sn, 'execlAmount' =>$this->amount, 'systemAmount' => $oneWithdraw['AMOUNT'] ])); } if ($this->bankRealName != $oneWithdraw['REAL_NAME']) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormBankRealNameInconsistent', [ 'sn' => $sn, 'execlBankRealName' =>$this->bankRealName, 'systemName' => $oneWithdraw['REAL_NAME'] ])); } if ($this->bankNo != $oneWithdraw['BANK_NO']) { $this->addError($attribute, Yii::t('ctx', 'withdrawFormBankNoInconsistent', [ 'sn' => $sn, 'excelBankNo' =>$this->bankNo, 'systemBankNo' => $oneWithdraw['BANK_NO'] ])); } } } /** * 添加提现申请 * @return null|string * @throws \yii\db\Exception */ public function add() { if (!$this->validate()) { return false; } $beforeData = Balance::getLogData(\Yii::$app->user->id); $this->userOperateLogger->saveBeforeContent=$beforeData; $config = Cache::getSystemConfig(); $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { $nowTime = $this->createdAt ? $this->createdAt : Date::nowTime(); $period = Withdraw::getPeriod($nowTime); //扣除会员奖金 Balance::changeUserBonus($this->_userId, 'BONUS', -abs($this->applyAmount), ['DEAL_TYPE_ID'=>DealType::WITHDRAW,'REMARK' => 'Period '. $period['nowPeriodNum'].' '.($this->scenario == 'addByAuto' ? 'auto withdrawal' : 'manual withdrawal'), 'TIME' => $nowTime]); //增加记录 $userInfo = Info::baseInfo($this->_userId); //手续费 $fees = $this->applyAmount * $config['withdrawFee']['VALUE']/100; $fees = Tool::formatPrice($fees); $realAmount = $this->applyAmount - $fees; //判断付款类型 $payType = Withdraw::PAY_TYPE_NO_INVOICE; $withdrawModel = new Withdraw(); $withdrawModel->SN = $this->_generateSn(); $withdrawModel->USER_ID = $this->_userId; $withdrawModel->ID_CARD = $userInfo['ID_CARD']; $withdrawModel->WITHDRAW_PERIOD_NUM = $period['nowPeriodNum']; $withdrawModel->WITHDRAW_YEAR = $period['nowYear']; $withdrawModel->WITHDRAW_MONTH = $period['nowMonth']; $withdrawModel->PAY_TYPE = $payType; $withdrawModel->IS_AUTO_WITHDRAW = $this->scenario == 'addByAuto' ? 1 : 0; $withdrawModel->AMOUNT = $this->applyAmount; $withdrawModel->FEES = $fees; $withdrawModel->REAL_AMOUNT = $realAmount; $withdrawModel->P_MONTH = Date::ociToDate($period['yearMonth'], Date::OCI_TIME_FORMAT_SHORT_MONTH); // if ($payType == Withdraw::PAY_TYPE_NO_INVOICE) { // $withdrawModel->AUDIT_STATUS = Withdraw::STATUS_AUDITED; // $withdrawModel->AUDITED_AT = $nowTime; // } else { $withdrawModel->AUDIT_STATUS = Withdraw::STATUS_APPLIED; // } $withdrawModel->CREATED_AT = $nowTime; //预计付款时间 $withdrawModel->PLAN_PAID_AT = $period['endTime'] + $config['withdrawFreezeDays']['VALUE'] * 3600 * 24; if ($this->scenario == 'addByAdmin') { $withdrawModel->UPDATE_ADMIN = \Yii::$app->user->id; $withdrawModel->UPDATE_REMARK = $this->createRemark; } if (!$withdrawModel->save()) { throw new Exception(Form::formatErrorsForApi($withdrawModel->getErrors())); } //考核会员注册类型 // RegType::chkRegType($this->_userId, $userInfo['SHOULD_REG_TYPE'], $period['nowYear'], $period['nowMonth']); $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('add', $e->getMessage()); return false; } $afterData = Balance::getLogData(\Yii::$app->user->id); $this->userOperateLogger->saveAfterContent=$afterData; unset($beforeData,$afterData); $this->userOperateLogger->clean()->save([ 'optType' => '会员提现申请', 'userId' => \Yii::$app->user->id, 'userName' => Info::getUserNameByUserId(\Yii::$app->user->id), 'remark' => $this->createRemark, ]); return $withdrawModel; } /** * 检测是否上传身份证 * @return int */ public function checkHasIdCardInfo() { if ($this->scenario !== 'addByUser') return 0; $userId = \Yii::$app->user->id; $user = User::findOneAsArray('ID=:ID', [':ID' => $userId], 'ID,USER_NAME,ID_CARD'); if( !$user ) { $this->addError('add', Yii::t('ctx', 'withdrawFormNoExistsUser')); return -1; } // if( !$user['ID_CARD'] ) { // $this->addError('add', '完善身份信息后才可以提现'); // return -1; // } // // $response = LingYunGongApi::hasIdCardInfo($user['ID_CARD']); // if( !$response ) { // $this->addError('add', '接口网络错误'); // return -1; // } // // if( !isset($response['has']) ) { // $this->addError('add', '接口格式错误'); // return -1; // } // // // if( $response['has'] === true ) { // return 0; // }else { // $this->addError('add', $response['err_msg']['msg']); // return -2; // } return 0; } /** * 生成流水号 * @return string */ private function _generateSn() { return 'TX' . Date::today('Ymd') . $this->_random(10, 1); } /** * 生成随机数 * * @param $length * @param int $numeric * @return string */ private function _random($length, $numeric = 0) { $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35); $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed)); $hash = ''; $max = strlen($seed) - 1; for ($i = 0; $i < $length; $i++) { $hash .= $seed[mt_rand(0, $max)]; } return $hash; } /** * 生成随机数 * @param $length * @param int $numeric * @return string */ public function wdcode($length, $numeric = 0) { $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35); $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed)); $hash = ''; $max = strlen($seed) - 1; for ($i = 0; $i < $length; $i++) { $hash .= $seed[mt_rand(0, $max)]; } return $hash; } /** * 修改预计打款日期 * @return null|static * @throws \yii\db\Exception */ public function editByAdmin() { if (!$this->validate()) { return null; } $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { $oneWithdraw = Withdraw::findOne(['ID' => $this->id]); $oneWithdraw->UPDATE_ADMIN = \Yii::$app->user->id; $oneWithdraw->REMARK = $this->createRemark; $planPaidAt = Date::utcToTime($this->planPaidAt); if ($oneWithdraw->PLAN_PAID_AT != $planPaidAt) { $oneWithdraw->PLAN_PAID_AT = $planPaidAt; } if (!$oneWithdraw->save()) { throw new Exception(Form::formatErrorsForApi($oneWithdraw->getErrors())); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('status', $e->getMessage()); return null; } return $oneWithdraw; } /** * 前台提现退回 * @return null|static * @throws \yii\db\Exception */ public function backByUser() { if (!$this->validate()) { return null; } $oneWithdraw = Withdraw::findOne(['ID' => $this->id]); $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { if (Cache::getSystemConfig()['isCanWithdrawBack']['VALUE'] != 1) { throw new Exception(Yii::t('app', 'isCanWithdrawBack')); } if (!Withdraw::find()->where('USER_ID=:USER_ID AND ID=:ID AND AUDIT_STATUS=:AUDIT_STATUS_1', ['USER_ID' => \Yii::$app->user->id, ':ID' => $this->id, ':AUDIT_STATUS_1' => Withdraw::STATUS_APPLIED])->exists()) { throw new Exception(Yii::t('app', 'withdrawRecordDoesNotExist')); } $oneWithdraw->BACK_REMARK = $this->createRemark; $oneWithdraw->BACK_FAIL_AT = Date::nowTime(); $oneWithdraw->AUDIT_STATUS = Withdraw::STATUS_RETURN; Balance::changeUserBonus($oneWithdraw['USER_ID'], 'BONUS', abs($oneWithdraw['AMOUNT']), ['DEAL_TYPE_ID'=>DealType::WITHDRAW_RETURN,'REMARK' => $oneWithdraw->WITHDRAW_PERIOD_NUM.'期前台提现退回']); if (!$oneWithdraw->save()) { throw new Exception(Form::formatErrorsForApi($oneWithdraw->getErrors())); } //发票设置为审核拒绝 // if ($invoiceModel = InvoiceAudit::findOne(['ID' => $oneWithdraw->INVOICE_ID])) { // $invoiceModel->AUDIT_STATUS = \Yii::$app->params['auditStatus']['reject']['value']; // $invoiceModel->AUDIT_REMARK = '提现退回'; // $invoiceModel->AUDITED_AT = Date::nowTime(); // if (!$invoiceModel->save()) { // throw new Exception(Form::formatErrorsForApi($invoiceModel->getErrors())); // } // } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('auditStatus', $e->getMessage()); return null; } return $oneWithdraw; } /** * 设置提现订单的状态 * @return null|static * @throws \yii\db\Exception */ public function changeStatus() { if (!$this->validate()) { return null; } $logs = []; $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { foreach ($this->selectedIds as $select) { $oneWithdraw = Withdraw::findOne(['ID' => $select]); //判断状态 if (($msg = Withdraw::chkAuditStatus($oneWithdraw->SN, $oneWithdraw->AUDIT_STATUS, $this->auditStatus)) != '') { throw new Exception($msg); } //待审核->已审核 if ($this->auditStatus == Withdraw::STATUS_AUDITED) { //同时审核发票 if ($invoiceModel = InvoiceAudit::findOne(['ID' => $oneWithdraw['INVOICE_ID']])) { if (InvoiceAudit::find()->where('INVOICE_NUM=:INVOICE_NUM AND WITHDRAW_ID!=:WITHDRAW_ID AND AUDIT_STATUS=:AUDIT_STATUS', [':INVOICE_NUM' => $invoiceModel->INVOICE_NUM, ':WITHDRAW_ID' => $invoiceModel->WITHDRAW_ID, ':AUDIT_STATUS' => \Yii::$app->params['auditStatus']['true']['value']])->exists()) { throw new Exception('提现流水号' . $oneWithdraw->SN . '发票的发票号码【' . $invoiceModel->INVOICE_NUM . '】已被使用'); } $invoiceModel->AUDIT_ADMIN = \Yii::$app->user->id; $invoiceModel->CREATE_REMARK = $this->createRemark ?? ''; $invoiceModel->AUDITED_AT = Date::nowTime(); if (!$invoiceModel->save()) { throw new Exception(Form::formatErrorsForApi($invoiceModel->getErrors())); } } $oneWithdraw->REMARK = $this->createRemark ?? ''; } //已审核->待付款 elseif ($this->auditStatus == Withdraw::STATUS_WAIT_PAID) { $oneWithdraw->PAID_FAIL_REMARK = ''; $oneWithdraw->PAID_FAIL_AT = 0; $oneWithdraw->REMARK = $this->createRemark ?? ''; $oneWithdraw->PLAN_PAID_AT = Date::utcToTime($this->planPaidAt); } //待付款->已付款 elseif ($this->auditStatus == Withdraw::STATUS_PAID) { $oneWithdraw->PAID_AT = Date::utcToTime($this->paidAt); //记录付款信息 $baseInfo = Info::baseInfo($oneWithdraw->USER_ID); if ($baseInfo['REG_TYPE'] == '758BF69C25C3422AA7743936BC77EE64') { $companyBank = CompanyBank::findOneAsArray('USER_ID=:USER_ID', [':USER_ID' => $baseInfo['ID']]); $oneWithdraw->REAL_NAME = $companyBank['OPEN_NAME']; $oneWithdraw->OPEN_BANK = $companyBank['OPEN_BANK']; $oneWithdraw->BANK_PROVINCE = $companyBank['BANK_PROVINCE']; $oneWithdraw->BANK_CITY = $companyBank['BANK_CITY']; $oneWithdraw->BANK_COUNTY = $companyBank['BANK_COUNTY']; $oneWithdraw->BANK_ADDRESS = $companyBank['BANK_ADDRESS']; $oneWithdraw->BANK_NO = $companyBank['BANK_NO']; } else { $oneWithdraw->REAL_NAME = $baseInfo['REAL_NAME']; $oneWithdraw->OPEN_BANK = $baseInfo['OPEN_BANK']; $oneWithdraw->BANK_PROVINCE = $baseInfo['BANK_PROVINCE']; $oneWithdraw->BANK_CITY = $baseInfo['BANK_CITY']; $oneWithdraw->BANK_COUNTY = $baseInfo['BANK_COUNTY']; $oneWithdraw->BANK_ADDRESS = $baseInfo['BANK_ADDRESS']; $oneWithdraw->BANK_NO = $baseInfo['BANK_NO']; } $oneWithdraw->REMARK = $this->createRemark ?? ''; } //已付款->付款失败 elseif ($this->auditStatus == Withdraw::STATUS_PAID_FALSE) { $oneWithdraw->PAID_FAIL_AT = Date::nowTime(); $oneWithdraw->PAID_FAIL_REMARK = $this->createRemark ?? ''; } //提现退回 elseif ($this->auditStatus == Withdraw::STATUS_RETURN) { $oneWithdraw->BACK_REMARK = $this->createRemark ?? ''; $oneWithdraw->BACK_FAIL_AT = Date::nowTime(); Balance::changeUserBonus($oneWithdraw['USER_ID'], 'BONUS', abs($oneWithdraw['AMOUNT']), [ 'DEAL_TYPE_ID' => DealType::WITHDRAW_RETURN, 'REMARK' => 'Period' . $oneWithdraw->WITHDRAW_PERIOD_NUM . ' ' . ($oneWithdraw->IS_AUTO_WITHDRAW ? 'Auto' : 'Manual') . ' withdrawal return' // 自动、手动、提现退回 ]); //发票设置为审核拒绝 $invoiceModel = InvoiceAudit::findOne(['ID' => $oneWithdraw->INVOICE_ID]); if ($invoiceModel) { $invoiceModel->AUDIT_STATUS = \Yii::$app->params['auditStatus']['reject']['value']; $invoiceModel->AUDIT_ADMIN = \Yii::$app->user->id; $invoiceModel->AUDIT_REMARK = ' withdrawal return'; // 提现退回 $invoiceModel->AUDITED_AT = Date::nowTime(); if (!$invoiceModel->save()) { throw new Exception(Form::formatErrorsForApi($invoiceModel->getErrors())); } } } $oneWithdraw->UPDATE_ADMIN = \Yii::$app->user->id; $oneWithdraw->AUDIT_STATUS = $this->auditStatus; $oneWithdraw->AUDITED_AT = Date::nowTime(); if (!$oneWithdraw->save()) { throw new Exception(Form::formatErrorsForApi($oneWithdraw->getErrors())); } $logs[$select] = $oneWithdraw->SN; } $adminId = \Yii::$app->user->id; \Yii::$app->redis->del('withdrawAudit_'.$adminId); $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('auditStatus', $e->getMessage()); return null; } return ['logs' => $logs, 'status' => $this->auditStatus]; } /** * 标记为付款失败 * @return null|static * @throws \yii\db\Exception */ public function excelPaidFalse() { if (!$this->validate()) { return null; } $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { $oneWithdraw = Withdraw::findOne(['SN' => $this->sn]); $oneWithdraw->PAID_FAIL_AT = Date::nowTime(); $oneWithdraw->PAID_FAIL_REMARK = $this->paidFailRemark; $oneWithdraw->UPDATE_ADMIN = \Yii::$app->user->id; $oneWithdraw->AUDIT_STATUS = Withdraw::STATUS_PAID_FALSE; $oneWithdraw->AUDITED_AT = Date::nowTime(); if (!$oneWithdraw->save()) { throw new Exception(Form::formatErrorsForApi($oneWithdraw->getErrors())); } $transaction->commit(); } catch (Exception $e) { $transaction->rollBack(); $this->addError('auditStatus', $e->getMessage()); return null; } return $oneWithdraw; } /** * 循环自动提现 * @param $limit * @param int $start * @return bool * @throws \yii\db\Exception */ public static function autoLoopWithdraw($limit, $start = 0) { // 获取设置自动提现的最低金额 $systemConfig = Cache::getSystemConfig(); $autoWithdrawMinAmount = $systemConfig['autoWithdrawMinAmount']['VALUE']; $autoWithdrawMaxAmount = $systemConfig['autoWithdrawMaxAmount']['VALUE']; // 获取全部设置了自动提现的会员的奖金大于这个数额的会员 $allData = UserInfo::find()->select('UI.USER_ID,UI.USER_NAME,UI.IS_BIND_MAIN,UB.BONUS,UB.BONUS_FREEZE')->from(UserInfo::tableName() . ' AS UI')->join('LEFT JOIN', UserBonus::tableName() . ' AS UB', 'UI.USER_ID=UB.USER_ID')->where('UI.IS_AUTO_WITHDRAW=1 AND (UI.IS_BIND_MAIN=1 OR (UB.BONUS - UB.BONUS_FREEZE >= :WITHDRAW_AMOUNT AND UI.IS_BIND=0))', [':WITHDRAW_AMOUNT' => $autoWithdrawMinAmount])->offset($start)->limit($limit)->asArray()->all(); if ($allData) { foreach ($allData as $data) { //本月提现过的忽略 if (Withdraw::hasThisMonthWithdraw($data['USER_ID'])) continue; //汇总主点位 $collectBind = 0; if ($data['IS_BIND_MAIN'] == 1) { $transferBonusForm = new TransferBonusForm(); $collectBind = $transferBonusForm->collectBind($data['USER_ID']); } $totalAmount = $data['BONUS'] + $collectBind - $data['BONUS_FREEZE']; if ($autoWithdrawMinAmount != 0 && $totalAmount < $autoWithdrawMinAmount) continue; $formModel = new WithdrawForm(); $formModel->scenario = 'addByAuto'; $formModel->userName = $data['USER_NAME']; //自动提现金额取整数 $formModel->applyAmount = floor(($autoWithdrawMaxAmount > 0 && $totalAmount > $autoWithdrawMaxAmount) ? $autoWithdrawMaxAmount : $totalAmount); if (!$formModel->add()) { continue; } unset($formModel); } unset($allData); $start = $start + $limit; return self::autoLoopWithdraw($limit, $start); } return true; } /** * 批量自动提现 * * * @throws \yii\db\Exception */ public function batchWithdraw($limit, $start, $params){ $config = Cache::getSystemConfig(); $minAmount = $config['manualWithdrawMinAmount']['VALUE']; $condition = ''; $adminRoleId = Admin::getRoleIdById($params['handleUserId']); $isSuper = AdminRole::isSuperAdmin($adminRoleId); if (!$isSuper) { $adminCountry = AdminCountry::getCountry($params['handleUserId']); $quotedAdminCountry = array_map(function($item) { return "'" . addslashes($item) . "'"; }, $adminCountry); $condition = " AND U.COUNTRY_ID IN (" . implode(',', $quotedAdminCountry) . ")"; } // 查找有奖金的用户 $allData = UserBonus::find() ->select('USER_ID, USER_NAME, ID_CARD, BONUS') ->from(UserBonus::tableName().' AS UB') ->join('INNER JOIN', User::tableName() . ' AS U','UB.USER_ID = U.ID ' . $condition) ->where("BONUS>$minAmount") ->offset(0) ->limit($limit) ->orderBy('U.ID') ->asArray() ->all(); LoggerTool::debug($allData); if($allData){ foreach ($allData as $data){ $db = \Yii::$app->db; $transaction = $db->beginTransaction(); try { $nowTime = $this->createdAt ?: Date::nowTime(); $period = Withdraw::getPeriod($nowTime); //扣除会员奖金 Balance::changeUserBonus($data['USER_ID'], 'BONUS', -abs($data['BONUS']), ['DEAL_TYPE_ID'=>DealType::WITHDRAW,'REMARK' => 'batch withdrawal', 'TIME' => $nowTime]); //手续费 $fees = $data['BONUS'] * $config['withdrawFee']['VALUE']/100; $fees = Tool::formatPrice($fees); $realAmount = $data['BONUS'] - $fees; //判断付款类型 $payType = Withdraw::PAY_TYPE_NO_INVOICE; $withdrawModel = new Withdraw(); $withdrawModel->SN = $this->_generateSn(); $withdrawModel->USER_ID = $data['USER_ID']; $withdrawModel->ID_CARD = $data['ID_CARD']; $withdrawModel->WITHDRAW_PERIOD_NUM = $period['nowPeriodNum']; $withdrawModel->WITHDRAW_YEAR = $period['nowYear']; $withdrawModel->WITHDRAW_MONTH = $period['nowMonth']; $withdrawModel->PAY_TYPE = $payType; $withdrawModel->IS_AUTO_WITHDRAW = $this->scenario == 'batchWithdraw' ? 1 : 0; $withdrawModel->AMOUNT = $data['BONUS']; $withdrawModel->FEES = $fees; $withdrawModel->REAL_AMOUNT = $realAmount; $withdrawModel->P_MONTH = Date::ociToDate($period['yearMonth'], Date::OCI_TIME_FORMAT_SHORT_MONTH); $withdrawModel->AUDIT_STATUS = Withdraw::STATUS_APPLIED; $withdrawModel->CREATED_AT = $nowTime; //预计付款时间 $withdrawModel->PLAN_PAID_AT = $period['endTime'] + $config['withdrawFreezeDays']['VALUE'] * 3600 * 24; if (!$withdrawModel->save()) { throw new Exception(Form::formatErrorsForApi($withdrawModel->getErrors())); } $transaction->commit(); unset($withdrawModel); } catch (Exception $e) { $transaction->rollBack(); $this->addError('add', $e->getMessage()); return false; } } unset($allData); $start = $start + $limit; return self::batchWithdraw($limit, $start, $params); } return true; } }