Login.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkAdmin
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2014~2019 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://demo.thinkadmin.top
  8. // +----------------------------------------------------------------------
  9. // | 开源协议 ( https://mit-license.org )
  10. // +----------------------------------------------------------------------
  11. // | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
  12. // | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
  13. // +----------------------------------------------------------------------
  14. namespace app\api\controller;
  15. use AlibabaCloud\Client\AlibabaCloud;
  16. use AlibabaCloud\Client\Exception\ClientException;
  17. use AlibabaCloud\Client\Exception\ServerException;
  18. use app\api\controller\Base;
  19. use think\Db;
  20. use Firebase\JWT\JWT;
  21. use EasyWeChat\Factory;
  22. /**
  23. * @title 登录
  24. * @controller Login
  25. * @group worker
  26. */
  27. class Login extends Base
  28. {
  29. /**
  30. * @title 用户协议
  31. * @desc 用户协议
  32. * @author QGF
  33. * @url /api/Login/agreement
  34. * @method GET
  35. * @tag 用户协议
  36. * @return name:-- type:string default:-- desc:用户协议内容(富文本)
  37. */
  38. public function agreement(){
  39. $this->success('获取成功',htmlspecialchars_decode(sysconf('agreement')));
  40. }
  41. /**
  42. * @title 注册
  43. * @desc 注册
  44. * @author QGF
  45. * @url /api/Login/register
  46. * @method POST
  47. * @tag 注册
  48. * @param name:phone type:int require:1 default:-- desc:手机号
  49. * @param name:code type:int require:1 default:-- desc:短信验证码
  50. * @param name:password type:string require:1 default:-- desc:密码
  51. */
  52. public function register(){
  53. $phone = input('phone');
  54. $code = input('code');
  55. $password = input('password');
  56. if(empty($phone) || empty($code) || empty($password)){
  57. $this ->error('参数错误');
  58. }
  59. $sms_id = $this->verify_sms($phone,$code);
  60. if(empty($sms_id)){
  61. $this->error('验证码不正确');
  62. }
  63. $member_id = Db::name('store_member')->where('phone',$phone)->value('id');
  64. if(!empty($member_id)){
  65. $this->error('该手机号已被注册');
  66. }
  67. $data = array(
  68. 'phone'=>$phone,
  69. 'password' => md5($password),
  70. 'decode_password' => $password,
  71. 'name' => substr($phone,-4),
  72. 'headimg' => 'https://zjth2021.oss-cn-beijing.aliyuncs.com/0909a49add201291/a20687c6493d3eab.jpg',
  73. 'background' => Db::name('store_background')->where('id',1)->value('logo'),
  74. );
  75. Db::name('store_member')->insert($data);
  76. $member_id = Db::name('store_member')->where('phone',$phone)->value('id');
  77. Db::name('store_member_sms')->where('id',$sms_id)->update(array('used'=>1));
  78. $token = self::create_jwt($member_id);
  79. $this->success('注册成功',$token);
  80. }
  81. /**
  82. * @title 微信登录(小程序)
  83. * @desc 微信登录(小程序)
  84. * @author QGF
  85. * @url /api/Login/we_chat_login
  86. * @method POST
  87. * @tag 登录 授权
  88. * @param name:code type:int require:1 default:-- desc:code值
  89. * @param name:headimg type:string require:1 default:-- desc:头像地址
  90. * @param name:name type:string require:1 default:-- desc:昵称
  91. * @return name:openid type:string default:-- desc:用户openid(未绑定手机号)
  92. * @return name:headimg type:string default:-- desc:用户头像地址(未绑定手机号)
  93. * @return name:name type:string default:屈耀光 desc:用户昵称(未绑定手机号)
  94. * @return name:token type:string default:-- desc:用户登录成功后的token值(已绑定手机号)
  95. */
  96. public function we_chat_login(){
  97. $code = input('code');
  98. $headimg = input('headimg');
  99. $name = input('name');
  100. if(empty($code) || empty($headimg) || empty($name)){
  101. $this->error('参数错误');
  102. }
  103. $app = Factory::miniProgram(config('app.mini_program'));
  104. $data = $app->auth->session($code);
  105. if(empty($data['openid'])){
  106. $this->error('微信登录失败');
  107. }
  108. $member = Db::name('store_member')->field('id,phone')->where('openid',$data['openid'])->find();
  109. if(empty($member['phone'])){
  110. $member_data = array(
  111. 'openid' => $data['openid'],
  112. 'headimg' => $headimg,
  113. 'name' => $name
  114. );
  115. $this->success('授权成功',$member_data);
  116. }
  117. $uid = $member['id'];
  118. if(empty($uid)){
  119. $this->error('数据有误');
  120. }
  121. $token = self::create_jwt($uid);
  122. $this->success('登录成功',$token);
  123. }
  124. /**
  125. * @title 微信登录(app)
  126. * @desc 微信登录
  127. * @author QGF
  128. * @url /api/Login/we_chat_app
  129. * @method POST
  130. * @tag 登录 授权
  131. * @param name:code type:int require:1 default:oRZeJ55dhq8y6gHI9PVwCrv0gvSM desc:code值
  132. * @return name:-- type:json default:-- desc:微信注册返回授权后的信息(openid:微信openid,name:微信昵称,headimgurl:微信头像地址,token:token值(这时为空)注:仅微信注册有)
  133. * @return name:token type:string default:-- desc:用户微信登录成功后的token值(仅用户登录有)
  134. */
  135. public function we_chat_app(){
  136. $code = input('code');
  137. if(empty($code)){
  138. $this->error('参数错误');
  139. }
  140. $res = requestGet('https://api.weixin.qq.com/sns/oauth2/access_token?appid='.config('app_program')['app_id'].'&secret='.config('app_program')['secret'].'&code='.$code.'&grant_type=authorization_code');
  141. $res = json_decode($res,true);
  142. $user_info = requestGet('https://api.weixin.qq.com/sns/userinfo?access_token='.$res['access_token'].'&openid='.$res['openid']);
  143. $user_info = json_decode($user_info,true);
  144. $data['openid'] = $user_info['openid'];
  145. $data['name'] = $user_info['nickname'];
  146. $data['headimg'] = $user_info['headimg'];
  147. $data['token'] = '';
  148. $member_id = Db::name('store_member')->where('app_openid',$data['openid'])->value('id');
  149. if(empty($member_id)){
  150. $this->success('授权成功',$data);
  151. }else{
  152. $token = self::create_jwt($member_id);
  153. $data['token'] = $token;
  154. $this->success('登录成功',$data);
  155. }
  156. }
  157. /**
  158. * @title 密码登录
  159. * @desc 密码登录
  160. * @author QGF
  161. * @url /api/Login/password_login
  162. * @method POST
  163. * @tag 密码登录
  164. * @param name:phone type:int require:1 default:-- desc:手机号
  165. * @param name:password type:string require:1 default:-- desc:密码
  166. * @return name:token type:string default:-- desc:用户登录成功后的token值
  167. */
  168. public function password_login(){
  169. $phone = input('phone');
  170. $password = input('password');
  171. if(empty($password) || empty($phone)){
  172. $this->error('参数错误');
  173. }
  174. $member_id = Db::name('store_member')->where('phone',$phone)->where('password',md5($password))->value('id');
  175. if(empty($member_id)){
  176. $this->error('手机号或密码错误');
  177. }
  178. $token = self::create_jwt($member_id);
  179. $this->success('登录成功',$token);
  180. }
  181. /**
  182. * @title 绑定手机号(点击微信登录时还没注册,绑定完手机号提交信息去注册)
  183. * @desc 绑定手机号
  184. * @author QGF
  185. * @url /api/Login/binding_phone
  186. * @method POST
  187. * @tag 绑定手机号
  188. * @param name:platform type:1 require:0 default:1 desc:平台(注:1:小程序2:app)
  189. * @param name:phone type:int require:1 default:-- desc:要绑定的手机号
  190. * @param name:code type:int require:1 default:-- desc:短信验证码
  191. * @param name:openid type:string require:1 default:-- desc:微信授权返回的openid
  192. * @param name:name type:string require:1 default:-- desc:微信授权返回的用户昵称
  193. * @param name:headimg type:string require:1 default:-- desc:微信授权返回的用户头像地址
  194. * @return name:token type:string default:-- desc:绑定成功后的token值
  195. */
  196. public function binding_phone(){
  197. $phone = input('phone');
  198. $code = input('code');
  199. $openid = input('openid');
  200. $name = input('name');
  201. $headimg = input('headimg');
  202. $platform = input('platform',1); //1:小程序,2:app
  203. if(empty($phone) || empty($code) || empty($openid) || empty($name) || empty($headimg)){
  204. $this ->error('参数错误');
  205. }
  206. $sms_id = $this->verify_sms($phone,$code);
  207. if(empty($sms_id)){
  208. $this->error('验证码不正确');
  209. }
  210. $member_id = Db::name('store_member')->where('phone',$phone)->value('id');
  211. if(!$member_id){
  212. $data = array(
  213. 'phone'=>$phone,
  214. 'name' => $name,
  215. 'headimg' => $headimg,
  216. );
  217. if($platform == 1){
  218. $data['openid'] = $openid;
  219. }else{
  220. $data['app_openid'] = $openid;
  221. }
  222. Db::name('store_member')->insert($data);
  223. $member_id = Db::name('store_member')->where('phone',$phone)->value('id');
  224. }else{
  225. if($platform == 1){
  226. $update_data['openid'] = $openid;
  227. }else{
  228. $update_data['app_openid'] = $openid;
  229. }
  230. Db::name('store_member')->where('id',$member_id)->update($update_data);
  231. }
  232. Db::name('store_member_sms')->where('id',$sms_id)->update(array('used'=>1));
  233. $token = self::create_jwt($member_id);
  234. $this->success('注册成功',$token);
  235. }
  236. /**
  237. * @title 忘记密码
  238. * @desc 忘记密码
  239. * @author QGF
  240. * @url /api/Login/reset_password
  241. * @method POST
  242. * @tag 忘记密码
  243. * @param name:phone type:int require:1 default:-- desc:手机号
  244. * @param name:code type:int require:1 default:-- desc:短信验证码
  245. * @param name:password type:string require:1 default:-- desc:密码
  246. */
  247. public function reset_password(){
  248. $phone = input('phone');
  249. $code = input('code');
  250. $password = input('password');
  251. if(empty($phone) || empty($code) || empty($password)){
  252. $this ->error('参数错误');
  253. }
  254. $sms_id = $this->verify_sms($phone,$code);
  255. if(empty($sms_id)){
  256. $this->error('验证码不正确');
  257. }
  258. $member = Db::name('store_member')->field('id,decode_password')->where('phone',$phone)->find();
  259. if(empty($member['id'])){
  260. $this ->error('该手机号未注册');
  261. }
  262. if($password == $member['decode_password']){
  263. $this ->error('新密码与原密码一致,直接登录');
  264. }
  265. $update_data = array(
  266. 'password'=>md5($password),
  267. 'decode_password'=>$password
  268. );
  269. Db::name('store_member')->where('phone',$phone)->update($update_data);
  270. Db::name('store_member_sms')->where('id',$sms_id)->update(array('used'=>1));
  271. $this->success('修改密码成功');
  272. }
  273. /**
  274. * @title 发送短信验证码
  275. * @desc 发送短信验证码
  276. * @author QGF
  277. * @url /api/Login/send_sms
  278. * @method POST
  279. * @tag 短信验证码
  280. * @param name:phone type:int require:1 default:-- desc:要获取验证码的手机号
  281. * @return name:code type:string default:-- desc:验证码
  282. */
  283. public function send_sms(){
  284. $phone = input('phone');
  285. if(empty($phone)){
  286. $this ->error('参数错误');
  287. }
  288. $code = rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9).rand(0,9);
  289. AlibabaCloud::accessKeyClient('LTAI5tDNASTjwM9mDSGckY3N', 'nAKY40GjGz4hf5A9RpoffDmaYWNL3y')->regionId('cn-hangzhou')->asDefaultClient();
  290. try {
  291. $result = AlibabaCloud::rpc()
  292. ->product('Dysmsapi')
  293. ->version('2017-05-25')
  294. ->action('SendSms')
  295. ->method('POST')
  296. ->host('dysmsapi.aliyuncs.com')
  297. ->options([
  298. 'query' => [
  299. 'RegionId' => "cn-hangzhou",
  300. 'PhoneNumbers' => $phone,
  301. 'SignName' => "碳汇资产",
  302. 'TemplateCode' => "SMS_222240090",
  303. 'TemplateParam' => json_encode(array("code"=>$code)),
  304. ],
  305. ])->request();
  306. $result = $result->toArray();
  307. $sms_data = array(
  308. 'phone'=>$phone,
  309. 'code'=>$code,
  310. 'result'=>$result['Message']
  311. );
  312. Db::name('store_member_sms')->insert($sms_data);
  313. } catch (ClientException $e) {
  314. echo $e->getErrorMessage() . PHP_EOL;
  315. } catch (ServerException $e) {
  316. echo $e->getErrorMessage() . PHP_EOL;
  317. }
  318. $this->success('发送成功',$code);
  319. }
  320. //校验短信验证码
  321. public function verify_sms($phone = '',$code = ''){
  322. $store_member_sms = Db::name('store_member_sms')->field('id,code')->where('phone',$phone)->where('used',0)->order('id desc')->find();
  323. if($store_member_sms['code'] == $code){
  324. return $store_member_sms['id'];
  325. }else{
  326. return 0;
  327. }
  328. }
  329. //token加密
  330. public function create_jwt($uid)
  331. {
  332. $key = md5(config('app.jwt')); //jwt的签发密钥,验证token的时候需要用到
  333. $time = time(); //签发时间
  334. $expire = $time + config('app.jwt_time'); //过期时间
  335. $token = array(
  336. "uid" => $uid,
  337. "iss" => "https://zain.com",//签发组织
  338. "aud" => "https://zain.com", //签发作者
  339. "iat" => $time,
  340. "nbf" => $time,
  341. "exp" => $expire
  342. );
  343. $jwt = JWT::encode($token, $key);
  344. return $jwt;
  345. }
  346. public function get_token(){
  347. $uid = input('uid',500);
  348. $token = $this->create_jwt($uid);
  349. $this->success('',$token);
  350. }
  351. }