| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 | <?php/** * Settle.php UTF-8 * 提现 * * @date    : 2018/5/18 16:27 * * @license 这不是一个自由软件,未经授权不许任何使用和传播。 * @author  : wuyonghong <wyh@huosdk.com> * @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];    }}
 |