// +---------------------------------------------------------------------- namespace Admin\Model; use Common\Api\GameApi; use Org\WeixinSDK\Weixin; use Think\Model; /** * 文档基础模型 */ class SpendModel extends Model { /* 自动验证规则 */ protected $_validate = array(); /* 自动完成规则 */ protected $_auto = array( array('pay_time', 'getCreateTime', self::MODEL_INSERT, 'callback'), array('pay_status', 0, self::MODEL_INSERT), array('order_number', '', self::MODEL_INSERT), ); protected function _after_select(&$result, $options) { foreach ($result as $key => $value) { // $result[$key]['pay_way'] = date('Y-m-d ', $value['time']); } } /** * 构造函数 * @param string $name 模型名称 * @param string $tablePrefix 表前缀 * @param mixed $connection 数据库连接信息 */ public function __construct($name = '', $tablePrefix = '', $connection = '') { /* 设置默认的表前缀 */ $this->tablePrefix = 'tab_'; /* 执行构造方法 */ parent::__construct($name, $tablePrefix, $connection); } /** * 创建时间不写则取当前时间 * @return int 时间戳 * @author huajie */ protected function getCreateTime() { $create_time = I('post.create_time'); return $create_time ? strtotime($create_time) : NOW_TIME; } public function amdin_account() { return session('user_auth.username'); } public function totalSpendTimes($map = "") { $map['s.pay_status'] = 1; $data = $this->alias("s")->field("IFNULL(count(pay_amount),0) as count") ->join("left join tab_game g on g.id = s.game_id") ->where($map) ->find(); return $data['count']; } /** * [dealPage 页码处理] * @param [type] $p [description] * @return [type] [description] */ public function dealPage($p) { $page = intval($p); $page = $page ? $page : 1; //默认显示第一页数据 return $page; } /** * 自动补单 */ public static function auto_repair() { $game = new GameApi(); $map['pay_status'] = 1; $map['pay_game_status'] = 0; $order = M("spend", 'tab_')->field('pay_order_number,1 as code')->where($map)->select();//普通消费 $bind_spend = M("bind_spend", 'tab_')->field('pay_order_number,2 as code')->where($map)->select();//绑币消费 if (!empty($bind_spend)) { array_push($order, $bind_spend); } $success_num = $error_num = 0; foreach ($order as $key => $val) { $param['out_trade_no'] = $val['pay_order_number']; $result = $game->game_pay_notify($param, $val['code']); if ($val['code'] == 1) { M('spend', 'tab_')->where(['pay_order_number' => $val['pay_order_number']])->setInc('auto_compensation'); } else { M('bind_spend', 'tab_')->where(['pay_order_number' => $val['pay_order_number']])->setInc('auto_compensation'); } if ($result == "success") { $success_num++; } else { $error_num++; } } $time = time_format0(); \Think\Log::record("自动补单({$time}):成功 {$success_num} 个,失败:{$error_num}个"); } /** * 退款接口 * @param $map */ public function Refund($map, $order, $sign) { if (md5("mcaseqwezdsi" . $order) !== $sign) { return false; } $RefundRecord = M('RefundRecord', 'tab_')->where($map)->find(); if (null == $RefundRecord) { $find = $this->where($map)->find(); $order_number = $find['pay_way'] == 1 ? date("YmdHis") : "TK_" . date('Ymd') . date('His') . sp_random_string(4); $BatchNo = date("YmdHis"); } else { $order_number = $RefundRecord['order_number']; $BatchNo = $RefundRecord['batch_no']; $find = $RefundRecord; } if ($find['pay_way'] == 1) { //页面上通过表单选择在线支付类型,支付宝为alipay 财付通为tenpay $pay = new \Think\Pay('alipay', C('alipay')); $vo = new \Think\Pay\PayVo(); $detail_data = $find['order_number'] . "^" . $find['pay_amount'] . "^调单"; $find['batch_no'] = $BatchNo; $vo->setOrderNo($find['order_number']) ->setService("refund_fastpay_by_platform_pwd") ->setSignType("MD5") ->setPayMethod("refund") ->setTable("RefundRecord") ->setBatchNo($BatchNo) ->setDetailData($detail_data); $this->add_refund_record($find, $find['order_number']); $this->where($map)->delete(); return $pay->buildRequestForm($vo); } elseif ($find['pay_way'] == 3) { $weixn = new Weixin(); $res = json_decode($weixn->weixin_Refund_pub($find['pay_order_number'], $order_number, $find['pay_amount'], $find['pay_amount'], C('wei_xin_app.partner')), true); $this->add_refund_record($find, $order_number); $this->where($map)->delete(); if ($res['status'] == 1) { return $res['status']; } else { return $res; } } elseif ($find['pay_way'] == 4) { $config = array("partner" => trim(C("weixin.partner")), "email" => "", "key" => trim(C("weixin.key"))); $pay = new \Think\Pay('swiftpass', $config); $vo = new \Think\Pay\PayVo(); $vo->setService('unified.trade.refund') ->setSignType("MD5") ->setPayMethod("refund") ->setTable("RefundRecord") ->setOrderNo($find['pay_order_number']) ->setBatchNo($order_number) ->setFee($find['pay_amount']); $this->add_refund_record($find, $order_number); $this->where($map)->delete(); $res = $pay->buildRequestForm($vo); if ($res['status'] == 0) { return $res['status']; } else { return false; } } elseif ($find['pay_way'] == 0) { $user_map['id'] = $find['user_id']; M('user', 'tab_')->where($user_map)->setInc('balance', $find['pay_amount']); $this->add_refund_record($find, $order_number); $this->where($map)->delete(); return true; } } /** * 添加退款记录 * @param $data * @return mixed */ public function add_refund_record($data, $order_number) { $RefundRecord = M('RefundRecord', 'tab_'); unset($data['id']); $map['pay_order_number'] = $data['pay_order_number']; $find = $RefundRecord->where($map)->find(); if (null !== $find) { if ($data['pay_way'] == 4 || $data['pay_way'] == 3) { $RefundRecord->where($map)->delete(); $data['tui_status'] = 2; $data['create_time'] = time(); $data['tui_amount'] = $data['pay_amount']; $data['order_number'] = $order_number; return $RefundRecord->add($data); } else { return true; } } else { if ($data['pay_way'] == 0) { $data['tui_status'] = 1; $data['tui_time'] = time(); $savv['sub_status'] = 1; $savv['settle_check'] = 1; $this->where($map)->save($savv); } elseif ($data['pay_way'] == 4 || $data['pay_way'] == 3) { $data['tui_status'] = 2; } $data['create_time'] = time(); $data['tui_amount'] = $data['pay_amount']; $data['order_number'] = $order_number; return $RefundRecord->add($data); } } /** * 微信退款查询接口 * @param [type] $orderNo [description] * @return [type] [description] */ public function weixin_refundquery($orderNo) { $weixn = new Weixin(); $res = $weixn->weixin_refundquery($orderNo); if ($res == "SUCCESS") { M('RefundRecord', 'tab_')->where(array('pay_order_number' => $orderNo))->setField('tui_status', 1); return json_encode(array('status' => 1, 'msg' => '退款成功')); } elseif ($res == "FAIL") { return json_encode(array('status' => 0, 'msg' => '退款失败')); } elseif ($res == "PROCESSING") { return json_encode(array('status' => 0, 'msg' => '退款处理中')); } } /** * 威富通查询退款接口 * @param [type] $map [description] * @return [type] [description] */ public function swiftpass_refund($orderNo) { $config = array("partner" => trim(C("weixin.partner")), "email" => "", "key" => trim(C("weixin.key"))); $pay = new \Think\Pay('swiftpass', $config); $vo = new \Think\Pay\PayVo(); $vo->setOrderNo($orderNo) ->setService('unified.trade.refundquery') ->setSignType("MD5") ->setPayMethod("find") ->setTable("RefundRecord"); $res = $pay->buildRequestForm($vo); if ($res['refund_status'] == "SUCCESS") { M('RefundRecord', 'tab_')->where(array('pay_order_number' => $orderNo))->setField('tui_status', 1); return json_encode(array('status' => 1, 'msg' => '退款成功')); } elseif ($res['refund_status'] == "FAIL") { return json_encode(array('status' => 0, 'msg' => '退款失败')); } elseif ($res['refund_status'] == "PROCESSING") { return json_encode(array('status' => 0, 'msg' => '退款处理中')); } } /** * 开放平台 付费人数 * @param string $map * @return mixed * author: xmy 280564871@qq.com */ public function countSpendUserOfOpen($map = "") { $sql = $this->alias("s")->field("s.user_id") ->join("left join tab_game g on g.id = s.game_id") ->where($map) ->group("s.game_id,s.user_id") ->select(false); $sql = "select count(DISTINCT user_id) as num from ({$sql}) as res"; $data = M()->query($sql); return $data[0]['num']; } /** * 累计付费 * @param string $map * @return mixed * author: xmy 280564871@qq.com */ public function totalSpend($map = "") { $map['s.pay_status'] = 1; $data = $this->alias("s")->field("IFNULL(sum(pay_amount),0) as num") ->join("right join tab_game g on g.id = s.game_id") ->where($map) ->find(); return $data['num']; } /** * 获取开放平台流水 * @param $map * @param $develop_id * author: xmy 280564871@qq.com */ public function getOpenSpend($map, $develop_id, $game_id) { // empty($game_id) || $map['s.game_id'] = $game_id; empty($game_id) || $join = "and g.id = {$game_id}"; $data = $this->alias("s")->field("IFNULL(sum(pay_amount),0) as num,d.time") ->join("right join tab_game g on g.id = s.game_id and g.developers = $develop_id {$join}") ->join("right join sys_date_list d on d.time = FROM_UNIXTIME(s.pay_time,'%Y-%m-%d') and s.pay_status = 1") ->where($map) ->group("d.time") ->select(); return $data; } /** * 付费玩家数 * @param $map * @param $develop_id * @return mixed * author: xmy 280564871@qq.com */ public function getPayerNum($map, $develop_id, $game_id) { // empty($game_id) || $map['s.game_id'] = $game_id; empty($game_id) || $join = "and g.id = {$game_id}"; $data = $this->alias("s")->field("IFNULL(count(DISTINCT user_id),0) as num,d.time") ->join("right join tab_game g on g.id = s.game_id and g.developers = $develop_id {$join}") ->join("right join sys_date_list d on d.time = FROM_UNIXTIME(s.pay_time,'%Y-%m-%d') and s.pay_status = 1") ->where($map) ->group("d.time") ->select(); return $data; } /** * 新增付费玩家 * @param $start * @param $end * @param $develop_id * @return mixed * author: xmy 280564871@qq.com */ public function getNewPayerNum($start, $end, $develop_id, $game_id) { //第一次充值 empty($game_id) || $map['s.game_id'] = $game_id; $map['s.pay_status'] = 1; $sql = $this->alias("s")->field("user_id,min(pay_time) as pay_time") ->join("right join tab_game g on g.id = s.game_id and g.developers = $develop_id") ->where($map) ->group("s.user_id") ->select(false); $sql = "SELECT count(res.user_id) as num,d.time FROM ({$sql}) res right join sys_date_list d on d.time = FROM_UNIXTIME(res.pay_time,'%Y-%m-%d') WHERE d.time BETWEEN '{$start}' and '{$end}' GROUP BY d.time"; $data = $this->query($sql); return $data; } /** * 累计付费玩家数(按天分组) * @param $map * @param $develop_id * @return mixed * author: xmy 280564871@qq.com */ public function getTotalPayerNum($start, $end, $develop_id) { $start = strtotime($start); $end = strtotime($end); $map['g.developers'] = $develop_id; $map['s.pay_status'] = 1; for ($time = $start; $time <= $end; $time += 86400) { $map['s.pay_time'] = ['lt', $time + 86399]; $data[]['num'] = $this->countSpendUserOfOpen($map); } return $data; } /** * 累计流水 * @param $map * @return mixed * author: xmy 280564871@qq.com */ public function getTotalSpend($map) { $map['pay_status'] = 1; $data = $this->field("IFNULL(sum(pay_amount),0) as num")->where($map)->find(); return $data; } /* * 游戏充值未到账列表 * @return array 结果集 * @author 鹿文学 */ public function checkSpend() { $list = $this->field('id,user_id,user_account,game_id,game_name,pay_amount,pay_order_number')->where(array('pay_status' => 0))->select(); $type = 101; if ($list[0]) { $list = D('check')->dealWithCheckList($type, $list); if (empty($list[0])) { return ''; } foreach ($list as $k => $v) { $data[$k]['info'] = '玩家:' . $v['user_account'] . ',游戏[' . $v['game_name'] . ']充值金额:' . $v['pay_amount'] . ',订单状态:下单未支付'; $data[$k]['type'] = $type; $data[$k]['url'] = U('Spend/lists', array('pay_order_number' => $v['pay_order_number'])); $data[$k]['create_time'] = time(); $data[$k]['status'] = 0; $data[$k]['position'] = $v['id']; } return $data; } else { D('check')->dealWithCheckListOnNull($type); return ''; } } /* * 游戏补单列表 * @return array 结果集 * @author 鹿文学 */ public function checkSupplement() { $list = $this->field('id,user_id,user_account,pay_order_number')->where(array('pay_status' => 1, 'pay_game_status' => 0))->select(); $type = 102; if ($list[0]) { $list = D('check')->dealWithCheckList($type, $list); if (empty($list[0])) { return ''; } foreach ($list as $k => $v) { $data[$k]['info'] = '玩家:' . $v['user_account'] . ',订单:' . $v['pay_order_number'] . ',操作:补单失败'; $data[$k]['type'] = $type; $data[$k]['url'] = U('Spend/lists', array('pay_order_number' => $v['pay_order_number'])); $data[$k]['create_time'] = time(); $data[$k]['status'] = 0; $data[$k]['position'] = $v['id']; } return $data; } else { D('check')->dealWithCheckListOnNull($type); return ''; } } /** * 统计总流水 * @param array $where 条件数组 * @return integer 数量 * @author 鹿文学 */ public function totalAmount($map = array()) { $map['pay_status'] = 1; $sum = $this->where($map)->sum('pay_amount'); return $sum ? $sum : 0; } /** * 分组统计流水 * @param array $map 条件数组 * @param string $fieldname 字段别名 * @param string $group 分组字段名 * @param integer $flag 时间类别(1:天,2:月,3:周) * @return array 详细数据 * @author 鹿文学 */ public function totalAmountByGroup($map = array(), $fieldname = 'amount', $group = 'time', $flag = 1, $order = 'time') { switch ($flag) { case 2: { $dateform = '%Y-%m'; }; break; case 3: { $dateform = '%Y-%u'; }; break; case 4: { $dateform = '%Y'; }; break; case 5: { $dateform = '%Y-%m-%d %H'; }; break; default: $dateform = '%Y-%m-%d'; } $map['pay_status'] = 1; $data = $this->field('FROM_UNIXTIME(pay_time,"' . $dateform . '") as ' . $group . ',sum(pay_amount) as ' . $fieldname) ->where($map)->group($group)->order($order)->select(); return $data; } /** * 分组统计所有流水 * @param array $map 条件数组 * @param string $fieldname 字段别名 * @param string $group 分组字段名 * @param integer $flag 时间类别(1:天,2:月,3:周) * @return array 详细数据 * @author 鹿文学 */ public function allAmountByGroup($map = array(), $fieldname = 'amount', $group = 'time', $flag = 1, $order = 'time') { switch ($flag) { case 2: { $dateform = '%Y-%m'; }; break; case 3: { $dateform = '%Y-%u'; }; break; case 4: { $dateform = '%Y'; }; break; case 5: { $dateform = '%Y-%m-%d %H'; }; break; default: $dateform = '%Y-%m-%d'; } $map['pay_status'] = 1; $union = D('deposit')->field('pay_order_number,FROM_UNIXTIME(create_time,"' . $dateform . '") as ' . $group . ',sum(pay_amount) as ' . $fieldname) ->where(['create_time' => $map['pay_time'], 'pay_status' => 1]) ->group($group)->select(false); $bind = M('Bind_recharge', 'tab_')->field('pay_order_number,FROM_UNIXTIME(create_time,"' . $dateform . '") as ' . $group . ',sum(real_amount) as ' . $fieldname) ->where(['create_time' => $map['pay_time'], 'pay_status' => 1]) ->group($group)->select(false); $sql = $this->field('pay_order_number,FROM_UNIXTIME(pay_time,"' . $dateform . '") as ' . $group . ',sum(pay_amount) as ' . $fieldname) ->union('(' . $union . ')') ->union('(' . $bind . ')') ->where($map)->group($group)->select(false); $data = $this->table('(' . $sql . ') as a')->field('a.' . $group . ',sum(a.' . $fieldname . ') as ' . $fieldname)->group('a.' . $group)->order($order)->select(); return $data; } /* * 付费用户 * @param array $map 条件数组 * @param string $fieldname 字段别名 * @param string $group 分组字段名 * @param integer $flag 时间类别(1:天,2:月,3:周) * @return array 详细数据 * @author 鹿文学 */ public function totalPlayerByGroup($map = array(), $fieldname = 'count', $group = 'time', $flag = 1, $order = 'time') { switch ($flag) { case 2: { $dateform = '%Y-%m'; }; break; case 3: { $dateform = '%Y-%u'; }; break; case 4: { $dateform = '%Y'; }; break; case 5: { $dateform = '%Y-%m-%d %H'; }; break; default: $dateform = '%Y-%m-%d'; } $map['pay_status'] = 1; $data = $this->field('FROM_UNIXTIME(pay_time,"' . $dateform . '") as ' . $group . ',count( DISTINCT user_id) as ' . $fieldname) ->where($map)->group($group)->order($order)->select(); return $data; } /* * 付费用户 * @param integer $start 开始时间戳 * @param integer $end 结束时间戳 * @param string $fieldname 字段别名 * @param string $group 分组字段名 * @param integer $flag 时间类别(1:天,2:月,3:周) * @return array 详细数据 * @author 鹿文学 */ public function totalPlayerByTime($start, $end, $fieldname = 'count', $group = 'time', $flag = 1, $order = 'time') { switch ($flag) { case 2: { $dateform = '%Y-%m'; }; break; case 3: { $dateform = '%Y-%u'; }; break; case 4: { $dateform = '%Y'; }; break; case 5: { $dateform = '%Y-%m-%d %H'; }; break; default: $dateform = '%Y-%m-%d'; } $map['pay_status'] = 1; $map['create_time'] = ['between', [$start, $end]]; $bindrecharge_data = M('bind_recharge', 'tab_')->field('FROM_UNIXTIME(create_time,"' . $dateform . '") as ' . $group . ',GROUP_CONCAT( DISTINCT user_id) as user_id') ->where($map)->group($group)->select(false); $deposit_data = M('deposit', 'tab_')->field('FROM_UNIXTIME(create_time,"' . $dateform . '") as ' . $group . ',GROUP_CONCAT( DISTINCT user_id) as user_id') ->where($map)->group($group)->select(false); $map['pay_way'] = array('gt', 0); unset($map['create_time']); $map['pay_time'] = ['between', [$start, $end]]; $lists = $this->field('FROM_UNIXTIME(pay_time,"' . $dateform . '") as ' . $group . ',GROUP_CONCAT( DISTINCT user_id) as user_id') ->union(' (' . $bindrecharge_data . ') ')->union(' (' . $deposit_data . ') ') ->where($map)->group($group)->select(false); $lists = $this->field('a.' . $group . ',GROUP_CONCAT(a.user_id) as user_id')->table(' (' . $lists . ') as a')->group('a.' . $group)->order('a.' . $order)->select(); $data = []; foreach ($lists as $k => $v) { $userid = array_unique(explode(',', $v['user_id'])); $data[$k] = array( $group => $v[$group], $fieldname => count($userid), ); } return $data; } /* * 付费用户总数 * @param array $map 条件数组 * @author 鹿文学 */ public function player($map = array()) { $map['pay_status'] = 1; $data = $this->field('count( DISTINCT user_id) as count') ->where($map)->select(); return $data[0] ? $data[0]['count'] : 0; } /* * 付费总数 * @param array $map 条件数组 * @author 鹿文学 */ public function amount($map = array()) { $map['pay_status'] = 1; $data = $this ->where($map)->sum('pay_amount'); return $data ? $data : 0; } /** * 列表 * * @param int $p * @param array $map * @param bool $field * * @return mixed * * @throws \think\Exception * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException * @author: 鹿文学[lwx] * @since: 2019\4\11 0011 13:40 */ public function lists($p = 1, $map = array(), $order, $field = true) { $page = intval($p); $page = $page ? $page : 1; //默认显示第一页数据 if (isset($_REQUEST['row'])) { $row = $_REQUEST['row']; } else { $row = 10; } $list = $this ->where($map) ->page($page, $row) ->order($order ? $order : 'pay_time desc') ->select(); $count = $this->where($map)->count(); $data['data'] = $list; $page = set_pagination($count, $row); if ($page) { $data['page'] = $page; } return $data; } /** * 获取统计 $map,$page,$row */ public function getSpendData($map = [], $field = '', $group = '', $order = '', $page = 0, $row = 0, $join = false) { $query = $this->field($field)->where($map)->group($group)->order($order); if ($join) { $query = $query->join($join); } if ($row == 0) { $data = $query->select(); } else { $data = $query->page($page, $row)->select(); } return $data; } public function sumSpend($map = [], $field = '') { $sum = $this->where($map)->sum($field); return $sum; } /** *获取游戏统计列表数据 * @param $map array 查询条件 * @param $row int 每页条数 * @param $page int 第几页 */ public function gameStatistics($map, $row = 0, $page = 1) { $query = $this->alias("s") ->field("s.game_id,s.game_name,p.partner as partner_name, SUM(CASE WHEN pay_way > 0 THEN pay_amount ELSE 0 END) as cash_count, SUM(CASE WHEN pay_way = 0 THEN pay_amount ELSE 0 END) as balance_coin_count, SUM(CASE WHEN pay_way = -1 THEN pay_amount ELSE 0 END) as inside_cash_count") ->join('LEFT JOIN tab_game as g ON s.game_id=g.id') ->join('LEFT JOIN tab_partner as p ON g.partner_id=p.id') ->where(['s.pay_status' => 1, 'pay_game_status' => 1]) ->where($map) ->group('s.game_id'); if ($row) { $query = $query->page($page,$row); } $data = $query->select(); return $data; } /** *获取游戏统计列表数据 */ public function totalGameStatistics($map, $join = true) { $query = $this->alias("s") ->field("SUM(CASE WHEN pay_way > 0 THEN pay_amount ELSE 0 END) as cash_count, SUM(CASE WHEN pay_way = 0 THEN pay_amount ELSE 0 END) as balance_coin_count, SUM(CASE WHEN pay_way = -1 THEN pay_amount ELSE 0 END) as inside_cash_count"); if ($join) { $query = $query->join('LEFT JOIN tab_game as g ON s.game_id=g.id') ->join('LEFT JOIN tab_partner as p ON g.partner_id=p.id'); } $data = $query->where(['s.pay_status' => 1, 'pay_game_status' => 1]) ->where($map) ->find(); // dd($query->_sql()); return $data; } }