* @version : HUOSDK 8.0 */ namespace huo\controller\finance; use huo\controller\agent\AgentCache; use huo\controller\agent\AgentWallet; use huo\controller\common\Base; use huo\controller\member\MemCache; use huo\controller\queue\SettleQueue; use huo\controller\wap\Option; use huo\logic\finance\SettleLogic; use huo\model\finance\SettleHistoryModel; use huo\model\finance\SettleModel; use huo\model\member\MemoauthModel; use huolib\constant\CommonConst; use huolib\constant\MemConst; use huolib\constant\OauthConst; use huolib\constant\OptionConst; use huolib\constant\SettleConst; use huolib\status\CommonStatus; use huolib\status\OrderStatus; use huolib\status\SettleStatus; use huolib\tool\StrUtils; use huolib\tool\Time; use huolib\withdraw\driver\Alipay; use huolib\withdraw\driver\Wxpay; use huomp\controller\finance\SettleVerifiedOut; use huomp\logic\finance\SettleLogLogic; use huomp\logic\game\OaMchLogic; use huomp\model\member\UnusualMemModel; use huomp\model\weixin\MpConfModel; use huoMpMsg\controller\OaOut; use think\Log; class Settle extends Base { /** * 获取提现列表 * * @param $agent_id * @param $param * @param string $page * @param string $order * * @return array */ public function getSettleList($agent_id, $param, $page = '1,10', $order = '-create_time') { $_rdata = (new SettleLogic())->getSettleList($agent_id, $param, $page, $order); $_code = CommonStatus::NO_ERROR; return $this->retSucMsg($_code, $_rdata); } /** * 提现 * * @param int $agent_id * @param float $amount * @param string $type * * @param array $oauth_data //第三方参数 * * @return array */ public function doSettle($agent_id, $amount, $type, $oauth_data = []) { if (!is_numeric($amount) || StrUtils::compareNumber($amount, 0) <= 0) { $_code = SettleStatus::AMOUNT_IS_ERROR; return $this->huoError($_code, SettleStatus::getMsg($_code)); } /* 更新钱包 */ $_rs = (new AgentWallet())->updateWallet( $agent_id, $amount, SettleConst::SETTLE_WALLET_DEDUCT, SettleConst::SETTLE_WALLET_LOCK ); if (SettleStatus::NO_ERROR != $_rs) { return $this->huoError($_rs, SettleStatus::getMsg($_rs)); } $_withdraw_cnt = (new SettleModel())->getCnt($agent_id); /* 添加提现记录 */ $_rs_data = $this->buildSettleOrder($agent_id, $amount, $type, $oauth_data); if (SettleStatus::NO_ERROR != $_rs_data['code']) { return $this->huoReturn($_rs_data); } /* 判断用户状态 冻结用户不可自动打款*/ $_ag_data = AgentCache::ins()->getInfoByAgentId($agent_id); if (!empty($_ag_data['mem_id'])) { $_mem_data = MemCache::ins()->getInfoById($_ag_data['mem_id']); if (MemConst::STATUS_FORBID == $_mem_data['status']) { $_um_model = new UnusualMemModel(); $_data = [ 'mem_id' => $_ag_data['mem_id'], 'agent_id' => $agent_id, 'type' => MemConst::UNUSUAL_MEN_TYPE_3 ]; $_um_data = $_um_model->getDataByAgentId($agent_id); if (empty($_um_data)) { $_um_model->addData($_data); } else { $_um_model->updateDataByAgentId($_data, $_data['agent_id']); } if (!empty($_rs_data['data']['s_id'])) { (new SettleModel())->updateData(['tag' => SettleConst::SETTLE_TAG_2], $_rs_data['data']['s_id']); } /* 已冻结用户 需要运营审核 */ return $this->huoReturn($_rs_data); } } /* 判断重名数 大于等于限制值 不可自动提现打款 */ if (!empty($oauth_data['real_name'])) { $_rs = (new SettleVerifiedOut())->isLimit($oauth_data['real_name']); $_um_model = new UnusualMemModel(); if (true == $_rs) { //达到限制记录玩家 $_data = [ 'mem_id' => $_ag_data['mem_id'], 'agent_id' => $agent_id, 'type' => MemConst::UNUSUAL_MEN_TYPE_4 ]; $_um_data = $_um_model->getDataByAgentId($agent_id); if (empty($_um_data)) { $_um_model->addData($_data); } else { $_um_model->updateDataByAgentId($_data, $_data['agent_id']); } /* 达到限制数量的第一个用户标记为 重名用户 需要运营审核 */ if (!empty($_rs_data['data']['s_id'])) { (new SettleModel())->updateData(['tag' => SettleConst::SETTLE_TAG_2], $_rs_data['data']['s_id']); } return $this->huoReturn($_rs_data); } else { $_um_model->deleteByAgentId($agent_id); } } $_max_amount = $this->getAutoMaxAmount($_withdraw_cnt); $_diff = StrUtils::compareNumber($amount, $_max_amount); $_can_settle = $_diff > 0 ? false : true; if (false == $_can_settle) { /* 已提现并且第一次提现大于最大自动提现金额 需要运营审核 */ return $this->huoReturn($_rs_data); } $_s_id = $_rs_data['data']['s_id']; /* 运营审核通过 */ $_rs = $this->setStatus($agent_id, $_s_id, SettleConst::SETTLE_STATUS_FIN_CHECK, '自动提现'); if (CommonStatus::NO_ERROR != $_rs['code']) { return $this->huoReturn($_rs); } return $this->setStatus($agent_id, $_s_id, SettleConst::SETTLE_STATUS_OK, '自动提现'); } /** * 获取最大提现金额 * * @param int $withdraw_cnt 提现次数 * * @return float */ public function getAutoMaxAmount($withdraw_cnt = 0) { $_setting_name = OptionConst::SETTING_SETTLE_LIMIT; $_m = new Option(); $_item = $_m->getOptionData($_setting_name, 1, true); if (!empty($_item['option_value'])) { $_option_value = json_decode($_item['option_value'], true); unset($_item); } if (empty($withdraw_cnt)) { return empty($_option_value['first_limit']) ? 0.5 : $_option_value['first_limit']; } return empty($_option_value['again_limit']) ? 0 : $_option_value['again_limit'];; } /** * 创建提现订单 * * @param $agent_id * @param $amount * @param $type * * @param array $oauth_data //第三方参数 * * @return array */ public function buildSettleOrder($agent_id, $amount, $type, $oauth_data = []) { $_data['agent_id'] = $agent_id; $_data['amount'] = $amount; $_data['type'] = $type; $_data['bankname'] = ''; $_data['branchname'] = ''; $_data['cardholder'] = empty($oauth_data['real_name']) ? '' : $oauth_data['real_name']; $_data['banknum'] = empty($oauth_data['openid']) ? '' : $oauth_data['openid']; $_data['status'] = SettleConst::SETTLE_STATUS_OP_CHECK; $_rs = (new SettleModel())->createOrder($_data); if (false === $_rs) { $_code = OrderStatus::ORDER_CREATE_FAIL; return $this->huoError($_code, OrderStatus::getMsg($_code)); } $_code = SettleStatus::NO_ERROR; $_rdata['s_id'] = $_rs; return $this->huoSuccess($_code, SettleStatus::getMsg($_code), $_rdata); } /** * 获取今日有效提现数量, 状态为 1待审核、2待财务审核、3已结算的为有效提现 状态为 4运营审核不通过、5财务审核不通过 为无效提现 * * @param int $agent_id * * @param float $amount * * @return array */ public function isAllowSettle($agent_id, $amount = 0.00) { /* 判断是否限制提下用户 */ $_umdata = (new UnusualMemModel())->getDataByAgentId($agent_id); if (!empty($_umdata) && MemConst::UNUSUAL_MEN_TYPE_5 == $_umdata['type']) { $_code = SettleStatus::SETTLT_REACHED_NOT_ALLOW; return $this->huoError($_code, SettleStatus::getMsg($_code)); } if (StrUtils::compareNumber($amount, 0.3) < 0) { $_code = SettleStatus::AMOUNT_IS_ERROR; return $this->huoError($_code, '提现金额必须不小于0.3元'); } list($_start_time, $_end_time) = Time::today(); $_map = [ 'agent_id' => $agent_id, 'type' => SettleConst::SETTLE_TYPE_MP, 'create_time' => ['gt', $_start_time], 'status' => ['in', [SettleConst::SETTLE_STATUS_OP_CHECK, SettleConst::SETTLE_STATUS_FIN_CHECK, SettleConst::SETTLE_STATUS_OK]], ]; $_count = (new SettleModel())->where($_map)->count('id'); $_limit = $this->getSettleLimit(); if (empty($_count) || $_count < $_limit) { $_code = CommonStatus::NO_ERROR; return $this->huoError($_code, SettleStatus::getMsg($_code), ['count' => $_count, 'limit' => $_limit]); } $_code = SettleStatus::SETTLT_REACHED_LIMIT; return $this->huoError($_code, SettleStatus::getMsg($_code), ['count' => $_count, 'limit' => $_limit]); } /** * 获取限制提现次数 */ public function getSettleLimit() { $_limit = 1; return $_limit; } /** * 设置状态 * * * @param int $admin_id * @param int $s_id * @param int $status * @param string $content * * @return array */ public function setStatus($admin_id, $s_id, $status, $content = '') { $_settle_model = new SettleModel(); $_data = $_settle_model->getDetail($s_id); if (empty($_data) || !is_numeric($admin_id)) { $_code = SettleStatus::INVALID_PARAMS; return $this->huoError($_code, SettleStatus::getMsg($_code)); } $_old_status = $_data['status']; $_check_time = $_data['check_time']; switch ($status) { case SettleConst::SETTLE_STATUS_FIN_CHECK: $_content = '运营审核通过,'.$content; $_data['status'] = SettleConst::SETTLE_STATUS_FIN_CHECK; $_data['check_time'] = time(); break; case SettleConst::SETTLE_STATUS_OK: $_content = '提现成功,'.$content; $_data['status'] = SettleConst::SETTLE_STATUS_OK; $_data['settle_time'] = time(); // $_data['pay_status'] = SettleConst::SETTLE_PAY_SUCCESS; break; case SettleConst::SETTLE_STATUS_OP_NO: $_content = '运营审核不通过,'.$content; $_data['status'] = SettleConst::SETTLE_STATUS_OP_NO; $_data['check_time'] = time(); $_data['failreason'] = $_content; break; case SettleConst::SETTLE_STATUS_FIN_NO: $_content = '财务审核不通过,'.$content; $_data['status'] = SettleConst::SETTLE_STATUS_FIN_NO; $_data['settle_time'] = time(); $_data['failreason'] = $_content; break; default: $_code = SettleStatus::INVALID_PARAMS; return $this->huoError($_code, SettleStatus::getMsg($_code)); } $_rs = $_settle_model->updateData($_data, $s_id); if (false === $_rs) { $_code = SettleStatus::INNER_ERROR; return $this->huoError($_code, SettleStatus::getMsg($_code)); } $_agent_wallet = new AgentWallet(); switch ($status) { case SettleConst::SETTLE_STATUS_OK: /* 减少冻结金额 */ $_rs = $_agent_wallet->updateWallet( $_data['agent_id'], $_data['amount'], SettleConst::SETTLE_WALLET_NO, SettleConst::SETTLE_WALLET_UNLOCK ); if (SettleStatus::NO_ERROR == $_rs) { if (SettleConst::SETTLE_TYPE_MP == $_data['type']) {//小程序提现在线打款 2018-08-16 /*在线打款*/ /* 提现入队列 */ $_data['status'] = SettleConst::SETTLE_STATUS_QUEUE; $_queue_data = $_data; $_queue_data['admin_id'] = $admin_id; $_rs = (new SettleQueue($_queue_data))->pushQueue(); if (SettleStatus::NO_ERROR != $_rs['code']) { //打款失败 $_agent_wallet->updateWallet( $_data['agent_id'], $_data['amount'], SettleConst::SETTLE_WALLET_NO, SettleConst::SETTLE_WALLET_LOCK ); //增加冻结金额 /*更换回运营审核通过*/ $_data['status'] = $_old_status; $_data['check_time'] = $_check_time; $_data['pay_status'] = SettleConst::SETTLE_PAY_PROCESSING; $_data['failreason'] = $_rs['msg']; $_settle_model->updateData($_data, $s_id); return $this->huoError(SettleStatus::SETTLT_PAY_ERROR, $_rs['msg']); } // $_content = '进入提现队列,'.$content; } } else { $_data['status'] = SettleConst::SETTLE_STATUS_FIN_CHECK; $_data['check_time'] = time(); $_data['failreason'] = ''; $_settle_model->updateData($_data, $s_id); (new OaOut())->sendAdminSettleMsg($_data['agent_id'], $_data['amount']); return $this->huoError($_rs, SettleStatus::getMsg($_rs)); } break; case SettleConst::SETTLE_STATUS_OP_NO: case SettleConst::SETTLE_STATUS_FIN_NO: /* 返回到账户中 */ $_rs = $_agent_wallet->updateWallet( $_data['agent_id'], $_data['amount'], SettleConst::SETTLE_WALLET_ADD, SettleConst::SETTLE_WALLET_UNLOCK ); if (SettleStatus::NO_ERROR == $_rs) { (new OaOut())->sendAdminMoneyChangeMsg($_data['agent_id'], $_data['amount']); $_data['is_return'] = 2; } else { $_data['is_return'] = 1; } break; default: break; } $_settle_model->updateData($_data, $s_id); $_sh_data['s_id'] = $s_id; $_sh_data['u_id'] = $admin_id; $_sh_data['content'] = $_content; (new SettleHistoryModel())->addLog($_sh_data); $_code = SettleStatus::NO_ERROR; return $this->huoError($_code, SettleStatus::getMsg($_code)); } /** * 放入队列处理 * * @param array $s_data 提现数据 * * @return array */ public function withdrawQueue($s_data) { $_data = $s_data; $_rs = $this->withdrawPayment($_data); if (SettleConst::SETTLE_SUCCESS != $_rs['code']) { /* 打款失败 */ /* 1.1 增加冻结金额 */ Log::write( '打款失败增加冻结金额'.json_encode($_data), Log::ERROR ); if (SettleConst::SETTLE_STATUS_QUEUE == $_data['status']) { (new AgentWallet())->updateWallet( $_data['agent_id'], $_data['amount'], SettleConst::SETTLE_WALLET_NO, SettleConst::SETTLE_WALLET_LOCK ); } $_data['status'] = SettleConst::SETTLE_STATUS_FIN_CHECK; // 退回财务审核 $_data['pay_status'] = SettleConst::SETTLE_PAY_FAILED; // 打款失败 $_data['failreason'] = json_encode($_rs); $_content = '提现失败,'.$_data['failreason']; $_rs['code'] = SettleStatus::SETTLT_PAY_ERROR; } else { /* 打款成功 */ $_content = '提现成功'; $_data['status'] = SettleConst::SETTLE_STATUS_OK; $_data['settle_time'] = time(); $_data['pay_status'] = SettleConst::SETTLE_PAY_SUCCESS; $_rs['code'] = SettleStatus::NO_ERROR; (new OaOut())->sendAdminSettleMsg($_data['agent_id'], $_data['amount']); } (new SettleModel())->updateData($_data, $_data['id']); (new SettleHistoryModel())->addData($s_data['id'], $s_data['admin_id'], $_content); $_rs['data'] = []; return $this->huoReturn($_rs); } /** * 提现打款 * * @param $s_data * * @return array|int */ public function withdrawPayment($s_data) { if (empty($s_data)) { return SettleStatus::INVALID_PARAMS; } switch ($s_data['type']) { case SettleConst::SETTLE_TYPE_BANK: //银行卡 return SettleStatus::TYPE_EMPTY; // TODO: chenbingling 2018/7/6 银行在线打款未接入 break; case SettleConst::SETTLE_TYPE_ALIPAY: //支付宝 $_pay_class = new Alipay(); $_pay_class->setPayeeAccount($s_data['banknum']); $_pay_class->setPayerShowName($this->getSettleRemark('show_name')); //$_pay_class->setRealAmount('0.1'); //TODO: chenbingling 2018/7/6 测试打款 使用 正式上线请勿使用 break; case SettleConst::SETTLE_TYPE_WXPAY: //微信 case SettleConst::SETTLE_TYPE_MP: //小程序提现 /* 获取微信商户配置 */ $_mem_auto = (new MemoauthModel())->getInfoByOpenId(OauthConst::OAUTH_WEIXIN, $s_data['banknum']); $_mp_id = (new MpConfModel())->getMpIdById($_mem_auto['conf_id']); $_config = (new OaMchLogic())->getDefaultMchConf($_mp_id); $_pay_class = new Wxpay($_config); $_pay_class->setOpenId($s_data['banknum']); //$_pay_class->setRealAmount('1'); //TODO: chenbingling 2018/7/6 测试打款 使用 正式上线请勿使用 break; default: return SettleStatus::TYPE_EMPTY; } /* 获取后台提现配置 */ $_vcfg = (new SettleVerifiedOut())->getVerifiedCfg(); if (CommonConst::STATUS_YES == $_vcfg['is_verified']) { //提现需实名 $_withdraw_cnt = (new SettleModel())->getCnt($s_data['agent_id']); if (CommonConst::STATUS_YES == $_vcfg['first_verified'] || $_withdraw_cnt > 1) { $_agent_data = AgentCache::ins()->getInfoByAgentId($s_data['agent_id']); $_mem_data = MemCache::ins()->getInfoById(get_val($_agent_data, 'mem_id', 0)); $_pay_class->setCheckName('FORCE_CHECK'); //微信校验用户姓名选项 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名 $s_data['cardholder'] = $_mem_data['real_name']; } } $_pay_class->setPayeeRealName($s_data['cardholder']); $_pay_class->setOrderId($s_data['id']); $_pay_class->setRealAmount($s_data['amount']); //TODO: chenbingling 2018/7/6 正式打款请用这个 $_pay_class->setRemark($this->getSettleRemark('remark', $s_data['amount'])); $_rs = $_pay_class->withDraw(); // $_rs=[]; /*打款记录*/ $_pay_data = []; $_pay_data['mem_id'] = get_val($s_data, 'mem_id', 0); $_pay_data['agent_id'] = get_val($s_data, 'agent_id', 0); $_pay_data['order_id'] = get_val($s_data, 'id', ''); $_pay_data['amount'] = get_val($s_data, 'amount', 0.00); $_pay_data['type'] = get_val($s_data, 'type', ''); $_pay_data['cardholder'] = get_val($s_data, 'cardholder', ''); $_pay_data['banknum'] = get_val($s_data, 'banknum', ''); $_pay_data['code'] = get_val($_rs, 'code', ''); $_pay_data['msg'] = get_val($_rs, 'msg', ''); $_pay_data['result'] = get_val($_rs, 'result', ''); $_pay_data['query_result'] = get_val($_rs, 'query_result', ''); (new SettleLogLogic())->addPayLog($_pay_data); return $_rs; } /** * 获取提现显示名称和备注 * * @param $name * @param int $money * * @return mixed */ protected function getSettleRemark($name = 'show_name', $money = 0) { $_setting_name = OptionConst::NAME_SETTLE_PAY_NOTE; $_option_value = [ 'show_name' => SettleConst::SETTLE_SHOW_NAME, 'remark' => SettleConst::SETTLE_REMARK ]; $_m = new Option(); $_item = $_m->getOptionData($_setting_name, 1, true, json_encode($_option_value)); if (!empty($_item['option_value'])) { $_item['option_value'] = json_decode($_item['option_value'], true); } $_data = [ 'show_name' => $_item['option_value']['show_name'], //提现显示付款方姓名 'remark' => sprintf($_item['option_value']['remark'], $money) //提现显示备注 ]; if (empty($_data[$name])) { return ''; } return $_data[$name]; } }