OutAccountServices.php 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2023 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\out;
  12. use app\dao\out\OutAccountDao;
  13. use app\services\BaseServices;
  14. use crmeb\exceptions\AdminException;
  15. use crmeb\exceptions\AuthException;
  16. use crmeb\services\CacheService;
  17. use crmeb\services\FormBuilder as Form;
  18. use crmeb\services\HttpService;
  19. use crmeb\utils\JwtAuth;
  20. use Firebase\JWT\ExpiredException;
  21. /**
  22. * 获取token
  23. * Class LoginServices
  24. * @package app\services\kefu
  25. * @method get($id, ?array $field = [], ?array $with = []) 获取一条数据
  26. * @method update($id, array $data, ?string $key = null)
  27. * @method save(array $data)保存
  28. */
  29. class OutAccountServices extends BaseServices
  30. {
  31. /**
  32. * LoginServices constructor.
  33. * @param OutAccountDao $dao
  34. */
  35. public function __construct(OutAccountDao $dao)
  36. {
  37. $this->dao = $dao;
  38. }
  39. /**
  40. * 账号密码登录
  41. * @param string $appid
  42. * @param string $appsecret
  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 $appid, string $appsecret = null)
  49. {
  50. $autInfo = $this->dao->get(['appid' => $appid, 'is_del' => 0]);
  51. if (!$autInfo) {
  52. throw new AuthException(410141);
  53. }
  54. if ($appsecret && !password_verify($appsecret, $autInfo->appsecret)) {
  55. throw new AuthException(400744);
  56. }
  57. if ($autInfo->status == 0) {
  58. throw new AuthException(400595);
  59. }
  60. $token = $this->createToken($autInfo->id, 'out');
  61. $data['last_time'] = time();
  62. $data['ip'] = request()->ip();
  63. $this->update($autInfo['id'], $data);
  64. return [
  65. 'access_token' => $token['token'],
  66. 'exp_time' => $token['params']['exp'],
  67. 'auth_info' => $autInfo->hidden(['appsecret', 'ip', 'is_del', 'add_time', 'status', 'last_time'])->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 CacheService $cacheService */
  82. $cacheService = app()->make(CacheService::class);
  83. /** @var JwtAuth $jwtAuth */
  84. $jwtAuth = app()->make(JwtAuth::class);
  85. //获取token信息
  86. [$md5Token, $id, $type] = $this->verifyToken($token, $jwtAuth, $cacheService);
  87. //获取对外账号
  88. $authInfo = $this->dao->getOne(['id' => $id, 'is_del' => 0]);
  89. $this->checkAuth($authInfo, $md5Token, $cacheService);
  90. return $authInfo->hidden(['appsecret', 'ip', 'is_del', 'add_time', 'status', 'last_time'])->toArray();
  91. }
  92. /**
  93. * 获取一条
  94. * @return array|\think\Model|null
  95. * @throws \think\db\exception\DataNotFoundException
  96. * @throws \think\db\exception\DbException
  97. * @throws \think\db\exception\ModelNotFoundException
  98. */
  99. public function getOne($where = [])
  100. {
  101. $info = $this->dao->getOne($where);
  102. return $info ? $info->toArray() : [];
  103. }
  104. /**
  105. * 获取列表
  106. * @param array $where
  107. * @return array
  108. * @throws \think\db\exception\DataNotFoundException
  109. * @throws \think\db\exception\DbException
  110. * @throws \think\db\exception\ModelNotFoundException
  111. */
  112. public function getList(array $where = [])
  113. {
  114. [$page, $limit] = $this->getPageValue();
  115. $where['is_del'] = 0;
  116. $list = $this->dao->getList($where, $page, $limit);
  117. $count = $this->dao->count($where);
  118. if ($list) {
  119. foreach ($list as &$item) {
  120. $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '暂无';
  121. $item['last_time'] = $item['last_time'] ? date('Y-m-d H:i:s', $item['last_time']) : '暂无';
  122. $item['rules'] = is_null($item['rules']) ? [] : explode(',', $item['rules']);
  123. }
  124. }
  125. return compact('count', 'list');
  126. }
  127. /**
  128. * 刷新token
  129. * @param string $token
  130. * @return array
  131. * @throws \Psr\SimpleCache\InvalidArgumentException
  132. * @throws \think\db\exception\DataNotFoundException
  133. * @throws \think\db\exception\DbException
  134. * @throws \think\db\exception\ModelNotFoundException
  135. */
  136. public function refresh(string $token): array
  137. {
  138. /** @var CacheService $cacheService */
  139. $cacheService = app()->make(CacheService::class);
  140. /** @var JwtAuth $jwtAuth */
  141. $jwtAuth = app()->make(JwtAuth::class);
  142. //获取token信息
  143. [$md5Token, $id, $type] = $this->verifyToken($token, $jwtAuth, $cacheService);
  144. //获取对外账号
  145. $authInfo = $this->dao->getOne(['id' => $id, 'is_del' => 0]);
  146. $this->checkAuth($authInfo, $md5Token, $cacheService);
  147. $cacheService->delete($md5Token);
  148. $token = $jwtAuth->createToken($id, $type);
  149. $data['last_time'] = time();
  150. $data['ip'] = request()->ip();
  151. $this->dao->update($id, $data);
  152. return [
  153. 'access_token' => $token['token'],
  154. 'exp_time' => $token['params']['exp'],
  155. ];
  156. }
  157. /**
  158. * 核对用户
  159. * @param $authInfo
  160. * @param string $md5Token
  161. * @param CacheService $cacheService
  162. * @return bool
  163. */
  164. protected function checkAuth($authInfo, string $md5Token, CacheService $cacheService): bool
  165. {
  166. if (!$authInfo) {
  167. if (!request()->isCli()) {
  168. $cacheService->delete($md5Token);
  169. }
  170. throw new AuthException(110003);
  171. }
  172. if ($authInfo->status == 2) {
  173. if (!request()->isCli()) {
  174. $cacheService->delete($md5Token);
  175. }
  176. throw new AuthException(400595);
  177. }
  178. return true;
  179. }
  180. /**
  181. * 获取token
  182. * @param string $token
  183. * @param JwtAuth $jwtAuth
  184. * @param CacheService $cacheService
  185. * @return array
  186. * @throws \Psr\SimpleCache\InvalidArgumentException
  187. */
  188. protected function verifyToken(string $token, JwtAuth $jwtAuth, CacheService $cacheService): array
  189. {
  190. if (!$token || $token === 'undefined') {
  191. throw new AuthException(400172);
  192. }
  193. $md5Token = md5($token);
  194. if (!$cacheService->has($md5Token) || !($cacheToken = $cacheService->get($md5Token, '', NULL, 'out'))) {
  195. throw new AuthException(110006);
  196. }
  197. //解析token
  198. [$id, $type] = $jwtAuth->parseToken($token);
  199. if (!$id || $type != 'out') {
  200. throw new AuthException(400172);
  201. }
  202. try {
  203. $jwtAuth->verifyToken();
  204. } catch (\Throwable $e) {
  205. if (!request()->isCli()) {
  206. $cacheService->delete($md5Token);
  207. }
  208. throw new AuthException(400172);
  209. }
  210. return [$md5Token, $id, $type];
  211. }
  212. /**
  213. * 设置账号推送接口
  214. * @param $id
  215. * @param $data
  216. * @return \crmeb\basic\BaseModel
  217. */
  218. public function outSetUpSave($id, $data)
  219. {
  220. return $this->dao->update($id, $data);
  221. }
  222. /**
  223. * 测试获取token接口
  224. * @param $data
  225. * @return int[]|mixed
  226. */
  227. public function textOutUrl($data)
  228. {
  229. if (!$data['push_account'] || !$data['push_password'] || !$data['push_token_url']) throw new AdminException(100100);
  230. $param = ['push_account' => $data['push_account'], 'push_password' => $data['push_password']];
  231. $res = HttpService::getRequest($data['push_token_url'], $param);
  232. $res = $res ? json_decode($res, true) : ['status' => 400];
  233. if (!isset($res['status']) && $res['status'] != 200) {
  234. throw new AdminException(100015);
  235. } else {
  236. return $res['data'];
  237. }
  238. }
  239. }