LoginServices.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. namespace app\services\kefu;
  12. use crmeb\exceptions\AuthException;
  13. use crmeb\utils\ApiErrorCode;
  14. use crmeb\utils\JwtAuth;
  15. use Firebase\JWT\ExpiredException;
  16. use think\facade\Cache;
  17. use app\services\BaseServices;
  18. use crmeb\services\CacheService;
  19. use app\dao\service\StoreServiceDao;
  20. use crmeb\services\WechatOpenService;
  21. use think\exception\ValidateException;
  22. use app\services\wechat\WechatUserServices;
  23. /**
  24. * 客服登录
  25. * Class LoginServices
  26. * @package app\services\kefu
  27. * @method get($id, ?array $field = [], ?array $with = []) 获取一条数据
  28. */
  29. class LoginServices extends BaseServices
  30. {
  31. /**
  32. * LoginServices constructor.
  33. * @param StoreServiceDao $dao
  34. */
  35. public function __construct(StoreServiceDao $dao)
  36. {
  37. $this->dao = $dao;
  38. }
  39. /**
  40. * 客服账号密码登录
  41. * @param string $account
  42. * @param string $password
  43. * @return array
  44. * @throws \think\db\exception\DataNotFoundException
  45. * @throws \think\db\exception\DbException
  46. * @throws \think\db\exception\ModelNotFoundException
  47. */
  48. public function authLogin(string $account, string $password = null)
  49. {
  50. $kefuInfo = $this->dao->get(['account' => $account]);
  51. if (!$kefuInfo) {
  52. throw new ValidateException('没有此用户');
  53. }
  54. if ($password && !password_verify($password, $kefuInfo->password)) {
  55. throw new ValidateException('账号或密码错误');
  56. }
  57. if (!$kefuInfo->status) {
  58. throw new ValidateException('您已被禁止登录');
  59. }
  60. $token = $this->createToken($kefuInfo->id, 'kefu');
  61. $kefuInfo->update_time = time();
  62. $kefuInfo->ip = request()->ip();
  63. $kefuInfo->save();
  64. return [
  65. 'token' => $token['token'],
  66. 'exp_time' => $token['params']['exp'],
  67. 'kefuInfo' => $kefuInfo->hidden(['password', 'ip', 'update_time', 'add_time', 'status', 'mer_id', 'customer', 'notify'])->toArray()
  68. ];
  69. }
  70. /**
  71. * 解析token
  72. * @param string $token
  73. * @return array
  74. * @throws \Psr\SimpleCache\InvalidArgumentException
  75. * @throws \think\db\exception\DataNotFoundException
  76. * @throws \think\db\exception\DbException
  77. * @throws \think\db\exception\ModelNotFoundException
  78. */
  79. // public function parseToken(string $token)
  80. // {
  81. // /** @var BaseAuth $services */
  82. // $services = app()->make(BaseAuth::class);
  83. // $adminInfo = $services->parseToken($token, function ($id) {
  84. // return $this->dao->get($id);
  85. // });
  86. // return $adminInfo->hidden(['password', 'ip', 'status']);
  87. // }
  88. public function parseToken(string $token)
  89. {
  90. $noCli = !request()->isCli();
  91. /** @var CacheService $cacheService */
  92. $cacheService = app()->make(CacheService::class);
  93. //检测token是否过期
  94. $md5Token = md5($token);
  95. if (!$token || !$cacheService->hasToken($md5Token) || !($cacheToken = $cacheService->getTokenBucket($md5Token))) {
  96. throw new AuthException(ApiErrorCode::ERR_LOGIN);
  97. }
  98. if ($token === 'undefined') {
  99. throw new AuthException(ApiErrorCode::ERR_LOGIN);
  100. }
  101. //是否超出有效次数
  102. if (isset($cacheToken['invalidNum']) && $cacheToken['invalidNum'] >= 3) {
  103. $cacheService->clearToken($md5Token);
  104. throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
  105. }
  106. /** @var JwtAuth $jwtAuth */
  107. $jwtAuth = app()->make(JwtAuth::class);
  108. //设置解析token
  109. [$id, $type] = $jwtAuth->parseToken($token);
  110. //验证token
  111. try {
  112. $jwtAuth->verifyToken();
  113. $cacheService->setTokenBucket($md5Token, $cacheToken, $cacheToken['exp']);
  114. } catch (ExpiredException $e) {
  115. $cacheToken['invalidNum'] = isset($cacheToken['invalidNum']) ? $cacheToken['invalidNum']++ : 1;
  116. $cacheService->setTokenBucket($md5Token, $cacheToken, $cacheToken['exp']);
  117. } catch (\Throwable $e) {
  118. $noCli && $cacheService->clearToken($md5Token);
  119. throw new AuthException(ApiErrorCode::ERR_LOGIN_INVALID);
  120. }
  121. //获取管理员信息
  122. $adminInfo = $this->dao->get($id);
  123. if (!$adminInfo || !$adminInfo->id) {
  124. $noCli && $cacheService->clearToken($md5Token);
  125. throw new AuthException(ApiErrorCode::ERR_LOGIN_STATUS);
  126. }
  127. $adminInfo->type = $type;
  128. return $adminInfo->hidden(['password', 'ip', 'status']);
  129. }
  130. /**
  131. * @return array
  132. * @throws \think\db\exception\DataNotFoundException
  133. * @throws \think\db\exception\DbException
  134. * @throws \think\db\exception\ModelNotFoundException
  135. */
  136. public function wechatAuth()
  137. {
  138. /** @var WechatOpenService $service */
  139. $service = app()->make(WechatOpenService::class);
  140. $info = $service->getAuthorizationInfo();
  141. if (!$info) {
  142. throw new ValidateException('授权失败');
  143. }
  144. $original = $info->getOriginal();
  145. if (!isset($original['unionid'])) {
  146. throw new ValidateException('unionid不存在');
  147. }
  148. /** @var WechatUserServices $userService */
  149. $userService = app()->make(WechatUserServices::class);
  150. $uid = $userService->value(['unionid' => $original['unionid']], 'uid');
  151. if (!$uid) {
  152. throw new ValidateException('获取用户UID失败');
  153. }
  154. $kefuInfo = $this->dao->get(['uid' => $uid]);
  155. if (!$kefuInfo) {
  156. throw new ValidateException('客服不存在');
  157. }
  158. if (!$kefuInfo->status) {
  159. throw new ValidateException('您已被禁止登录');
  160. }
  161. $token = $this->createToken($kefuInfo->id, 'kefu');
  162. $kefuInfo->update_time = time();
  163. $kefuInfo->ip = request()->ip();
  164. $kefuInfo->save();
  165. return [
  166. 'token' => $token['token'],
  167. 'exp_time' => $token['params']['exp'],
  168. 'kefuInfo' => $kefuInfo->hidden(['password', 'ip', 'update_time', 'add_time', 'status', 'mer_id', 'customer', 'notify'])->toArray()
  169. ];
  170. }
  171. /**
  172. * 检测有没有人扫描登录
  173. * @param string $key
  174. * @return array|int[]
  175. * @throws \Psr\SimpleCache\InvalidArgumentException
  176. * @throws \think\db\exception\DataNotFoundException
  177. * @throws \think\db\exception\DbException
  178. * @throws \think\db\exception\ModelNotFoundException
  179. */
  180. public function scanLogin(string $key)
  181. {
  182. $hasKey = Cache::has($key);
  183. if ($hasKey === false) {
  184. $status = 0;//不存在需要刷新二维码
  185. } else {
  186. $keyValue = CacheService::get($key);
  187. if ($keyValue === '0') {
  188. $status = 1;//正在扫描中
  189. $kefuInfo = $this->dao->get(['uniqid' => $key], ['account', 'uniqid']);
  190. if ($kefuInfo) {
  191. $tokenInfo = $this->authLogin($kefuInfo->account);
  192. $tokenInfo['status'] = 3;
  193. $kefuInfo->uniqid = '';
  194. $kefuInfo->save();
  195. CacheService::delete($key);
  196. return $tokenInfo;
  197. }
  198. } else {
  199. $status = 2;//没有扫描
  200. }
  201. }
  202. return ['status' => $status];
  203. }
  204. }