User.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. <?php
  2. namespace app\api\controller\v2;
  3. use app\api\controller\Api;
  4. use app\common\model\Channel;
  5. use app\common\model\Members;
  6. use app\common\model\MembersTwo;
  7. use app\common\model\Game;
  8. use app\common\model\Subaccount;
  9. use app\common\service\FkStrategiesService;
  10. use app\service\CommonService;
  11. use app\service\GameService;
  12. use think\Cache;
  13. use think\Db;
  14. use think\Env;
  15. use think\Session;
  16. use app\common\model\Setting;
  17. use app\api\library\MemberDevice;
  18. class User extends Api
  19. {
  20. private $_passwordSalt = ''; // 密码加密的盐
  21. private $_encryptMethod = ''; // 密码加密方法
  22. private $_passwordEncrypt = null; // 加密密码
  23. private $_password = null; // 密码明文
  24. /**
  25. * 用户详情
  26. * @throws \think\db\exception\DataNotFoundException
  27. * @throws \think\db\exception\ModelNotFoundException
  28. * @throws \think\exception\DbException
  29. */
  30. public function userInfo()
  31. {
  32. // dump($this->input);
  33. //用户信息
  34. $userInfo = model('Members')->where(['id' => $this->input['userid']])->field('mobile,email,nickname,username,id,imeil,dy_uid')->find();
  35. //实用认证信息
  36. $membersTwoInfo = model('MembersTwo')->where(['userid' => $this->input['userid']])->find();
  37. //游戏信息
  38. $gameInfo = model('Game')->where(['id' => $this->input['gameid']])->find();
  39. $isVisitor = '未认证';
  40. // 游戏账户信息
  41. // $subInfo = model('Subaccount')->where(['game_id' => $this->input['gameid'], 'member_id' => $this->input['userid']])->field('last_imeil')->find();
  42. if ($gameInfo['game_auth_type'] == 1 || $gameInfo['game_auth_type'] == 2) { //中宣部实名认证
  43. $gameAccountInfo = model('Subaccount')->where(['game_id' => $this->input['gameid'], 'member_id' => $this->input['userid']])->find();
  44. if ($gameAccountInfo) {
  45. if ($gameAccountInfo['auth_status'] == 3) {
  46. $membersTwoInfo['realname'] = trim($gameAccountInfo['real_name']);
  47. $membersTwoInfo['idcard'] = trim($gameAccountInfo['idcard_num']);
  48. $isVisitor = '已认证';
  49. } else if ($gameAccountInfo['auth_status'] == 1) {
  50. vendor('authSdk.Authentication', '.class.php');
  51. $auth = new \Authentication();
  52. $result = $auth->query(trim($gameInfo['game_bizid']), $gameAccountInfo['member_id'] . '-' . $gameAccountInfo['id']);
  53. if ($result['errcode'] == 0) {
  54. $resultData = $result['data']['result'];
  55. if ($resultData['status'] == 0 && isset($resultData['pi']) && trim($resultData['pi']) <> '') {
  56. $updAccountData = array();
  57. $updAccountData['auth_type'] = 1;
  58. $updAccountData['auth_status'] = 3;
  59. $updAccountData['auth_pi'] = $resultData['pi'];
  60. $updAccountData['last_query_time'] = time();
  61. $updResult = model('Subaccount')->where(['id' => $gameAccountInfo['id']])->update($updAccountData);
  62. if ($updResult) {
  63. $membersTwoInfo['realname'] = trim($gameAccountInfo['real_name']);
  64. $membersTwoInfo['idcard'] = trim($gameAccountInfo['idcard_num']);
  65. $isVisitor = '已认证';
  66. } else {
  67. $membersTwoInfo['realname'] = '';
  68. $membersTwoInfo['idcard'] = '';
  69. $isVisitor = '未认证';
  70. }
  71. } else if ($resultData['status'] == 1) {
  72. $updAccountData = array();
  73. $updAccountData['auth_type'] = 1;
  74. $updAccountData['last_query_time'] = time();
  75. $updResult = model('Subaccount')->where(['id' => $gameAccountInfo['id']])->update($updAccountData);
  76. $membersTwoInfo['realname'] = trim($gameAccountInfo['real_name']);
  77. $membersTwoInfo['idcard'] = trim($gameAccountInfo['idcard_num']);
  78. $isVisitor = '未认证';
  79. } else if ($resultData['status'] == 2) {
  80. $updAccountData = array();
  81. $updAccountData['auth_type'] = 1;
  82. $updAccountData['auth_status'] = 2;
  83. $updAccountData['last_query_time'] = time();
  84. $updResult = model('Subaccount')->where(['id' => $gameAccountInfo['id']])->update($updAccountData);
  85. $membersTwoInfo['realname'] = '';
  86. $membersTwoInfo['idcard'] = '';
  87. $isVisitor = '未认证';
  88. }
  89. }
  90. } else {
  91. $isVisitor = '未认证';
  92. // if (empty($userInfo['mobile']) && empty($userInfo['email'])) {
  93. // $isVisitor = '游客';
  94. // } else {
  95. // $isVisitor = '已认证';
  96. // }
  97. }
  98. } else {
  99. $isVisitor = '未认证';
  100. }
  101. } else { //平台实名认证
  102. if ($membersTwoInfo['realname'] && $membersTwoInfo['idcard']) {
  103. $isVisitor = '已认证';
  104. } else {
  105. $isVisitor = '未认证';
  106. }
  107. }
  108. if ($userInfo['mobile']) {
  109. $userInfo['mobile'] = substr_replace($userInfo['mobile'], '****', 3, 4);
  110. }
  111. if ($membersTwoInfo['realname'] && $membersTwoInfo['idcard']) {
  112. $userInfo['realname'] = mb_substr($membersTwoInfo['realname'], 0, 1, "UTF-8") . '**';
  113. $userInfo['idcard'] = substr_replace($membersTwoInfo['idcard'], '*************', 3, 13);
  114. } else {
  115. $userInfo['realname'] = $userInfo['idcard'] = '';
  116. }
  117. $userInfo['isVisitor'] = $isVisitor;
  118. // $kefu = model('common/Kefu')->getKefuList();
  119. $kefuList = $this->getKefuList($gameInfo['id']);
  120. $result = [
  121. 'userInfo' => $userInfo,
  122. 'm_url' => MOBILE_SITE_DOMAIN,
  123. 'customer_service' => $kefuList,
  124. 'is_mobile' => 2, // 绑定手机号弹框是否隐藏“跳过”按钮:1=展示(默认)、2=隐藏【绑定手机号弹框 的“跳过”按钮】
  125. 'is_new_imei' => 1, // 是否新设备:1=否、2=是【效验弹框】
  126. 'is_bind_mobile' => 1, // 绑定手机号弹框是否隐藏:1=展示(默认)、2=隐藏【绑定手机号弹框】
  127. 'handle_num' => 0, // 用于展示当前手机号绑定逻辑的处理标识序号
  128. ];
  129. // 有手机号不进行绑定
  130. if(!empty($userInfo['mobile'])){
  131. $result['is_bind_mobile'] = 2;
  132. }
  133. // ## 针对 v3.6.0 以上版本进行全新的手机号绑定/校验拦截处理(隔离老版本逻辑)
  134. $isWhitelisted = false;
  135. $whitelistConfig = (new Setting())->getSetting('game_channel_by_mobild_whitelist');
  136. if (!empty($whitelistConfig)) {
  137. $config = json_decode($whitelistConfig, true);
  138. // 1. 匹配游戏
  139. $gameMatch = false;
  140. if ($config['game_ids'] === 'all') {
  141. $gameMatch = true;
  142. } else {
  143. $gameIds = explode(',', $config['game_ids']);
  144. if (in_array($this->input['gameid'], $gameIds)) {
  145. $gameMatch = true;
  146. }
  147. }
  148. // 2. 匹配渠道(智能层级继承判定)
  149. $channelMatch = false;
  150. if ($gameMatch == false) {
  151. if ($config['channel_ids'] === 'all') {
  152. $channelMatch = true;
  153. } else {
  154. $whitelistChannelIds = explode(',', $config['channel_ids']);
  155. // 获取当前用户的渠道及继承链
  156. $userChannel = Db::name('nw_channel')
  157. ->where('id', $this->input('channel_id'))
  158. ->field('id, id_path')
  159. ->find();
  160. if ($userChannel) {
  161. $userPaths = array_filter(explode(',', $userChannel['id_path']));
  162. $userPaths[] = $userChannel['id']; // 把自身也包含进去
  163. if (!empty(array_intersect($userPaths, $whitelistChannelIds))) {
  164. $channelMatch = true;
  165. }
  166. }
  167. }
  168. }
  169. if ($gameMatch || $channelMatch) {
  170. $isWhitelisted = true;
  171. }
  172. }
  173. // 设置初始情况:
  174. $result['is_mobile'] = 2; // 隐藏跳过(强制绑定)
  175. $result['is_new_imei'] = 1; // 隐藏设备校验
  176. $result['is_bind_mobile'] = 2; // 隐藏绑定弹框
  177. $result['handle_num'] = 10;
  178. // 3. 执行高版本新规则覆盖
  179. if ($isWhitelisted) {
  180. // 已匹配白名单配置:隐藏手机号弹窗、效验弹框
  181. $result['is_mobile'] = 2; // 展示跳过
  182. $result['is_new_imei'] = 1; // 隐藏设备校验弹框
  183. $result['is_bind_mobile'] = 2; // 隐藏绑定弹框
  184. $result['handle_num'] = 11;
  185. } else {
  186. // 未匹配白名单配置
  187. if (empty($userInfo['mobile'])) {
  188. // 未绑定手机号:只弹出 [绑定手机号] 弹窗
  189. $result['is_mobile'] = 2; // 隐藏跳过(强制绑定)
  190. $result['is_new_imei'] = 1; // 展示设备校验弹框
  191. $result['is_bind_mobile'] = 1; // 展示绑定弹框
  192. $result['handle_num'] = 12;
  193. } else {
  194. // 已绑定手机号:切换设备登录则弹出 [校验手机号] 弹窗
  195. $memberDevice = new MemberDevice();
  196. $isRecentDevice = $memberDevice->isRecentDevice(
  197. $this->input['userid'],
  198. $this->input['gameid'],
  199. $this->input('imeil')
  200. );
  201. if (!$isRecentDevice) {
  202. $result['is_mobile'] = 2; // 隐藏跳过(强制绑定)
  203. $result['is_new_imei'] = 2; // 展示弹出设备校验弹框
  204. $result['is_bind_mobile'] = 2; // 隐藏绑定弹框
  205. $result['handle_num'] = 13;
  206. }
  207. }
  208. }
  209. $clientVersion = str_ireplace('v', '', $this->input('version'));
  210. if (!empty($clientVersion) && version_compare($clientVersion, '3.6.5', '<')) {
  211. // ## 老版本说明 ##
  212. // $result['is_mobile'] = 2; // 隐藏跳过(强制绑定)【老版本:2=开启弹框】
  213. // $result['is_new_imei'] = 1; // 隐藏设备校验【老版本:2=开启弹框】
  214. if($result['is_mobile'] == 2 && $isWhitelisted == true){
  215. $result['is_mobile'] = 1; // 老版本兼容:展示跳过
  216. }
  217. }
  218. $result['system_message_count'] = model('SystemMessage')
  219. ->where('is_show', 1)
  220. ->where('member_id', $this->input['userid'])
  221. ->count();
  222. $this->jsonResult($result, 1, '获取成功');
  223. }
  224. /**
  225. * 获取相关游戏的客服,没有则获取公共客服
  226. * @param $game_id 游戏ID
  227. *
  228. * @return mixed
  229. */
  230. private function getKefuList($game_id = '')
  231. {
  232. $list = model('common/Kefu')->getKefuByGameId(['game_id' => $game_id]);
  233. if (!$list) {
  234. $list = model('common/Kefu')->getKefuByGameId(['game_id' => 0]);
  235. }
  236. return $list;
  237. }
  238. /**
  239. * 修改密码
  240. *
  241. * @throws \think\db\exception\DataNotFoundException
  242. * @throws \think\db\exception\ModelNotFoundException
  243. * @throws \think\exception\DbException
  244. */
  245. public function updatePwd()
  246. {
  247. $checkResult = $this->validate(
  248. $this->input,
  249. [
  250. ['oldpassword', 'require|min:6|max:15', '密码不能为空|密码最少6位字符最多15个字符|密码最少6位字符最多15个字符'],
  251. ['password', 'require|min:6|max:15', '密码不能为空|密码最少6位字符最多15个字符|密码最少6位字符最多15个字符'],
  252. ['repassword', 'require|confirm:password', '密码不能为空|两次输入的密码不一致'],
  253. ]
  254. );
  255. if (true !== $checkResult) {
  256. $this->jsonResult('', 0, $checkResult, 'json');
  257. }
  258. $data['oldpassword'] = $this->input['oldpassword'];
  259. $data['password'] = $this->input['password'];
  260. $data['repassword'] = $this->input['repassword'];
  261. if ($data['oldpassword'] == $data['password']) $this->jsonResult([], 0, '新密码不能与旧密码相同');
  262. $info = model('Members')->field('id,username,email,mobile,password')->where(["id" => $this->input['userid'], 'flag' => 0])->find();
  263. $this->_password = $data['oldpassword'];
  264. $this->_passwordEncrypt = $this->getPassword();
  265. if ($this->_passwordEncrypt != $info['password']) $this->jsonResult([], 0, '输入的旧密码错误');
  266. $this->_password = $data['password'];
  267. $this->_passwordEncrypt = '';
  268. $this->_passwordEncrypt = $this->getPassword();
  269. $res = model('Members')->save(['password' => $this->_passwordEncrypt], ['id' => $this->input['userid']]);
  270. model('MemberHistory')->insertGetId(['password' => $this->_passwordEncrypt, 'userid' => $this->input['userid'], 'ip' => request()->ip(), 'create_time' => NOW_TIMESTAMP]);
  271. if ($res) {
  272. $this->jsonResult([], 1, '修改成功');
  273. }
  274. $this->jsonResult([], 0, '修改失败');
  275. }
  276. /**
  277. * 绑定手机号-获取验证码
  278. * @throws \think\db\exception\DataNotFoundException
  279. * @throws \think\db\exception\ModelNotFoundException
  280. * @throws \think\exception\DbException
  281. */
  282. public function getBindPhoneCode()
  283. {
  284. $checkResult = $this->validate($this->input, [
  285. ['type', 'require|integer|in:1,2', '类型不能为空|请输入类型|请输入类型'], // 1 绑定手机 2换绑手机
  286. ['phone', 'require|integer|length:11', '手机号不能为空|请输入正确的手机号|请输入正确的手机号'],
  287. ]);
  288. if (true !== $checkResult) {
  289. $this->jsonResult('', 0, $checkResult, 'json');
  290. }
  291. if (isset($this->input['captcha'], $this->input['random']) && $this->input['captcha'] && $this->input['random']) {
  292. $captcha = new \app\common\library\Captcha();
  293. if (!$captcha->check($this->input['captcha'], $this->input['random'])) {
  294. $this->jsonResult('', 0, '图形验证码错误', 'json');
  295. }
  296. }
  297. if (isVirtualMobile($this->input['phone'])) {
  298. $this->jsonResult('', 0, '禁止使用虚拟手机号!');
  299. }
  300. $info = model('Members')->field('id,username,email,mobile')->where(["id" => $this->input['userid'], 'flag' => 0])->find();
  301. if (!$info) {
  302. $this->jsonResult([], 0, '账号不存在');
  303. }
  304. if ($info['mobile'] && $this->input['type'] == 1) {
  305. $this->jsonResult([], 0, '已绑定手机号');
  306. } else {
  307. if ($info['mobile'] == $this->input['phone']) {
  308. $this->jsonResult([], 0, '换绑手机号不能与原手机号一样');
  309. }
  310. }
  311. $result = (new \app\common\library\Sms)->sendCode($this->input['phone'], config('ALI_SMS.bindMobile'));
  312. if (isset($result) && $result['status']) {
  313. $this->jsonResult([], 1, '发送成功');
  314. } else {
  315. $this->jsonResult([], 0, $result['msg']);
  316. }
  317. }
  318. // 新设备手机号验证码获取
  319. public function getNewImeiCode()
  320. {
  321. $checkResult = $this->validate($this->input, [
  322. ['captcha', 'require', '图形验证码有误!'],
  323. ['random', 'require', '图形验证码标识有误!'],
  324. ]);
  325. if (true !== $checkResult) {
  326. $this->jsonResult('', 0, $checkResult, 'json');
  327. }
  328. if (isset($this->input['captcha'], $this->input['random']) && $this->input['captcha'] && $this->input['random']) {
  329. $captcha = new \app\common\library\Captcha();
  330. if (!$captcha->check($this->input['captcha'], $this->input['random'])) {
  331. $this->jsonResult('', 0, '图形验证码错误', 'json');
  332. }
  333. }
  334. $mobile = model('Members')->where(["id" => $this->input['userid'], 'flag' => 0])->value('mobile');
  335. if (!$mobile) {
  336. $this->jsonResult([], 0, '当前账户不存在或者未绑定手机号');
  337. }
  338. $result = (new \app\common\library\Sms)->sendCode($mobile, config('ALI_SMS.bindMobile'));
  339. if (isset($result) && $result['status']) {
  340. $this->jsonResult([], 1, '发送成功');
  341. } else {
  342. $this->jsonResult([], 0, $result['msg']);
  343. }
  344. }
  345. // 新设备验证手机号验证码
  346. public function newImeilValid()
  347. {
  348. $code = $this->input('code');
  349. if (empty($code)) {
  350. $this->jsonResult('', 0, '请输入验证码!');
  351. }
  352. if (!$this->input['imeil']) {
  353. $this->jsonResult([], 0, '操作异常!!!');
  354. }
  355. $mobile = model('Members')->where(["id" => $this->input['userid'], 'flag' => 0])->value('mobile');
  356. if (!$mobile) {
  357. $this->jsonResult([], 0, '当前账户不存在或者未绑定手机号');
  358. }
  359. $codeResult = (new \app\common\library\Sms)->checkCode($mobile, $code);
  360. if (!$codeResult['status']) {
  361. $this->jsonResult('', 0, $codeResult['msg']);
  362. }
  363. $times = NOW_TIMESTAMP;
  364. $result = model('Members')->save(['imeil' => $this->input['imeil'], 'update_time' => $times], ['id' => $this->input['userid']]);
  365. if (!$result) {
  366. $this->jsonResult('', 0, '效验失败!');
  367. }
  368. $subResult = (new Subaccount())->where(['game_id' => $this->input['gameid'], 'member_id' => $this->input['userid']])->update(['update_time' => $times, "last_imeil" => $this->input['imeil']]);
  369. if (!$subResult) {
  370. $this->jsonResult('', 0, '效验处理失败!');
  371. }
  372. // 验证成功后,将新设备添加到常用设备列表(强制替换最旧设备)
  373. try {
  374. $memberDevice = new MemberDevice();
  375. $memberDevice->addDevice(
  376. $this->input['userid'],
  377. $this->input['gameid'],
  378. $this->input['imeil'],
  379. $this->input('device', 0),
  380. true // 强制替换
  381. );
  382. } catch (\Exception $e) {
  383. // 设备记录更新失败不影响验证流程
  384. trace('设备记录更新失败:' . $e->getMessage(), 'error');
  385. }
  386. $this->jsonResult('', 1, 'success');
  387. }
  388. /**
  389. * 绑定手机号
  390. * @throws \think\db\exception\DataNotFoundException
  391. * @throws \think\db\exception\ModelNotFoundException
  392. * @throws \think\exception\DbException
  393. */
  394. public function bindPhone()
  395. {
  396. $checkResult = $this->validate(
  397. $this->input,
  398. [
  399. ['gameid', 'require', '游戏ID不能为空'],
  400. ['imeil', 'require', '设备号不能为空'],
  401. ['type', 'require|integer|in:1,2', '类型不能为空|类型错误|类型错误'],
  402. ['code', 'require|integer|length:6', '验证码不能为空|请输入验证码|请输入验证码'],
  403. ['phone', 'require|integer|length:11', '手机号不能为空|请输入正确的手机号|请输入正确的手机号'],
  404. // ['password', 'requireIf:type,2|min:6|max:15', '密码不能为空|密码最少6位字符最多15个字符|密码最少6位字符最多15个字符'],
  405. ]
  406. );
  407. if (true !== $checkResult) {
  408. $this->jsonResult('', 0, $checkResult, 'json');
  409. }
  410. $data['type'] = $this->input['type'];
  411. $data['code'] = $this->input['code'];
  412. $data['phone'] = $this->input['phone'];
  413. $info = model('Members')->field('id,username,email,mobile,password')->where(["id" => $this->input['userid'], 'flag' => 0])->find();
  414. if (!$info) {
  415. $this->jsonResult([], 0, '用户信息不存在');
  416. }
  417. if ($info['mobile']) {
  418. $this->jsonResult([], 0, '已绑定手机号');
  419. }
  420. if ($data['type'] == 2) {
  421. if (empty($this->input['password'])) {
  422. $this->jsonResult([], 0, '密码不能为空');
  423. }
  424. $data['password'] = $this->input['password'];
  425. $this->_password = $data['password'];
  426. $this->_passwordEncrypt = $this->getPassword();
  427. if ($this->_passwordEncrypt != $info['password']) {
  428. $this->jsonResult([], 0, '密码错误');
  429. }
  430. }
  431. $result = (new \app\common\library\Sms)->checkCode($data['phone'], $data['code']);
  432. if (isset($result) && $result['status']) {
  433. $memberResult = model('Members')->where('id', $this->input['userid'])->update(['mobile' => $data['phone'], 'imeil' => $this->input['imeil'], 'update_time' => time()]);
  434. $historyResult = model('MemberHistory')->insertGetId(['mobile' => $data['phone'], 'userid' => $this->input['userid'], 'ip' => request()->ip(), 'create_time' => NOW_TIMESTAMP]);
  435. $subResult = (new Subaccount())->where(['game_id' => $this->input['gameid'], 'member_id' => $this->input['userid']])->update(['update_time' => NOW_TIMESTAMP, "last_imeil" => $this->input['imeil']]);
  436. // 绑定成功后,将当前设备添加到常用设备列表
  437. if($memberResult && $historyResult && $subResult){
  438. try {
  439. $memberDevice = new MemberDevice();
  440. $memberDevice->addDevice(
  441. $this->input['userid'],
  442. $this->input['gameid'],
  443. $this->input['imeil'],
  444. $this->input('device', 0)
  445. );
  446. } catch (\Exception $e) {
  447. // 设备记录更新失败不影响绑定流程
  448. trace('设备记录更新失败:' . $e->getMessage(), 'error');
  449. }
  450. $this->jsonResult([], 1, '绑定成功');
  451. }
  452. $this->jsonResult([], 0, '绑定失败!');
  453. }
  454. $this->jsonResult([], 0, $result['msg']);
  455. }
  456. /**
  457. * 换绑手机号-原手机号验证码获取
  458. * @throws \think\db\exception\DataNotFoundException
  459. * @throws \think\db\exception\ModelNotFoundException
  460. * @throws \think\exception\DbException
  461. */
  462. public function unbindingPhoneCode()
  463. {
  464. if (isset($this->input['captcha'], $this->input['random']) && $this->input['captcha'] && $this->input['random']) {
  465. $captcha = new \app\common\library\Captcha();
  466. if (!$captcha->check($this->input['captcha'], $this->input['random'])) {
  467. $this->jsonResult('', 0, '验证码错误', 'json');
  468. }
  469. }
  470. $info = model('Members')->field('id,username,email,mobile')->where(["id" => $this->input['userid'], 'flag' => 0])->find();
  471. if (!$info) {
  472. $this->jsonResult([], 0, '手机号不存在');
  473. }
  474. if (!$info['mobile']) {
  475. $this->jsonResult([], 0, '手机号不存在');
  476. }
  477. $result = (new \app\common\library\Sms)->sendCode($info['mobile'], config('ALI_SMS.bindMobileVLMobile'));
  478. if (isset($result) && $result['status']) {
  479. $this->jsonResult([], 1, '发送成功');
  480. } else {
  481. $this->jsonResult([], 0, $result['msg']);
  482. }
  483. }
  484. /**
  485. * 换绑原手机验证码验证
  486. * @throws \think\db\exception\DataNotFoundException
  487. * @throws \think\db\exception\ModelNotFoundException
  488. * @throws \think\exception\DbException
  489. */
  490. public function checkUnbindingPhoneCode()
  491. {
  492. $checkResult = $this->validate(
  493. $this->input,
  494. [
  495. ['code', 'require|integer|length:6', '验证码不能为空|请输入验证码|请输入验证码'],
  496. ]
  497. );
  498. if (true !== $checkResult) {
  499. $this->jsonResult('', 0, $checkResult, 'json');
  500. }
  501. $data['code'] = $this->input['code'];
  502. $info = model('Members')->field('id,username,email,mobile')->where(["id" => $this->input['userid'], 'flag' => 0])->find();
  503. if (!$info) {
  504. $this->jsonResult([], 0, '手机号不存在');
  505. }
  506. $result = (new \app\common\library\Sms)->checkCode($info['mobile'], $data['code']);
  507. if (isset($result) && $result['status']) {
  508. $cacheStr = md5('v2:User:checkUnbindingPhoneCode:phone:' . $info['mobile'] . '_' . time());
  509. Cache::store('default')->set('v2:User:checkUnbindingPhoneCode:' . $cacheStr, $info['id'], 15 * 60);
  510. $res = [
  511. 'checkToken' => $cacheStr
  512. ];
  513. $this->jsonResult($res, 1, '发送成功');
  514. } else {
  515. $this->jsonResult([], 0, $result['msg']);
  516. }
  517. }
  518. /**
  519. * 换绑手机号
  520. * @throws \think\db\exception\DataNotFoundException
  521. * @throws \think\db\exception\ModelNotFoundException
  522. * @throws \think\exception\DbException
  523. */
  524. public function unbindingPhone()
  525. {
  526. $checkResult = $this->validate(
  527. $this->input,
  528. [
  529. ['checkToken', 'require', 'token不能为空'],
  530. ['code', 'require|integer|length:6', '验证码不能为空|请输入验证码|请输入验证码'],
  531. ['phone', 'require|integer|length:11', '手机号不能为空|请输入正确的手机号|请输入正确的手机号'],
  532. ]
  533. );
  534. if (true !== $checkResult) {
  535. $this->jsonResult('', 0, $checkResult, 'json');
  536. }
  537. $data['checkToken'] = $this->input['checkToken'];
  538. $data['code'] = $this->input['code'];
  539. $data['phone'] = $this->input['phone'];
  540. $id = Cache::store('default')->get('v2:User:checkUnbindingPhoneCode:' . $data['checkToken']);
  541. if (!$id) {
  542. $this->jsonResult([], 0, '验证信息已过期,请重新发起验证');
  543. }
  544. $info = model('Members')->field('id,username,email,mobile')->where(["id" => $this->input['userid'], 'flag' => 0])->find();
  545. if (!$info) {
  546. $this->jsonResult([], 0, '手机号不存在');
  547. }
  548. $result = (new \app\common\library\Sms)->checkCode($data['phone'], $data['code']);
  549. if (isset($result) && $result['status']) {
  550. model('Members')->save(['mobile' => $data['phone']], ['id' => $this->input['userid']]);
  551. model('MemberHistory')->insertGetId(['mobile' => $info['mobile'] . ' 改为 ' . $data['phone'], 'userid' => $this->input['userid'], 'ip' => request()->ip(), 'create_time' => NOW_TIMESTAMP]);
  552. $this->jsonResult([], 1, '绑定成功');
  553. }
  554. $this->jsonResult([], 0, $result['msg']);
  555. }
  556. /**
  557. * 获取加密密码
  558. * @return false|string
  559. */
  560. public function getPassword()
  561. {
  562. $password = (string)$this->_passwordEncrypt;
  563. if (empty($password)) {
  564. switch (strtoupper($this->_encryptMethod)) {
  565. case 'MD5':
  566. $password = $this->_md5Code($this->_password, $this->_passwordSalt);
  567. break;
  568. default:
  569. $password = $this->_authCode($this->_password, $this->_passwordSalt);
  570. break;
  571. }
  572. $this->_passwordEncrypt = $password;
  573. }
  574. return $password;
  575. }
  576. /**
  577. * 账号验证
  578. */
  579. public function verifyUserName()
  580. {
  581. $checkResult = $this->validate(
  582. $this->input,
  583. [
  584. ['username', 'require', '账号不能为空'],
  585. ]
  586. );
  587. $data['username'] = $this->input['username']; //游戏id
  588. if (true !== $checkResult) {
  589. $this->jsonResult('', 0, $checkResult, 'json');
  590. }
  591. $user = (new Members())->getUserName($data);
  592. if ($user) {
  593. $this->jsonResult($user, 1, '成功');
  594. } else {
  595. $this->jsonResult([], 0, '账号不存在');
  596. }
  597. }
  598. private function _md5Code($password, $salt = '')
  599. {
  600. return md5($password . $salt);
  601. }
  602. private function _authCode($password, $salt = '')
  603. {
  604. return auth_code($password, 'ENCODE', $salt);
  605. }
  606. /**
  607. * 实名认证
  608. */
  609. public function personalIdentity()
  610. {
  611. $checkResult = $this->validate($this->input, [
  612. ['realname', ['require', 'length' => ':2,100', 'regex' => "/^[\p{L}\p{M}\p{N}'\-·.\s]{2,100}$/u"], '请输入姓名|姓名最少两位以上|姓名格式有误'],
  613. // '请输入姓名|姓名只能是2-10位的汉字|姓名只能是2-10位的汉字'],
  614. ['idcard', 'require|validateIDCard', '请输入身份证号码|身份证号码格式不正确'],
  615. ]);
  616. if (true !== $checkResult) {
  617. $this->jsonResult('', 0, $checkResult, 'json');
  618. }
  619. $data = [
  620. 'realname' => $this->input['realname'],
  621. 'idcard' => $this->input['idcard'],
  622. 'update_time' => time()
  623. ];
  624. $member_id = $this->input['userid'];
  625. // 通过身份证验证年龄
  626. if (!isMeetAgeByIDCard($data['idcard'], 18, 200)) $this->jsonResult([], 0, '您未满足年龄要求(18岁),无法通过认证');
  627. $gameInfo = (new Game())->where(['id' => $this->input['gameid']])->find();
  628. $memberRes = model('MembersTwo')->updateInfo($data, $member_id);
  629. // FIXME: 封禁某个实名信息的账户使用 - 处理实名后的账户封禁
  630. if ($this->input['idcard'] == '440105199806235432') {
  631. return $this->jsonResult('', 0, '认证失败,当前账户已被封禁!');
  632. }
  633. $membersTwoModel = new MembersTwo();
  634. // 中宣部实名认证
  635. if ($gameInfo['game_auth_type'] == 1) {
  636. if (!trim($gameInfo['game_bizid'])) {
  637. return $this->jsonResult('', 0, '该游戏未配置游戏备案识别码');
  638. }
  639. $gameAccountInfo = model('Subaccount')->where(['game_id' => $this->input['gameid'], 'member_id' => $member_id])->find();
  640. if ($gameAccountInfo) {
  641. if ($gameAccountInfo['auth_status'] <> 3) {
  642. vendor('authSdk.Authentication', '.class.php');
  643. $auth = new \Authentication();
  644. $result = $auth->check(trim($gameInfo['game_bizid']), $this->input['gameid']. '-' .$gameAccountInfo['member_id'] . '-' . $gameAccountInfo['id'], $data['realname'], $data['idcard']);
  645. if ($result['errcode'] <> 0) {
  646. if ($result['errcode'] == 2004) {
  647. return $this->jsonResult('', 0, '不能频繁调用中宣部实名认证接口,请稍后再重新发起认证');
  648. } else {
  649. return $this->jsonResult('', 0, '调用接口异常:' . $result['errmsg']);
  650. }
  651. } else {
  652. $resultData = $result['data']['result'];
  653. if ($resultData['status'] == 0) {
  654. $updAccountData = array();
  655. $updAccountData['auth_type'] = 1;
  656. $updAccountData['real_name'] = trim($data['realname']);
  657. $updAccountData['idcard_num'] = trim($data['idcard']);
  658. $updAccountData['auth_status'] = 3;
  659. $updAccountData['auth_pi'] = $resultData['pi'];
  660. $updAccountData['last_auth_time'] = time();
  661. $updResult = model('Subaccount')->where(['id' => $gameAccountInfo['id']])->update($updAccountData);
  662. // 更新用户扩展信息的实名信息
  663. $membersTwoModel->update($data, ['userid' => $member_id]);
  664. // 插入玩家历史记录
  665. Db::table('cy_member_history')->insert([
  666. 'userid' => $member_id,
  667. 'password' => $data['realname'] . ' - ' . $data['idcard'] . ' - ' . $this->input['username'],
  668. 'mobile' => '',
  669. 'ip' => request()->ip(),
  670. 'create_time' => time(),
  671. ]);
  672. if ($updResult) {
  673. $mark = $this->checkPlayLogin($this->input['idcard']);
  674. return $this->jsonResult(["mark" => $mark], 1, '认证成功');
  675. } else {
  676. return $this->jsonResult('', 0, '实名认证结果保存异常');
  677. }
  678. } else if ($resultData['status'] == 1) {
  679. $updAccountData = array();
  680. $updAccountData['auth_type'] = 1;
  681. $updAccountData['real_name'] = trim($data['realname']);
  682. $updAccountData['idcard_num'] = trim($data['idcard']);
  683. $updAccountData['auth_status'] = 1;
  684. $updAccountData['auth_pi'] = $resultData['pi'];
  685. $updAccountData['last_auth_time'] = time();
  686. $updResult = model('Subaccount')->where(['id' => $gameAccountInfo['id']])->update($updAccountData);
  687. if ($updResult) {
  688. $mark = $this->checkPlayLogin($this->input['idcard']);
  689. return $this->jsonResult(["mark" => $mark], 2, '您的实名认证请求已提交审核,请耐心等待认证结果');
  690. } else {
  691. return $this->jsonResult('', 0, '您的实名认证请求已提交审核,保存异常');
  692. }
  693. } else {
  694. return $this->jsonResult('', 0, '未通过实名认证');
  695. }
  696. }
  697. } else {
  698. $mark = $this->checkPlayLogin($this->input['idcard']);
  699. // 处理游戏绑定渠道管理
  700. (new CommonService())->handleBelongToBinding($this->input['userid'], $this->input['member_channel_id'], $this->input['gameid'], $this->input['idcard'], $this->input['realname']);
  701. return $this->jsonResult(["mark" => $mark], 1, '您已实名认证成功');
  702. }
  703. } else {
  704. return $this->jsonResult('', 0, '您尚未创建游戏账号');
  705. }
  706. }
  707. // 通过上级调用中宣部认证
  708. else if ($gameInfo['game_auth_type'] == 2) {
  709. $gameAccountInfo = model('Subaccount')->where(['game_id' => Session::get('game_id'), 'member_id' => $member_id])->find();
  710. if ($gameAccountInfo) {
  711. return $this->jsonResult('', 0, '该认证方式尚未开放');
  712. } else {
  713. return $this->jsonResult('', 0, '您尚未创建游戏账号');
  714. }
  715. }
  716. // 平台实名认证
  717. else {
  718. //实名认证数据更新
  719. if ($membersTwoModel->where(['userid' => $member_id])->find()) {
  720. $flag = $membersTwoModel->update($data, ['userid' => $member_id]);
  721. } else {
  722. $data['userid'] = $member_id;
  723. $data['username'] = $this->input['username'];
  724. $data['create_time'] = time();
  725. $flag = $membersTwoModel->insert($data);
  726. }
  727. // 插入玩家历史记录
  728. Db::table('cy_member_history')->insert([
  729. 'userid' => $member_id,
  730. 'password' => $data['realname'] . ' - ' . $data['idcard'] . ' - ' . $this->input['username'],
  731. 'mobile' => '',
  732. 'ip' => request()->ip(),
  733. 'create_time' => time(),
  734. ]);
  735. if ($flag) {
  736. $mark = $this->checkPlayLogin($this->input['idcard'], '', 'trim');
  737. // 处理游戏绑定渠道管理
  738. $handleResult = (new CommonService())->handleBelongToBinding($this->input['userid'], $this->input['member_channel_id'], $this->input['gameid'], $this->input['idcard'], $this->input['realname']);
  739. return $this->jsonResult(["mark" => $mark, 'handle' => $handleResult], 1, '认证成功');
  740. } else {
  741. return $this->jsonResult('', 0, '认证失败');
  742. }
  743. }
  744. if ($memberRes) {
  745. $this->jsonResult($memberRes, 1, '成功');
  746. }
  747. $this->jsonResult('', 0, '认证失败');
  748. }
  749. /***
  750. * 检测是否成年
  751. */
  752. public function checkPlayLogin($idcard)
  753. {
  754. $flag = 0;
  755. if (isMeetAgeByIDCard($idcard, 12, 18)) {
  756. $flag = 1;
  757. }
  758. return $flag;
  759. }
  760. // 常见问题列表
  761. public function problem()
  762. {
  763. $checkResult = $this->validate(
  764. $this->input,
  765. [
  766. ['page', 'require|integer|egt:1', '页数不能为空|页数必须是整数|页数必须大于1'],
  767. ['pageSize', 'require|integer|egt:10', '页码不能为空|页码必须是整数|页码必须大于10'],
  768. ]
  769. );
  770. if (true !== $checkResult) {
  771. $this->jsonResult('', 0, $checkResult);
  772. }
  773. $data['page'] = $this->input['page'];
  774. $data['pageSize'] = $this->input['pageSize'];
  775. $list = model('CpsProblem')->alias('a')
  776. ->field('id,title,answer')
  777. ->order('order asc, create_time asc')
  778. ->paginate(['list_rows' => $data['pageSize'], 'page' => $data['page']])
  779. ->toArray();
  780. $this->jsonResult($list, 1, '获取成功');
  781. }
  782. /**
  783. * 心跳获取
  784. *
  785. * @return void
  786. */
  787. public function heartbeat()
  788. {
  789. $this->jsonResult([], 1, '上传成功');
  790. }
  791. /**
  792. * 获取176的渠道推广信息
  793. *
  794. * @return void
  795. * @throws \think\db\exception\DataNotFoundException
  796. * @throws \think\db\exception\ModelNotFoundException
  797. * @throws \think\exception\DbException
  798. */
  799. public function getYqlChannel()
  800. {
  801. $setInfo = model('Common/Setting')->where(['name' => 'yql_tg_value'])->value('value');
  802. $result = ['tg_url' => '', 'value' => $setInfo];
  803. if (model('Common/Setting')->where(['name' => 'yql_tg_status'])->value('value') == 0) {
  804. return $this->jsonResult($result, 1, '未开启176推广');
  805. }
  806. $channel_id = $this->input('channel_id');
  807. $yql_id = (new Channel())->where(['id' => $channel_id, 'status' => 1, 'yql_id' => ['<>', 0]])->value('yql_id');
  808. if (empty($yql_id)) {
  809. return $this->jsonResult($result, 1, '当前渠道所属的176的推广信息为空');
  810. }
  811. $app_url = Env::get("yql.app_url");
  812. $app_hash_key = Env::get("yql.app_hash_key");
  813. $code = strEncrypt($yql_id, $app_hash_key);
  814. $result['tg_url'] = $app_url . "#/pages/invite/invite?cid=" . $code;
  815. $this->jsonResult($result, 1, 'success');
  816. }
  817. // 获取专属客服
  818. public function getChannelCall()
  819. {
  820. // $channel_id = $this->input('channel_id'); // 渠道ID(客户端传入)
  821. $channel_id = $this->input('member_channel_id'); // 渠道ID(当前账户所属渠道)
  822. $game_id = $this->input('gameid');
  823. $result = [
  824. "notice" => "",
  825. "wx_qr_code" => "",
  826. "wx_kefu_url" => "",
  827. ];
  828. // 查询专属客服(type=2)且启用(status=1)
  829. $res = db('cy_kefu')
  830. ->field('id, nickname, notice, wx_qr_code, wx_kefu_url')
  831. ->where('status', 1)
  832. ->where('type', 2)
  833. ->where(function ($query) use ($game_id, $channel_id) {
  834. // 情况1:同时匹配 game 和 channel
  835. $query->whereRaw("FIND_IN_SET('{$game_id}', game_id) AND FIND_IN_SET('{$channel_id}', channel_id)")
  836. // 情况2:只匹配 channel(排除游戏未设置的)
  837. ->whereOrRaw("FIND_IN_SET('{$channel_id}', channel_id) AND game_id=0")
  838. // 情况3:默认配置
  839. ->whereOr('is_default', 2);
  840. })
  841. ->orderRaw("
  842. (FIND_IN_SET('{$game_id}', game_id) AND FIND_IN_SET('{$channel_id}', channel_id)) DESC,
  843. (FIND_IN_SET('{$channel_id}', channel_id) AND game_id=0) DESC,
  844. (`is_default` = 2) DESC,
  845. id DESC
  846. ")
  847. ->find();
  848. if ($res) {
  849. $result = $res;
  850. }
  851. $this->jsonResult(['info' => $result], 1, '获取成功');
  852. }
  853. }