// +---------------------------------------------------------------------- namespace App\Services\Common; use App\Models\CoinLogModel; use App\Models\MemberModel; use App\Models\UserModel; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use Earnp\GoogleAuthenticator\GoogleAuthenticator; /** * 币种明细(提币、存币)-服务类 * Class CoinLogService * @package App\Services\Common */ class CoinLogService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @since 2020/11/10 * CoinLogService constructor. */ public function __construct() { $this->model = new CoinLogModel(); $this->memberModel = new MemberModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 获取列表 * @param $params 参数 * @param int $pageSize 分页大小:默认 15 * @return array */ public function getDataList($params, $pageSize = 15) { $where = ['a.mark' => 1]; $type = isset($params['type'])? $params['type'] : 1; $status = isset($params['status'])? $params['status'] : 0; $changeType = isset($params['change_type'])? $params['change_type'] : 1; $contactType = isset($params['contact_type'])? $params['contact_type'] : 1; $coinType = isset($params['coin_type'])? $params['coin_type'] : 1; $userId = isset($params['user_id'])? $params['user_id'] : 0; if($type>0){ $where['a.type'] = $type; } if($status>0){ $where['a.status'] = $status; } if($contactType>0){ $where['a.contact_type'] = $contactType; } if($changeType>0){ $where['a.change_type'] = $changeType; } if($coinType>0){ $where['a.coin_type'] = $coinType; } if($userId>0){ $where['a.user_id'] = $userId; } $list = $this->model->from('coin_logs as a') ->leftJoin('member as m', 'm.id', '=', 'a.user_id') ->where($where) ->where(function ($query) use($params){ $keyword = isset($params['keyword'])? $params['keyword'] : ''; if($keyword){ $query->where('a.order_no','like',"{$keyword}")->orWhere('m.username','like',"%{$keyword}%"); } // 日期 $date = isset($params['date']) ? $params['date'] : []; $start = isset($date[0])? $date[0] : ''; $end = isset($date[1])? $date[1] : ''; $end = $start>=$end? '' : $end; if ($start) { $query->where('a.create_time','>=', strtotime($start)); } if($end){ $query->where('a.create_time','<', strtotime($end)); } }) ->select(['a.*', 'm.username']) ->orderBy('a.create_time','desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list? $list->toArray() :[]; if($list){ foreach($list['data'] as &$item){ $item['time_text'] = $item['create_time']? datetime(strtotime($item['create_time']), 'm-d H:i'):''; } } return [ 'pageSize'=> $pageSize, 'total'=>isset($list['total'])? $list['total'] : 0, 'list'=> isset($list['data'])? $list['data'] : [] ]; } /** * 验证是否存在 * @param \App\Services\字段名 $field * @param \App\Services\字段值 $value * @param string $pk * @return mixed */ public function checkExists($field, $value, $pk = 'id', $status=0) { $cacheKey = "caches:coinLogs:exists:{$field}_{$value}"; if($result = RedisService::get($cacheKey)){ return $result; } $result = parent::checkExists($field, $value, $pk, $status); if($result){ RedisService::set($cacheKey, $result, rand(3,5)); } return $result; } /** * 根据交易订单号获取提币记录 * @param $txid * @return array|false|mixed */ public function getCacheInfoByTxid($txid) { $cacheKey = "caches:wallets:coinLog:{$txid}"; if($data = RedisService::get($cacheKey)){ return $data; } $data = $this->model->where(['txid' => $txid]) ->select(['id', 'user_id','order_no', 'num','free', 'coin_type', 'balance', 'change_type', 'status']) ->first(); if($data){ RedisService::set($cacheKey, $data, rand(3,5)); } return $data; } /** * 提币/转账 * @param $userId 用户 * @param $params 参数:to_address-提币地址,num-数量,contact_type-合约类型 * @return bool */ public function withdraw($userId, $params) { $num = isset($params['num'])? floatval($params['num']) : 0; $toAddress = isset($params['to_address'])? $params['to_address'] : ''; $contactType = isset($params['contact_type'])? intval($params['contact_type']) : 1; if(empty($userId) || empty($toAddress)){ $this->error ='1013'; return false; } $userInfo = MemberService::make()->getInfo($userId); if(empty($userInfo) || $userInfo['status'] != 1){ $this->error = '2009'; return false; } if(!in_array($contactType, [1,2])){ $this->error ='2209'; return false; } // 交易密码 $tradePassword = isset($params['trade_password'])? $params['trade_password'] : ''; $password = isset($userInfo['trade_password'])? $userInfo['trade_password'] : ''; if (empty($password)) { $this->error = '2015'; return false; } if (!$tradePassword || get_password($tradePassword . md5($tradePassword . 'otc')) != $password) { $this->error = '2016'; return false; } // 谷歌验证码 $checkGoogle = isset($params['check_google'])? $params['check_google'] : 1; if($checkGoogle){ $googleCode = isset($params['google_code'])? $params['google_code'] : ''; $info = UserModel::where(['user_id'=> $userId])->select(['google_secret','google_verify_time'])->first(); $googleSecret = isset($info['google_secret'])? $info['google_secret'] : ''; $verifyTime = isset($info['google_verify_time'])? intval($info['google_verify_time']) : 0; if(empty($googleSecret)){ $this->error = '2017'; return false; } // 刚验证更新的谷歌验证码24小时内不得提币 if($verifyTime && $verifyTime> time()){ $this->error = '2019'; return false; } if (!GoogleAuthenticator::CheckCode($googleSecret, $googleCode)) { $this->error = '2018'; return false; } } $config = ConfigService::make()->getConfigOptionByGroup(6); $coinOutFree = isset($config['coin_out_free'])? floatval($config['coin_out_free']) : 0; $fee = floatval($num * $coinOutFree/100); // 余额是否足够 if($userInfo['usdt_num'] < floatval($num + $fee)){ $this->error = '2212'; return false; } $data = [ 'type'=> isset($params['type'])? $params['type'] : 1, 'user_id'=> $userId, 'from_address'=> '', 'to_address'=> $toAddress, 'change_type'=> 2, 'coin_type'=> isset($params['coin_type'])? $params['coin_type'] : 1, 'contact_type'=> $contactType, 'order_no'=> get_order_num('Tw'), 'txid'=> uniqid(), 'num'=> $num, 'free'=> $fee, 'balance'=> $userInfo['usdt_num'], 'create_time'=> time(), 'update_time'=> time(), 'status'=> 3, 'mark'=> 1, ]; $this->model->startTrans(); if(!$this->model->edit($data)){ $this->model->rollBack(); $this->error = '2013'; return false; } // 扣除余额 if(!$this->memberModel->where(['id'=> $userId,'mark'=>1])->decrement('usdt_num', ($num + $fee))){ $this->model->rollBack(); $this->error = '2014'; return false; } $this->model->commit(); $this->error = '2216'; return true; } }