Login.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\model\UserFacility;
  4. use app\common\model\UserGroup;
  5. use app\common\model\UserLevelRank;
  6. use app\common\model\UserLoginLog;
  7. use app\common\validate\UserVali;
  8. use app\common\model\User;
  9. use app\common\model\UserWallet;
  10. use Elasticsearch\Endpoints\License\Post;
  11. use library\service\CaptchaService;
  12. use library\tools\Data;
  13. use think\cache\driver\Redis;
  14. use think\Db;
  15. use EasyWeChat\Factory;
  16. use app\common\model\InviteInfo;
  17. use function AlibabaCloud\Client\value;
  18. /**
  19. * @title 用户登录
  20. * @controller Login
  21. */
  22. class Login extends Base
  23. {
  24. // 需要登录的
  25. protected $need_login = [
  26. 'addActive'
  27. ];
  28. /**
  29. * @title 用户统一登录
  30. * @desc 用户登录
  31. * @author qc
  32. * @url /api/Login/unifiedLogin
  33. * @method POST
  34. * @tag 登录 授权
  35. * @param name:account_type type:int require:1 default:1 desc:账号类型1企业2个人
  36. * @param name:phone_pre type:int require:1 default:86 desc:手机号前缀
  37. * @param name:account type:int require:1 default:-- desc:账号
  38. * @param name:code type:int require:1 default:-- desc:验证码
  39. * @param name:facility_type type:int require:1 default:-- desc:设备类型1:安卓手机设备,2:ios手机设备,3:安卓ipad,4:iosipad,5:h5,6pc电脑设备号
  40. * @param name:facility_code type:string require:1 default:-- desc:设备号
  41. * @return name:token type:string default:-- desc:用户登录成功后的token值
  42. * @return name:phone type:string default:-- desc:绑定的手机号
  43. */
  44. public function unifiedLogin()
  45. {
  46. $code = input('post.code','');
  47. $account = input('post.account','');
  48. $phone_pre = input('post.phone_pre','86');
  49. $account_type = input('post.account_type', 1);
  50. $facility_type = input('post.facility_type', 1);
  51. $facility_code = input('post.facility_code');
  52. $ret_data = ['code' => 200, 'token' => ''];
  53. $msg = '登录成功';
  54. Db::startTrans();
  55. try {
  56. $check_code = $this->checkPhoneCode($account,$code,$phone_pre);
  57. if(!in_array($account,config('power.phone'))) {
  58. // 上线需要去掉注释
  59. if(!$check_code) $this->exception('验证码错误');
  60. $this->updatePhoneCode($check_code);
  61. }
  62. $where = [];
  63. $where[] = $account_type == 1 ? ['email','=',$account] : ['phone','=',$account];
  64. if($account_type == 1) {
  65. $where[] = ['email','=',$account] ;
  66. }else{
  67. $where[] = ['phone','=',$account] ;
  68. $where[] = ['phone_pre','=',$phone_pre] ;
  69. }
  70. $where[] = ['is_deleted','=',0];
  71. $user_info = User::where($where)->find();
  72. if(!$facility_code) $this->exception('设备号不能为空');
  73. if(!$user_info) {
  74. $reg_data = [];
  75. $reg_data['account_type'] = $account_type;
  76. $reg_data['facility_'.$facility_type] = $facility_code;// 注册设备号
  77. if($account_type == 1){
  78. $group_title = explode('@',$account)[1];
  79. $group_info = UserGroup::where(['title'=>'@'.$group_title])->find();
  80. $reg_data['email'] = $account;
  81. $validate = new UserVali();
  82. if (!$validate->scene('email_login')->check(['email'=>$account])) $this->exception($validate->getError());
  83. if($group_info){
  84. $reg_data['name'] = 'G企业用户_'.$group_info->name.'_'.$group_title;
  85. $check_group = User::where(['group_id'=>$group_info->id,'is_first'=>1])->value('id');//该公司是否有第一个注册的
  86. $reg_data['group_id'] = $group_info->id;
  87. if(!$check_group) $reg_data['is_first'] =1;
  88. if($check_group)$reg_data['group_first'] = $check_group;
  89. }else{
  90. $this->exception('该企业邮箱ID无效');
  91. // $reg_data['name'] = 'G企业用户_'.$group_title;
  92. }
  93. }else{
  94. $validate = new UserVali();
  95. if (!$validate->scene('phone_login')->check(['phone'=>$account])) {
  96. $this->exception($validate->getError());
  97. }
  98. $reg_data['phone'] = $account;
  99. $reg_data['phone_pre'] = $phone_pre;
  100. $reg_data['name'] = 'G'. substr_replace($account,'****',3,4);
  101. }
  102. $user_info = User::create($reg_data);
  103. if($account_type == 1 && isset_full_check($reg_data,'is_first',1)) User::where('id',$user_info->id)->update(['group_first'=>$user_info->id]);
  104. $reg_level = sysconf('vip_experience');
  105. // 非企业会员注册,是否怎送会员
  106. if($reg_level && $account_type == 2) UserLevelRank::create(['user_id'=>$user_info->id,'level_id'=>$reg_level,'start_time'=>time(),'end_time'=>time()+86400*7,'end_date'=>date('Y-m-d H:i:s',time()+86400*7)]);
  107. $user_info = $user_info->toArray();
  108. }else{
  109. $user_info = $user_info->toArray();
  110. // 已设置登录设备号
  111. if($user_info['status'] != 1) $this->exception('用户被禁用');
  112. }
  113. // 设备号验证
  114. if(!UserFacility::checkFacility($user_info['id'],$facility_type,$facility_code,$account)) $this->exception('设备号错误');
  115. if(empty($user_info['hx_username']) || !$user_info['hx_username']) hx_register($user_info['id']);
  116. $ret_data['token'] = $this->createJwt($user_info['id'],$facility_code,$facility_type);
  117. if($user_info['account_type'] == 1) {
  118. if(empty($user_info['bind_id'])) {
  119. $ret_data['phone'] = null;
  120. }else{
  121. $ret_data['phone'] = User::where('id',$user_info['bind_id'])->value('phone');
  122. }
  123. }else{
  124. $ret_data['phone'] = $user_info['phone'];
  125. }
  126. $redis = new Redis();
  127. // 登录账号的token
  128. $redis->set('TOKEN_'.$user_info['id'].'_'.$facility_type,$ret_data['token'],86400 * 7);//保存redis 天
  129. UserLoginLog::creatLog($user_info['id'],$facility_type,$facility_code,$account,$ret_data['token']);
  130. Db::commit();
  131. }catch (\Exception $e){
  132. $ret_data['code'] = 201;
  133. $ret_data['phone'] = null;
  134. $msg =$e->getMessage();
  135. Db::rollback();
  136. }
  137. $ret_data['code'] == 200 ? $this->success($msg,$ret_data):$this->error($msg,$ret_data);
  138. }
  139. /**
  140. * @title 获取验证码
  141. * @desc 获取验证码
  142. * @author qc
  143. * @url /api/Login/getCaptcha
  144. * @method GET
  145. * @return name:image type:string default:-- desc:图片
  146. * @return name:uniqid type:string default:-- desc:uniqid
  147. */
  148. public function getCaptcha()
  149. {
  150. $image = CaptchaService::instance();
  151. $captcha = ['image' => $image->getData(), 'uniqid' => $image->getUniqid()];
  152. $this->success('生成验证码成功', $captcha);
  153. }
  154. public static function create_emchat_user($user_id,$nick_name) {
  155. $user_emchat_name = 'Act_'.$user_id;
  156. $user_emchat_password = 'abc123456';
  157. $base_set = [
  158. 'client_id' => 'YXA6NS5H0GDGEe20Q9VWb7Fpew',
  159. 'client_secret' => 'YXA6zkYKRQMJbxi_6cN1ERHuFn9QUpI',
  160. 'org_name' => '1414221110068467',
  161. 'app_name' => 'kefuchannelapp104968',
  162. ];
  163. $emchat = new Easemob($base_set);
  164. $result = $emchat->createUser($user_emchat_name, $user_emchat_password,$nick_name); //创建emchat用户
  165. if (isset($result['error']) && $result['error'] != '') {
  166. return false;
  167. }
  168. return ['user_emchat_name' => $user_emchat_name, 'user_emchat_password' => $user_emchat_password];
  169. }
  170. /**
  171. * @title 查看清除设备号次数
  172. * @desc 查看清除设备号次数
  173. * @author qc
  174. * @url /api/Login/facility_num
  175. * @method GET
  176. * @param name:account_type type:int require:1 default:1 desc:账号类型1企业2个人
  177. * @param name:phone_pre type:int require:1 default:86 desc:手机号前缀
  178. * @param name:account type:int require:1 default:-- desc:账号
  179. * @return name:image type:string default:-- desc:图片
  180. * @return name:uniqid type:string default:-- desc:uniqid
  181. */
  182. public function facility_num()
  183. {
  184. $data = input();
  185. $account_type = $data['account_type'];
  186. $account = $data['account'];
  187. $phone_pre = $data['phone_pre'];
  188. $where = [];
  189. if($account_type == 1) {
  190. $where[] = ['email','=',$account] ;
  191. }else{
  192. $where[] = ['phone','=',$account] ;
  193. $where[] = ['phone_pre','=',$phone_pre] ;
  194. }
  195. $user_info = User::where($where)->find();
  196. $data['user_id'] = $user_info['id'];
  197. $time = strtotime($user_info['create_at']); // 将日期转换为时间戳
  198. //当前年份
  199. $year = date('Y');
  200. $his = date('-m-d H:i:s',$time);
  201. $timestamp_e = $year.$his; // 格式化输出结果
  202. $time_e = strtotime($timestamp_e); // 将日期转换为时间戳
  203. $oneYearLaterTimestamp = $time_e - (60 * 60 * 24 * 365); // 减少一年的秒数
  204. $timestamp_s = date('Y-m-d H:i:s', $oneYearLaterTimestamp); // 格式化输出结果
  205. // $timestamp_e = date('Y-m-d H:i:s',mktime(23, 59, 59, 12, 31, $user_info['create_at']));
  206. $log = Db::name('facility_log')->where('user_id',$data['user_id'])
  207. ->where('operate','clean')
  208. ->where('create_at','>',$timestamp_s)
  209. ->where('create_at','<',$timestamp_e)->count();
  210. $num = 2 - $log;
  211. if($num < 0){
  212. $num = 0;
  213. }
  214. $arr = [
  215. 'timestamp_s' => $timestamp_s,
  216. 'timestamp_e' => $timestamp_e,
  217. 'num' => $num
  218. ];
  219. $this->success('操作成功,剩余'.$num.'次',$arr);
  220. }
  221. /**
  222. * @title 清除设备号
  223. * @desc 清除设备号
  224. * @author qc
  225. * @url /api/Login/facility
  226. * @method GET
  227. * @param name:account_type type:int require:1 default:1 desc:账号类型1企业2个人
  228. * @param name:phone_pre type:int require:1 default:86 desc:手机号前缀
  229. * @param name:account type:int require:1 default:-- desc:账号
  230. * @param name:facility_type type:int require:1 default:-- desc:设备类型1:安卓手机设备,2:ios手机设备,3:安卓ipad,4:iosipad,5:h5,6pc电脑设备号
  231. * @return name:image type:string default:-- desc:图片
  232. * @return name:uniqid type:string default:-- desc:uniqid
  233. */
  234. public function facility(){
  235. $data = input();
  236. // if(!$this->user_id){
  237. // $this->error('请先登录');
  238. // }
  239. $account_type = $data['account_type'];
  240. $account = $data['account'];
  241. $phone_pre = $data['phone_pre'];
  242. $facility_type = $data['facility_type'];
  243. $where = [];
  244. if($account_type == 1) {
  245. $where[] = ['email','=',$account] ;
  246. }else{
  247. $where[] = ['phone','=',$account] ;
  248. $where[] = ['phone_pre','=',$phone_pre] ;
  249. }
  250. $user_info = User::where($where)->find();
  251. $data['user_id'] = $user_info['id'];
  252. // $timestamp_s = date('Y-m-d H:i:s',mktime(0, 0, 0, 1, 1, date('Y')));
  253. // $timestamp_e = date('Y-m-d H:i:s',mktime(23, 59, 59, 12, 31, date('Y')));
  254. $time = strtotime($user_info['create_at']); // 将日期转换为时间戳
  255. //当前年份
  256. $year = date('Y');
  257. $his = date('-m-d H:i:s',$time);
  258. $timestamp_e = $year.$his; // 格式化输出结果
  259. $time_e = strtotime($timestamp_e); // 将日期转换为时间戳
  260. $oneYearLaterTimestamp = $time_e - (60 * 60 * 24 * 365); // 减少一年的秒数
  261. $timestamp_s = date('Y-m-d H:i:s', $oneYearLaterTimestamp); // 格式化输出结果
  262. // return $timestamp_s.'-'.$timestamp_e;
  263. $log = Db::name('facility_log')->where('user_id',$data['user_id'])
  264. ->where('operate','clean')
  265. ->where('create_at','>',$timestamp_s)
  266. ->where('create_at','<',$timestamp_e)->count();
  267. $num = 2 - $log;
  268. if($num < 0){
  269. $num = 0;
  270. }
  271. if($log >= 2){
  272. $this->error('今年的清除次数已耗尽');
  273. }
  274. // return json($data);
  275. $redis = new Redis();
  276. for ($i=1;$i<=4;$i++) {
  277. // $check_facility = UserFacility::where(['user_id'=>$data['user_id'],'type'=>$i,'facility'=>$data['facility_'.$i]])->value('id');
  278. $redis = new Redis();
  279. // if(isset($data['facility_'.$i])){
  280. Data::save('UserFacility',['user_id'=>$data['user_id'],'type'=>$i,'facility'=>'','set_time'=>date('Y-m-d H:i:s')], 'user_id',['user_id'=>$data['user_id'],'type'=>$i]);
  281. // if($data['facility_'.$i] == ''){
  282. $redis->rm('TOKEN_'.$data['user_id'].'_'.$i);
  283. // var_dump('TOKEN_'.$data['user_id'].'_'.$i);die;
  284. $aliases = $this->aliases($data['user_id'],[],'GET','?new_format=true');
  285. if(isset($aliases['data']) && $aliases['data'] != '' && $aliases['data'] != null){
  286. if(count($aliases['data']) > 0){
  287. //别名下有绑定的Registration ID
  288. $registration_ids = [];
  289. foreach ($aliases['data'] as $k => $v){
  290. if($i == 1 || $i == 3){
  291. //安卓
  292. if($facility_type == $i){
  293. if($v['platform'] == "android"){
  294. $registration_ids[] = $v['registration_id'];
  295. }
  296. }
  297. }else if($i == 2 || $i == 4){
  298. //ios
  299. if($facility_type == $i) {
  300. if ($v['platform'] == "ios") {
  301. $registration_ids[] = $v['registration_id'];
  302. }
  303. }
  304. }
  305. }
  306. if(count($registration_ids) > 0){
  307. $body = [
  308. "registration_ids"=>[
  309. "remove"=> $registration_ids
  310. ]
  311. ];
  312. //var_dump($body);die;
  313. // var_dump($registration_ids);die;
  314. $aliases_del = $this->aliases($data['user_id'],$body,'POST');
  315. // var_dump($aliases_del);die;
  316. }
  317. }
  318. }
  319. // }
  320. // }
  321. }
  322. $arr = [
  323. 'user_id' => $data['user_id'],
  324. 'create_at' => date("Y-m-d H:i:s"),
  325. 'operate' => 'clean'
  326. ];
  327. Db::name('facility_log')->insert($arr);
  328. $this->success('操作成功,剩余'.($num - 1).'次');
  329. }
  330. // /**
  331. // * @title 推送查询
  332. // * @desc 推送查询
  333. // */
  334. public function aliases($id = 66,$registration_ids = [],$type = 'GET',$new_format = ''){
  335. $data = input();
  336. // if(!$data['url'] || !$data['from'] || !$data['to'] || !$data['url']){
  337. //
  338. // }
  339. $arr = [
  340. 'url'=>'https://device.jpush.cn/v3/aliases/'.$id.$new_format,
  341. 'AppKey'=>config('app.jiguang')['AppKey'],
  342. 'MasterSecret'=>config('app.jiguang')['MasterSecret'],
  343. ];
  344. // $hx_voice = hx_voice(24);
  345. // $url= $arr['url'].$arr['org_name'].'/'.$arr['app_name'].'/'.'messages/users';
  346. // $body['from'] = $data['form']; //'member2200'
  347. // $body['to'] = $data['to']; //worker1000
  348. // $body['type'] = 'audio';
  349. // $body['body'] = [
  350. // 'filename' => $data['filename'], //'testaudio.amr', //语音文件的名称
  351. // 'url' => $data['url'] //'http://tmp/bQo7Udv1FETr01c4bb0ecee3a2edb86b00a393176fcc.durationTime=2790.aac', //语音文件的url地址
  352. // ];
  353. $body = $registration_ids;
  354. $options['type']="audio";
  355. $options['msg']='发送';
  356. $b=json_encode($body);
  357. // return $b;
  358. $str = $arr['AppKey'].':'.$arr['MasterSecret'];
  359. //$str = '7d431e42dfa6a6d693ac2d04:5e987ac6d2e04d95a9d8f0d1';
  360. $base64 = base64_encode($str);
  361. //$header=['Authorization' => ];
  362. $header = array("Authorization: Basic ".$base64);
  363. // return json($header);
  364. $result=$this->postCurl($arr['url'],$b,$header,$type);
  365. // $result=$this->postCurl($url,$body,$header);
  366. //dump($result);
  367. return $result;
  368. // return $hx_voice;
  369. }
  370. public function postCurl($url,$body,$header,$type="POST"){
  371. //1.创建一个curl资源
  372. $ch = curl_init();
  373. //2.设置URL和相应的选项
  374. curl_setopt($ch,CURLOPT_URL,$url);//设置url
  375. //1)设置请求头
  376. // array_push($header, 'Accept:application/json');
  377. // array_push($header,'Content-Type:application/json');
  378. // array_push($header, 'http:multipart/form-data');
  379. //设置为false,只会获得响应的正文(true的话会连响应头一并获取到)
  380. curl_setopt($ch,CURLOPT_HEADER,0);
  381. // curl_setopt ( $ch, CURLOPT_TIMEOUT,5); // 设置超时限制防止死循环
  382. //设置发起连接前的等待时间,如果设置为0,则无限等待。
  383. curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,5);
  384. //将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
  385. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  386. //2)设备请求体
  387. if (strlen($body)>0) {
  388. //$b=json_encode($body,true);
  389. curl_setopt($ch, CURLOPT_POSTFIELDS, $body);//全部数据使用HTTP协议中的"POST"操作来发送。
  390. }
  391. //设置请求头
  392. // if(count($header)>0){
  393. // curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
  394. // }
  395. curl_setopt($ch,CURLOPT_HTTPHEADER,$header);
  396. //上传文件相关设置
  397. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  398. curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
  399. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 对认证证书来源的检查
  400. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);// 从证书中检查SSL加密算
  401. //3)设置提交方式
  402. switch($type){
  403. case "GET":
  404. curl_setopt($ch,CURLOPT_HTTPGET,true);
  405. break;
  406. case "POST":
  407. curl_setopt($ch,CURLOPT_POST,true);
  408. break;
  409. case "PUT"://使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请求。这对于执行"DELETE" 或者其他更隐蔽的HTT
  410. curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"PUT");
  411. break;
  412. case "DELETE":
  413. curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"DELETE");
  414. break;
  415. }
  416. //4)在HTTP请求中包含一个"User-Agent: "头的字符串。-----必设
  417. // curl_setopt($ch, CURLOPT_USERAGENT, 'SSTS Browser/1.0');
  418. // curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
  419. //curl_setopt ( $ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)' ); // 模拟用户使用的浏览器
  420. //5)
  421. //3.抓取URL并把它传递给浏览器
  422. $res=curl_exec($ch);
  423. $result=json_decode($res,true);
  424. //4.关闭curl资源,并且释放系统资源
  425. curl_close($ch);
  426. if(empty($result))
  427. return $res;
  428. else
  429. return $result;
  430. }
  431. /**
  432. * @title 增加活跃度
  433. * @desc 增加活跃度
  434. * @author qc
  435. * @url /api/Login/addActive
  436. * @method Post
  437. * @param name:type type:int require:1 default:-- desc:设备类型1:安卓手机设备,2:ios手机设备,3:安卓ipad,4:iosipad,5:h5,6pc电脑设备号
  438. * @return name:image type:string default:-- desc:图片
  439. * @return name:uniqid type:string default:-- desc:uniqid
  440. */
  441. public function addActive(){
  442. $startTime = date('Y-m-d') . ' 00:00:00'; // 获取今天的起始时间
  443. $endTime = date('Y-m-d') . ' 23:59:59'; // 获取今天的结束时间
  444. if(!$this->user_id){
  445. $this->error('请先登录');
  446. }
  447. $active_log = Db::name('user_active_log')
  448. ->where('create_at','>',$startTime)
  449. ->where('create_at','<',$endTime)
  450. ->where('user_id',$this->user_id)
  451. ->find();
  452. if(!$active_log){
  453. $data = input();
  454. $arr = [
  455. 'user_id' => $this->user_id,
  456. 'create_at' => date('Y-m-d H:i:s'),
  457. 'type' => $data['type']
  458. ];
  459. Db::name('user_active_log')->insert($arr);
  460. }
  461. $this->success('操作成功');
  462. }
  463. }