LoginServices.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\services\user;
  13. use app\model\user\User;
  14. use app\services\system\SmsRecordServices;
  15. use Exception;
  16. use Psr\SimpleCache\InvalidArgumentException;
  17. use qiniu\basic\BaseModel;
  18. use qiniu\basic\BaseServices;
  19. use qiniu\services\CacheService;
  20. use qiniu\services\sms\Sms;
  21. use think\db\exception\DataNotFoundException;
  22. use think\db\exception\DbException;
  23. use think\db\exception\ModelNotFoundException;
  24. use think\exception\ValidateException;
  25. use think\facade\Config;
  26. use think\Model;
  27. /**
  28. *
  29. * Class LoginServices
  30. * @package app\services\user
  31. * @mixin User
  32. */
  33. class LoginServices extends BaseServices
  34. {
  35. /**
  36. * LoginServices constructor.
  37. * @param User $model
  38. */
  39. public function __construct(User $model)
  40. {
  41. $this->model = $model;
  42. }
  43. /**
  44. * @param $account
  45. * @param $password
  46. * @param int $spread_uid
  47. * @return array
  48. * @throws DataNotFoundException
  49. * @throws DbException
  50. * @throws ModelNotFoundException
  51. */
  52. public function login($account, $login_type, $password, $spread_uid = 0)
  53. {
  54. if ($login_type != 'phone') $login_type = 'account';
  55. $user = $this->getOne([$login_type => $account], 'uid,pwd,status,salt');
  56. if ($user) {
  57. if ($user->pwd !== password((string)$password, $user->salt)[0])
  58. throw new ValidateException('账号或密码错误');
  59. } else {
  60. throw new ValidateException('账号或密码错误');
  61. }
  62. if (!$user['status'])
  63. throw new ValidateException('已被禁止,请联系管理员');
  64. $uid = (int)$user['uid'];
  65. //更新用户信息
  66. $token = $this->createToken($uid, 'api', $user->pwd);
  67. if ($token) {
  68. // 用户登录成功事件
  69. $this->updateUserLastLogin($uid);
  70. if ($spread_uid > 0) {
  71. /** @var UserSpreadServices $spreadService */
  72. $spreadService = app()->make(UserSpreadServices::class);
  73. $spreadService->setSpread($uid, $spread_uid);
  74. }
  75. return ['token' => $token['token'], 'expires_time' => $token['params']['exp']];
  76. } else
  77. throw new ValidateException('登录失败');
  78. }
  79. /**
  80. * 更新用户信息
  81. * @param int $uid
  82. * @return bool
  83. */
  84. public function updateUserLastLogin(int $uid): bool
  85. {
  86. $data['last_time'] = time();
  87. $data['last_ip'] = app()->request->ip();
  88. if (!$this->update($uid, $data, 'uid')) {
  89. throw new ValidateException('修改信息失败');
  90. }
  91. return true;
  92. }
  93. /**
  94. * 更新用户信息
  95. * @param int $uid
  96. * @param array $wechatInfo
  97. * @param array $userInfo
  98. * @return bool
  99. * @throws DataNotFoundException
  100. * @throws DbException
  101. * @throws ModelNotFoundException
  102. */
  103. public function updateUserWechatLogin(int $uid, array $wechatInfo, $userInfo = []): bool
  104. {
  105. if (!$userInfo) {
  106. $userInfo = $this->get($uid);
  107. if (!$userInfo) {
  108. throw new ValidateException('数据不存在');
  109. }
  110. }
  111. $data = [];
  112. if (isset($wechatInfo['nickname']) && $wechatInfo['nickname']) {
  113. $data['nickname'] = $wechatInfo['nickname'];
  114. }
  115. if (isset($wechatInfo['headimgurl']) && $wechatInfo['headimgurl']) {
  116. $data['avatar'] = $wechatInfo['headimgurl'];
  117. }
  118. if (isset($wechatInfo['phone']) && $wechatInfo['phone'] && !$this->be(['account|phone' => $wechatInfo['phone']]) && !$userInfo['phone']) {
  119. $data['phone'] = $wechatInfo['phone'];
  120. $data['account'] = $wechatInfo['phone'];
  121. }
  122. $data['last_time'] = time();
  123. $data['last_ip'] = app()->request->ip();
  124. if (!$this->update($uid, $data, 'uid')) {
  125. throw new ValidateException('修改信息失败');
  126. }
  127. if (($wechatInfo['spread_uid'] ?? 0) > 0) {
  128. /** @var UserSpreadServices $spreadService */
  129. $spreadService = app()->make(UserSpreadServices::class);
  130. $spreadService->setSpread($uid, $wechatInfo['spread_uid']);
  131. }
  132. return true;
  133. }
  134. /**
  135. * 发送验证码
  136. * @param $phone
  137. * @param $type
  138. * @param $time
  139. * @param $ip
  140. * @return int
  141. * @throws DataNotFoundException
  142. * @throws DbException
  143. * @throws ModelNotFoundException
  144. */
  145. public function verify($phone, $type, $time, $ip)
  146. {
  147. if ($this->getOne(['phone' => $phone]) && ($type == 'register' || $type == 'change_new')) {
  148. throw new ValidateException('手机号已注册');
  149. }
  150. $default = Config::get('sms.default', 'qiniu');
  151. $defaultMaxPhoneCount = Config::get('sms.maxPhoneCount', 10);
  152. $defaultMaxIpCount = Config::get('sms.maxIpCount', 50);
  153. $maxPhoneCount = Config::get('sms.stores.' . $default . '.maxPhoneCount', $defaultMaxPhoneCount);
  154. $maxIpCount = Config::get('sms.stores.' . $default . '.maxIpCount', $defaultMaxIpCount);
  155. /** @var SmsRecordServices $smsRecord */
  156. $smsRecord = app()->make(SmsRecordServices::class);
  157. if ($smsRecord->getCount(['phone' => $phone, 'add_ip' => $ip, 'time' => 'today']) >= $maxPhoneCount) {
  158. throw new ValidateException('您今日发送短信次数已经达到上限');
  159. }
  160. if ($smsRecord->getCount(['add_ip' => $ip, 'time' => 'today']) >= $maxIpCount) {
  161. throw new ValidateException('此IP今日发送短信次数已经达到上限');
  162. }
  163. if (CacheService::get('code_' . $phone))
  164. throw new ValidateException('验证码' . $time . '分钟内有效');
  165. mt_srand();
  166. $code = rand(100000, 999999);
  167. $data['code'] = $code;
  168. $data['time'] = $time;
  169. $res = app()->make(Sms::class)->send($phone, 'VERIFICATION_CODE_TIME', $data);
  170. if (!$res)
  171. throw new ValidateException('短信平台验证码发送失败');
  172. return $code;
  173. }
  174. /**
  175. * H5用户注册
  176. * @param $phone
  177. * @param $password
  178. * @param $spread_uid
  179. * @param string $user_type
  180. * @param string $nickname
  181. * @return Model|BaseModel
  182. * @throws DataNotFoundException
  183. * @throws DbException
  184. * @throws ModelNotFoundException
  185. */
  186. public function register($phone, $password, $spread_uid, string $user_type = 'h5', string $nickname = '')
  187. {
  188. if ($this->getOne(['phone' => $phone])) {
  189. throw new ValidateException('该手机号已使用');
  190. }
  191. $data['account'] = create_account();
  192. [$data['pwd'], $data['salt']] = password((string)$password);
  193. $data['phone'] = $phone;
  194. $data['real_name'] = '';
  195. $data['birthday'] = 0;
  196. $data['user_type'] = $user_type;
  197. $data['add_time'] = time();
  198. $data['add_ip'] = app('request')->ip();
  199. $data['last_time'] = time();
  200. $data['last_ip'] = app('request')->ip();
  201. $data['nickname'] = $nickname ?: substr(md5($phone . time()), 0, 12);
  202. $data['avatar'] = sys_config('h5_avatar');
  203. $data['status'] = 1;
  204. $data['is_promoter'] = ((sys_config('brokerage_func_status', 0) && sys_config('store_brokerage_statu', 1) == 2) ? 1 : 0);
  205. if (!$re = $this->create($data)) {
  206. throw new ValidateException('注册失败');
  207. } else {
  208. if ($spread_uid > 0) {
  209. /** @var UserSpreadServices $spreadService */
  210. $spreadService = app()->make(UserSpreadServices::class);
  211. $spreadService->setSpread($re->uid, $spread_uid);
  212. }
  213. return $re;
  214. }
  215. }
  216. /**
  217. * 重置密码
  218. * @param $account
  219. * @param $password
  220. * @return bool
  221. * @throws DataNotFoundException
  222. * @throws DbException
  223. * @throws ModelNotFoundException
  224. */
  225. public function reset($account, $password)
  226. {
  227. $user = $this->getOne(['phone' => $account]);
  228. if (!$user) {
  229. throw new ValidateException('账号不存在');
  230. }
  231. [$pwd, $salt] = password((string)$password);
  232. if (!$this->update($user['uid'], ['pwd' => $pwd, 'salt' => $salt], 'uid')) {
  233. throw new ValidateException('修改密码失败');
  234. }
  235. return true;
  236. }
  237. /**
  238. * 重置交易密码
  239. * @param $account
  240. * @param $password
  241. * @return bool
  242. * @throws DataNotFoundException
  243. * @throws DbException
  244. * @throws ModelNotFoundException
  245. */
  246. public function trade_reset($account, $password)
  247. {
  248. $user = $this->getOne(['phone' => $account]);
  249. if (!$user) {
  250. throw new ValidateException('账号不存在');
  251. }
  252. [$pwd, $salt] = password((string)$password);
  253. if (!$this->update($user['uid'], ['trade_pwd' => $pwd, 'trade_salt' => $salt], 'uid')) {
  254. throw new ValidateException('修改交易密码失败');
  255. }
  256. return true;
  257. }
  258. /**
  259. * 手机号登录
  260. * @param $phone
  261. * @param $spread_uid
  262. * @param string $user_type
  263. * @return array
  264. * @throws Exception
  265. */
  266. public function mobile($phone, $spread_uid, $user_type = 'h5')
  267. {
  268. //数据库查询
  269. $user = $this->getOne(['phone' => $phone]);
  270. if (!$user) {
  271. $user = $this->register($phone, '123456', $spread_uid, $user_type);
  272. if (!$user) {
  273. throw new ValidateException('用户登录失败,无法生成新用户,请稍后再试!');
  274. }
  275. }
  276. if (!$user->status)
  277. throw new ValidateException('已被禁止,请联系管理员');
  278. $uid = (int)$user['uid'];
  279. $token = $this->createToken($uid, 'api', $user->pwd);
  280. if ($token) {
  281. // 用户登录成功事件
  282. $this->updateUserLastLogin($uid);
  283. if ($spread_uid > 0) {
  284. /** @var UserSpreadServices $spreadService */
  285. $spreadService = app()->make(UserSpreadServices::class);
  286. $spreadService->setSpread($uid, $spread_uid);
  287. }
  288. return ['token' => $token['token'], 'expires_time' => $token['params']['exp']];
  289. } else {
  290. throw new ValidateException('登录失败');
  291. }
  292. }
  293. }