account_type); } public function verify_login_type($login_type) { return in_array($login_type, $this->login_type); } } class auth_list { /** @var array $items */ public $items; public function __construct($list) { $this->items = array(); if (is_object($list)) $list = (array)$list; if (is_array($list)) { foreach ($list as $item) { array_push($this->items, new auth_item($item)); } } } public function search($name) { /** @var auth_item $item */ foreach($this->items as $item) { if (0 == strcasecmp($item->name, $name)) return $item; } return null; } } class game_item extends ToolBase { public $game_id; public $scheme = 'http'; public $address; public $port; public function get_address($param = null, $needencode = true) { if (empty($this->scheme)) { $is_https = (isset($_SERVER['REQUEST_SCHEME']) && strcasecmp($_SERVER['REQUEST_SCHEME'], 'https') == 0) || (isset($_SERVER['HTTPS']) && (strcasecmp($_SERVER['HTTPS'], 'on') == 0 || strcasecmp($_SERVER['HTTPS'], '1') == 0)); $this->scheme = $is_https ? 'https' : 'http'; } if (empty($this->port)) { if (0 == strcasecmp('https', $this->scheme)) $this->port = 443; else $this->port = 80; } if (0 == strcasecmp('https', $this->scheme)) $result = 'https://' . $this->address . (443 == $this->port ? '' : ':' . $this->port) . '/index.html'; else $result = 'http://' . $this->address . (80 == $this->port ? '' : ':' . $this->port) . '/index.html'; if (empty($param)) return $result; if (is_object($param)) $param = (array)$param; if ($needencode) { if (is_array($param)) { $data = array(); foreach ($param as $key => $value) { array_push($data, rawurlencode($key) . '=' . rawurlencode($value)); } $result .= '?' . implode('&', $data); } else { $result .= '?' . rawurlencode($param); } } else { if (is_array($param)) { $data = array(); foreach ($param as $key => $value) { array_push($data, $key . '=' . $value); } $result .= '?' . implode('&', $data); } else { $result .= '?' . $param; } } return $result; } } class game_list { /** @var array of game_item */ public $items; public function __construct($list) { $this->items = array(); if (is_object($list)) $list = (array)$list; if (is_array($list)) { foreach ($list as $item) { array_push($this->items, new game_item($item)); } } } public function search($game_id) { /** @var game_item $item */ foreach($this->items as $item) { if (0 == strcasecmp($item->game_id, $game_id)) return $item; } return null; } } class player extends BaseMethod { const SCHEME_HTTP = 'http'; const SCHEME_HTTPS = 'https'; const GAME_ID_TEST = 'test'; /// 测试环境下的游戏id,不用更改。 /// 有效的来源标志 const AUTH_SIGN = [ /// 游戏跳转的标志 [ 'name' => 'WHITELOGIN', /// 标志标识 'account_type' => [], /// 允许使用的账户类型 'login_type' => [2], /// 允许使用的登录类型 ], /// 黄超的标志 [ 'name' => 'GAMEPAY', /// 标志标识 'account_type' => [1, 2, ], /// 允许使用的账户类型 'login_type' => [1], /// 允许使用的登录类型 ], /// 第一个三方游戏来源 [ 'name' => 'TG9000000001', /// 标志标识 'account_type' => [101, 102, ], /// 允许使用的账户类型 'login_type' => [1], /// 允许使用的登录类型 ], ]; /** @var auth_list $auth_list */ private $auth_list; /** @var game_list $game_list */ private $game_list; public function __construct() { parent::__construct(); $this->auth_list = new auth_list(self::AUTH_SIGN); if (file_exists(dirname(__DIR__) . '/config/game.config.json')) { $str = file_get_contents(dirname(__DIR__) . '/config/game.config.json'); $obj = JsonStringToJsonObject($str); if (is_null($obj)) { $obj = include dirname(__DIR__) . '/config/game.config.php'; } $this->game_list = new game_list($obj); } else { $this->game_list = new game_list(include dirname(__DIR__) . '/config/game.config.php'); } } /** * 用户登录 * 被请求方法示例:参数固定为RequestParameter和ReturnParameter对象,返回值固定为true(成功)和false(失败) * @param RequestParameter $request * @param ReturnParameter $return * @return bool * { "agentid": "a", "channelid": "b", "openid": "c", "unionid": "d", "nickname": "eee", "avatar": "dd", "sex": 0, "province": "jx", "city": "nc" } */ public function login($request, $return) { $param = (array)@$request->biz_content; if (!is_array($param)) { //参数格式错误 $return->seterrors(ERRORCODE_INPARAMERROR, ERRORINFO_INPARAMERROR); return false; } $agent_id = empty(@$param['agentid']) ? '' : $param['agentid']; /// 代理 $channel_id = empty(@$param['channelid']) ? '' : $param['channelid']; /// 渠道 //$game_id = empty(@$param['gameid']) ? '' : $param['gameid']; /// 游戏id $player_id = empty(@$param['playerid']) ? '' : $param['playerid']; /// 用户id $open_id = empty(@$param['openid']) ? '' : $param['openid']; /// openid $union_id = empty(@$param['unionid']) ? '' : $param['unionid']; /// unionid //$nick_name = empty(@$param['nickname']) ? '' : $param['nickname']; /// 昵称 //$avatar = empty(@$param['avatar']) ? '' : $param['avatar']; /// 头像 $from_sign = mb_strtoupper(empty(@$param['fromsign']) ? '' : $param['fromsign'], USEDCHARSET); /// 来源标志 if (empty($agent_id)) { $return->seterrors(ERRORCODE_AGENTIDERROR, ERRORINFO_AGENTIDERROR); return false; } if (empty($channel_id)) { $return->seterrors(ERRORCODE_CHANNELIDERROR, ERRORINFO_CHANNELIDERROR); return false; } if (empty($player_id)) { $return->seterrors(ERRORCODE_PLAYERIDERROR, ERRORINFO_PLAYERIDERROR); return false; } /// 判断来源 $auth = $this->auth_list->search($from_sign); if (!$auth) { $return->seterrors(ERRORCODE_INVALIDPARAMETER, sprintf(ERRORINFO_INVALIDPARAMETER, 'source sign')); return false; } if (!$cmd = $this->NewServantCommand()) $cmd = $this->NewMasterCommand(); if ($auth->verify_login_type(1)) /// 允许获取玩家信息 { if (!empty($union_id)) { $ret = $cmd ->select('idx', 'play_playerid', 'play_nickname', 'play_avatar', 'play_sex', 'play_roomcard', 'play_bean', 'play_invitecode', 'play_openid', 'play_unionid') ->from('player') ->where([ 'play_agentid' => $agent_id, 'play_channelid' => $channel_id, 'play_unionid' => $union_id, 'play_playerid' => $player_id, ]) ->request(); } elseif (!empty($open_id)) { $ret = $cmd ->select('idx', 'play_playerid', 'play_nickname', 'play_avatar', 'play_sex', 'play_roomcard', 'play_bean', 'play_invitecode', 'play_openid', 'play_unionid') ->from('player') ->where([ 'play_agentid' => $agent_id, 'play_channelid' => $channel_id, 'play_openid' => $open_id, 'play_playerid' => $player_id, ]) ->request(); } else { $return->seterrors(ERRORCODE_INVALIDPARAMETER, sprintf(ERRORINFO_INVALIDPARAMETER, 'player information')); return false; } if (!$this->pdo_isdone()) { $return->seterrors($this->geterrorcode(), $this->geterrorinfo()); return false; } elseif (empty($ret)) { $return->seterrors(ERRORCODE_PLAYERNOTEXISTERROR, ERRORINFO_PLAYERNOTEXISTERROR); return false; } $player = $ret[0]; /// 请求玩家 $playerData = array( 'app' => 'youle', 'route' => 'agent', 'rpc' => 'query_player2', 'data' => array( 'agentid' => $agent_id, 'playerid' => $player_id, ), ); $json_data = json_encode($playerData); $dd_ret = file_get_contents(REQUEST_USER_INFO . '?' . $json_data); /// 请求数据出错 if (!$dd_ret) { $return->SetErrors(ERRORCODE_NODATAERROR, ERRORINFO_NODATAERROR); return false; } $playerInfo = json_decode($dd_ret, true); $player['play_nickname'] = usefull::getInstance()->check_name($playerInfo['data']['nickname']); $player['play_avatar'] = isset($playerInfo['data']['avatar']) ? $playerInfo['data']['avatar'] : ''; $player['play_roomcard'] = isset($playerInfo['data']['roomcard']) ? $playerInfo['data']['roomcard'] : ''; $player['play_bean'] = isset($playerInfo['data']['bean']) ? $playerInfo['data']['bean'] : ''; $ret = $this->pdo_execute(/** @lang text */'update player set play_nickname=?, play_avatar=?, play_sex=?, play_roomcard=?, play_bean=? where idx=?', $player['play_nickname'], $player['play_avatar'], isset($playerInfo['data']['sex']) ? $playerInfo['data']['sex'] : '', $player['play_roomcard'], $player['play_bean'], $player['idx']); if (!$ret) { $return->SetErrors($this->GetErrorCode(), $this->GetErrorInfo()); return false; } /// 记录登录流水 $ret = $this->pdo_execute(/** @lang text */ 'insert into ct_player_login_info(agent_id,channel_id,player_id,login_time,from_sign) values(?,?,?,now(),?)', $agent_id, $channel_id, $player_id, $from_sign); if (!$ret) { $return->seterrors($this->geterrorcode(), $this->geterrorinfo()); return false; } // if (strcmp($ret['play_playerid'], $player_id)) /// id不匹配 // { // $return->seterrors(ERRORCODE_PLAYERIDERROR, ERRORINFO_PLAYERIDERROR); // return false; // } // // /// 更新昵称和头像 // $ret = $cmd // ->update('player') // ->fields('play_nickname', 'play_avatar') // ->values($nick_name, $avatar) // ->where(array('idx' => $player['idx'])) // ->execute(); // if (!$ret) // { // $return->seterrors($this->geterrorcode(), $this->geterrorinfo()); // return false; // } $player_info = array( 'playerid' => $player_id, /// id 'openid' => $player['play_openid'], /// openid 'unionid' => $player['play_unionid'], /// unionid 'nickname' => $player['play_nickname'], /// 昵称 'avatar' => $player['play_avatar'], /// 头像 'sex' => $player['play_sex'], /// 性别 'card' => empty($player['play_roomcard']) ? 0 : $player['play_roomcard'], /// 房卡数 'gold' => empty($player['play_bean']) ? 0 : $player['play_bean'], /// 金币数 'invitecode' => empty($player['play_invitecode']) ? '' : $player['play_invitecode'], /// 邀请码 ); } else $player_info = []; if ($auth->verify_login_type(2)) /// 允许获取代理信息 { $fields = [ 'idx', 'saus_agentid', 'saus_channelid', 'saus_openid', 'saus_unionid', 'saus_salesman', 'saus_salesid', 'saus_level', 'saus_salestype', 'saus_roomcard', 'saus_bean', 'saus_power', 'saus_invitecode', 'saus_pushmoney1', 'saus_pushmoney2', 'saus_status', 'password', 'global_power', 'saus_tel', 'saus_wechat', 'is_send_star', 'saus_nickname', 'saus_avatar', 'saus_sex', 'saus_province', 'saus_city', 'user_id', 'player_id', 'is_vip' ]; if (!empty($union_id)) { $ret = $cmd ->select($fields) ->from('sales_user') ->where(['saus_agentid' => $agent_id, 'saus_channelid' => $channel_id, 'saus_unionid' => $union_id, 'player_id' => $player_id, ]) ->request(); } elseif (!empty($open_id)) { $ret = $cmd ->select($fields) ->from('sales_user') ->where(['saus_agentid' => $agent_id, 'saus_channelid' => $channel_id, 'saus_openid' => $open_id, 'player_id' => $player_id, ]) ->request(); } else { $return->seterrors(ERRORCODE_INVALIDPARAMETER, sprintf(ERRORINFO_INVALIDPARAMETER, 'player information')); return false; } if (!$this->pdo_isdone()) { $return->seterrors($this->geterrorcode(), $this->geterrorinfo()); return false; } elseif (empty($ret)) { $return->seterrors(ERRORCODE_PLAYERNOTEXISTERROR, ERRORINFO_PLAYERNOTEXISTERROR); return false; } $sales = $ret[0]; if (isset($_SERVER['HTTP_CLIENT_IP'])) $address = $_SERVER['HTTP_CLIENT_IP']; elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) $address = $_SERVER['HTTP_X_FORWARDED_FOR']; elseif (isset($_SERVER['REMOTE_ADDR'])) $address = $_SERVER['REMOTE_ADDR']; else $address = null; /// 记录登录流水 $ret = $cmd ->insert('ct_sales_login_log') ->fields('agent_id', 'channel_id', 'sales_id', 'login_type', 'login_time', 'login_addr', 'login_status') ->values($agent_id, $channel_id, $sales['saus_salesid'], 2, date('Y-m-d H:i:s'), $address, 0) ->execute(); if (!$ret) { $return->seterrors($this->geterrorcode(), $this->geterrorinfo()); return false; } /// 返回用户信息 $sales_info = array( 'idx' => isset($sales['idx']) ? $sales['idx'] : '', /// 代理 'agentid' => isset($sales['saus_agentid']) ? $sales['saus_agentid'] : '', /// 代理 'channelid' => isset($sales['saus_channelid']) ? $sales['saus_channelid'] : '', /// 渠道 'openid' => isset($sales['saus_openid']) ? $sales['saus_openid'] : '', /// openid 'unionid' => isset($sales['saus_unionid']) ? $sales['saus_unionid'] : '', /// unionid 'nickname' => isset($sales['saus_nickname']) ? $sales['saus_nickname'] : '', /// 昵称 'headimgurl' => isset($sales['saus_avatar']) ? $sales['saus_avatar'] : '', /// 头像 'sex' => isset($sales['saus_sex']) ? $sales['saus_sex'] : '', /// 性别 'province' => isset($sales['saus_province']) ? $sales['saus_province'] : '', /// 省 'city' => isset($sales['saus_city']) ? $sales['saus_city'] : '', /// 市 'salesman' => empty($sales['saus_salesman']) ? 0 : intval($sales['saus_salesman']), /// 是否代理 'salesid' => isset($sales['saus_salesid']) ? $sales['saus_salesid'] : '', /// 代理编号 'level' => isset($sales['saus_level']) ? $sales['saus_level'] : '', /// 代理等级 'salestype' => isset($sales['saus_salestype']) ? $sales['saus_salestype'] : '', /// 代理类型 'roomcard' => isset($sales['saus_roomcard']) ? $sales['saus_roomcard'] : '', /// 账户房卡数 'bean' => isset($sales['saus_bean']) ? $sales['saus_bean'] : '', /// 账户金币数 'salespower' => isset($sales['saus_power']) ? $sales['saus_power'] : '', /// 代理权限 'agentmode' => '', /// 分享模式 //'pushmoney' => intval($sales['saus_pushmoney1']) + intval($sales['saus_pushmoney2']), /// 提成金额 'sausstatus' => isset($sales['saus_status']) ? $sales['saus_status'] : '', /// 当前状态 'html_applysales' => '', /// 成为代理的方式 'global_power' => isset($sales['global_power']) ? intval($sales['global_power']) : 0, /// 是否总代 'tel' => isset($sales['saus_tel']) ? $sales['saus_tel'] : '', /// 电话号码 'wechat' => isset($sales['saus_wechat']) ? $sales['saus_wechat'] : '', /// 微信号码 'user_id' => empty(@$sales['user_id']) ? '' : $sales['user_id'], /// 统一账户编号 'is_bind' => empty($sales['saus_tel']) ? 0 : (0 == $sales['is_send_star'] ? 0 : 1), /// 是否绑定 'logintype' => 11, /// 自动登录 'player_id' => isset($sales['player_id']) ? $sales['player_id'] : '', 'is_vip' => $sales['is_vip'], ); } else $sales_info = []; $return->biz_content = []; foreach ($player_info as $k => $v) { $return->biz_content[$k] = $v; } foreach ($sales_info as $k => $v) { $return->biz_content[$k] = $v; } return true; } /** * 用户登录 * 被请求方法示例:参数固定为RequestParameter和ReturnParameter对象,返回值固定为true(成功)和false(失败) * @param RequestParameter $request * @param ReturnParameter $return * @return bool * { "agentid": "a", "channelid": "b", "openid": "c", "unionid": "d", "nickname": "eee", "avatar": "dd", "sex": 0, "province": "jx", "city": "nc" } */ public function change_account($request, $return) { $param = (array)@$request->biz_content; if (!is_array($param)) { /// 参数格式错误 $return->seterrors(ERRORCODE_INPARAMERROR, ERRORINFO_INPARAMERROR); return false; } $agent_id = empty(@$param['agentid']) ? '' : $param['agentid']; /// 代理 $channel_id = empty(@$param['channelid']) ? '' : $param['channelid']; /// 渠道 $game_id = empty(@$param['gameid']) ? '' : $param['gameid']; /// 游戏id $player_id = empty(@$param['playerid']) ? '' : $param['playerid']; /// 用户id $change_type = intval(empty(@$param['changetype']) ? 0 : $param['changetype']); /// 类型(1:购买房卡;2:购买金币;101:三方转账房卡;102:三方转账金币;) $change_amount = floatval(empty(@$param['changeamount']) ? 0 : $param['changeamount']); /// 变更数量 $transaction_id = @$param['transactionid']; /// 订单号 $pay_fee = intval(empty(@$param['payfee']) ? 0 : $param['payfee']); /// 支付金额(分) $from_sign = mb_strtoupper(empty(@$param['fromsign']) ? '' : $param['fromsign'], USEDCHARSET); /// 来源标志 $remark = @$param['remark']; /// 备注 if (empty($agent_id)) { $return->seterrors(ERRORCODE_AGENTIDERROR, ERRORINFO_AGENTIDERROR); return false; } if (empty($channel_id)) { $return->seterrors(ERRORCODE_CHANNELIDERROR, ERRORINFO_CHANNELIDERROR); return false; } if (empty($player_id)) { $return->seterrors(ERRORCODE_PLAYERIDERROR, ERRORINFO_PLAYERIDERROR); return false; } if (empty($change_type)) { $return->seterrors(ERRORCODE_TYPEERROR, ERRORINFO_TYPEERROR); return false; } /// 判断来源 $auth = $this->auth_list->search($from_sign); if (!$auth) { $return->seterrors(ERRORCODE_INVALIDPARAMETER, sprintf(ERRORINFO_INVALIDPARAMETER, 'source sign')); return false; } /// 判断类型 if (!$auth->verify_account_type($change_type)) { $return->seterrors(ERRORCODE_TYPEERROR, ERRORINFO_TYPEERROR); return false; } if (in_array($change_type, [1, 2])) /// 三方购买房卡、金币 { if (empty($pay_fee)) { $return->seterrors(ERRORCODE_ORDERMONEYERROR, ERRORINFO_ORDERMONEYERROR); return false; } if (empty($transaction_id)) { $return->seterrors(ERRORCODE_ORDERIDERROR, ERRORINFO_ORDERIDERROR); return false; } } $this->pdo_begintransaction(); try { /// 校验账户 $cmd = /** @lang text */'select play_roomcard, play_bean from player a where play_agentid = ? and play_channelid = ? and play_playerid = ?'; $ret = $this->pdo_request($cmd, $agent_id, $channel_id, $player_id); if (!$this->pdo_isdone()) throw new Exception($this->geterrorinfo() . '(' . __LINE__ . ')', $this->geterrorcode()); elseif (empty($ret)) throw new Exception(ERRORINFO_PLAYER_NOT_EXISTS, ERRORCODE_PLAYER_NOT_EXISTS); switch ($change_type) { case 1: /// 三方购买房卡 $account = $ret[0]['play_roomcard'] + $change_amount; if ($ret[0]['play_roomcard'] + $change_amount < 0) throw new Exception(ERRORINFO_AMOUNTERROR, ERRORCODE_AMOUNTERROR); $oper_type = 1; break; case 2: /// 三方购买金币 $account = $ret[0]['play_bean'] + $change_amount; if ($ret[0]['play_bean'] + $change_amount < 0) throw new Exception(ERRORINFO_AMOUNTERROR, ERRORCODE_AMOUNTERROR); $oper_type = 11; break; case 101: /// 三方转账房卡 throw new Exception(ERRORINFO_TYPEERROR, ERRORCODE_TYPEERROR); $account = $ret[0]['play_roomcard'] + $change_amount; if ($ret[0]['play_roomcard'] + $change_amount < 0) throw new Exception(ERRORINFO_AMOUNTERROR, ERRORCODE_AMOUNTERROR); $oper_type = 1; break; case 102: /// 三方转账星星 $account = $ret[0]['play_bean'] + $change_amount; if ($ret[0]['play_bean'] + $change_amount < 0) throw new Exception(ERRORINFO_AMOUNTERROR, ERRORCODE_AMOUNTERROR); $oper_type = 11; break; default: /// 其他 throw new Exception(ERRORINFO_TYPEERROR, ERRORCODE_TYPEERROR); break; } if (!empty($game_id) && 102 == $change_type) { if (DEBUG_MODE) { $game_info = $this->game_list->search(self::GAME_ID_TEST); } else { $game_info = $this->game_list->search($game_id); } } else $game_info = null; /// 没有传入游戏id则写入日志表 if (empty($game_info)) { /// 记录同步流水 $cmd = /** @lang text */<<pdo_execute($cmd, $agent_id, $channel_id, $player_id, $oper_type, $change_amount, time()); if (!$ret) throw new Exception($this->geterrorinfo() . '(' . __LINE__ . ')', $this->geterrorcode()); $log_id = $this->pdo_lastinsertid(); } else { $data = array( 'app' => 'youle', 'route' => 'agent', 'rpc' => 0 > $change_amount ? 'coin_sub' : 'coin_add', /// 减少、增加 'data' => array( 'agentid' => $agent_id, 'playerid' => $player_id, 'change' => abs($change_amount), ), ); $result = file_get_contents($game_info->get_address(JsonObjectToJsonString($data), false)); $result = JsonStringToJsonObject(rawurldecode($result)); if (0 == $result->data->result) /// 成功 $account = $result->data->bean; else /// 失败 throw new Exception($result->data->error, ERRORCODE_UNKNOWN); $log_id = 0; } /// 记录购买流水 $cmd = /** @lang text */<<pdo_execute($cmd, $agent_id, $channel_id, $player_id, $transaction_id, $pay_fee, $change_type, $change_amount, $from_sign, $log_id, $remark); if (!$ret) throw new Exception($this->geterrorinfo() . '(' . __LINE__ . ')', $this->geterrorcode()); $this->pdo_commit(); $return->biz_content = array( 'agentid' => $agent_id, 'channelid' => $channel_id, 'playerid' => $player_id, 'account' => $account, ); return true; } catch(Exception $Exception) { $this->pdo_rollback(); $return->seterrors($Exception->getcode(), $Exception->getmessage()); return false; } } }