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' => '提现申请不存在'], [['userName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME', 'message' => '会员不存在'], [['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, '输入的会员姓名或身份证号与系统不一致'); } if ($userInfo['REG_TYPE'] != $this->regType) { $this->addError($attributes, '选择的会员注册类型与系统不一致'); } } $this->_userId = $userInfo['USER_ID']; } else { $this->addError($attributes, $this->userName . 'Member does not exist'); // 会员不存在 } } /** * 校验申请金额是否小于当前余额并符合配置中的设置 * @param $attribute * @return bool */ public function isApplyAmount($attribute) { $config = Cache::getSystemConfig(); if ($this->applyAmount <= 0) { $this->addError('scenario', '提现金额必须大于0'); } if ((int)($this->applyAmount)!=$this->applyAmount) { $this->addError('scenario', '提现金额必须是整数'); } $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, '场景不存在'); return false; } if ($minAmount != 0 && $this->applyAmount < $minAmount) { $this->addError($attribute, '提现金额不能少于' . $minAmount . '元'); } if ($maxAmount != 0 && $this->applyAmount > $maxAmount) { $this->addError($attribute, '提现金额不能高于' . $maxAmount . '元'); } // 提现条件判断 $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', '提现金额必须小于的可用余额'); } } /** * 校验支付密码 * @param $attribute * @param $params */ public function validatePassword($attribute, $params) { if (!User::validatePayPassword($this->_userId, $this->payPassword)) { $this->addError($attribute, '支付密码不正确'); } } 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, '申请提现校验失败'); } } public function validateAuditCode($attribute) { $adminId = \Yii::$app->user->id; $redisCode = \Yii::$app->redis->getset('withdrawAudit_'.$adminId,''); if ($this->withdrawAudit!=$redisCode) { $this->addError($attribute, '提现审核校验失败'); } } /** * 批量数据 * @param $attributes */ public function isSelected($attributes) { if (!$this->selectedIds) { $this->addError($attributes, 'A piece of data must be selected'); // 必须选择一条数据 } 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, '不能选择过去的日期'); } } /** * 判断信息是否一致 * @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, '不存在提现流水号为' . $sn . '的已付款记录'); } if ($oneWithdraw) { $info = Info::baseInfo($oneWithdraw['USER_ID']); if ($this->userName != $info['USER_NAME']) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的用户名' . $this->userName . '与系统中的信息【' . $info['USER_NAME'] . '】不一致'); } if ($this->realName != $info['REAL_NAME']) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的会员姓名' . $this->realName . '与系统中的信息【' . $info['REAL_NAME'] . '】不一致'); } if ($this->withdrawPeriodNum != $oneWithdraw['WITHDRAW_PERIOD_NUM']) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的提现期数' . $this->withdrawPeriodNum . '与系统中的信息【' . $oneWithdraw['WITHDRAW_PERIOD_NUM'] . '】不一致'); } if (Date::convert(Date::utcToTime($this->paidAt)) != Date::convert($oneWithdraw['PAID_AT'])) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的付款日期' . Date::convert(Date::utcToTime($this->paidAt)) . '与系统中的信息【' . Date::convert($oneWithdraw['PAID_AT']) . '】不一致'); } if ($this->amount != $oneWithdraw['AMOUNT']) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的提现金额' . $this->amount . '与系统中的信息【' . $oneWithdraw['AMOUNT'] . '】不一致'); } if ($this->bankRealName != $oneWithdraw['REAL_NAME']) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的实时开户名' . $this->bankRealName . '与系统中的信息【' . $oneWithdraw['REAL_NAME'] . '】不一致'); } if ($this->bankNo != $oneWithdraw['BANK_NO']) { $this->addError($attribute, 'Excel中提现流水号' . $sn . '的实时银行账户' . $this->bankNo . '与系统中的信息【' . $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', '不存在该用户'); 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('提现退回已关闭'); } 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('符合退回的提现记录不存在'); } $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){ $config = Cache::getSystemConfig(); $minAmount = $config['manualWithdrawMinAmount']['VALUE']; // 查找有奖金的用户 $allData = UserBonus::find()->select('USER_ID, USER_NAME, ID_CARD, BONUS')->from(UserBonus::tableName().' AS UB')->join('LEFT JOIN', User::tableName().' AS U','UB.USER_ID = U.ID')->where("BONUS>$minAmount")->offset(0)->limit($limit)->orderBy('U.ID')->asArray()->all(); 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())); } // print_r($data['BONUS'].',,'.$i.PHP_EOL); $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); } return true; } }