MerchantAdminRepository.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <?php
  2. namespace app\common\repositories\system\merchant;
  3. use app\common\dao\BaseDao;
  4. use app\common\dao\system\merchant\MerchantAdminDao;
  5. use app\common\model\system\merchant\Merchant;
  6. use app\common\model\system\merchant\MerchantAdmin;
  7. use app\common\repositories\BaseRepository;
  8. use app\common\repositories\system\auth\RoleRepository;
  9. use ln\exceptions\AuthException;
  10. use ln\services\JwtTokenService;
  11. use FormBuilder\Exception\FormBuilderException;
  12. use FormBuilder\Factory\Elm;
  13. use FormBuilder\Form;
  14. use think\db\exception\DataNotFoundException;
  15. use think\db\exception\DbException;
  16. use think\db\exception\ModelNotFoundException;
  17. use think\exception\ValidateException;
  18. use think\facade\Cache;
  19. use think\facade\Config;
  20. use think\facade\Route;
  21. use think\Model;
  22. /**
  23. * Class MerchantRepository
  24. * @package app\common\repositories\system\merchant
  25. * @mixin MerchantAdminDao
  26. * @author zfy
  27. * @day 2020-04-16
  28. */
  29. class MerchantAdminRepository extends BaseRepository
  30. {
  31. const PASSWORD_TYPE_ADMIN = 1;
  32. const PASSWORD_TYPE_MERCHANT = 2;
  33. const PASSWORD_TYPE_SELF = 3;
  34. /**
  35. * MerchantAdminRepository constructor.
  36. * @param MerchantAdminDao $dao
  37. */
  38. public function __construct(MerchantAdminDao $dao)
  39. {
  40. $this->dao = $dao;
  41. }
  42. /**
  43. * @param $merId
  44. * @param array $where
  45. * @param $page
  46. * @param $limit
  47. * @return array
  48. * @throws DataNotFoundException
  49. * @throws DbException
  50. * @throws ModelNotFoundException
  51. * @author zfy
  52. * @day 2020-04-18
  53. */
  54. public function getList($merId, array $where, $page, $limit)
  55. {
  56. $query = $this->dao->search($merId, $where, 1);
  57. $count = $query->count();
  58. $list = $query->page($page, $limit)->hidden(['pwd', 'is_del'])->select();
  59. $topAccount = $this->dao->merIdByAccount($merId);
  60. foreach ($list as $k => $role) {
  61. if ($topAccount)
  62. $list[$k]['account'] = $topAccount . '@' . $role['account'];
  63. $list[$k]['rule_name'] = $role->roleNames();
  64. }
  65. return compact('list', 'count');
  66. }
  67. /**
  68. * @param int $merId
  69. * @param int|null $id
  70. * @param array $formData
  71. * @return Form
  72. * @throws FormBuilderException
  73. * @author zfy
  74. * @day 2020-04-18
  75. */
  76. public function form(int $merId, ?int $id = null, array $formData = []): Form
  77. {
  78. $form = Elm::createForm(is_null($id) ? Route::buildUrl('merchantAdminCreate')->build() : Route::buildUrl('merchantAdminUpdate', ['id' => $id])->build());
  79. $rules = [
  80. Elm::select('roles', '身份', [])->options(function () use ($merId) {
  81. $data = app()->make(RoleRepository::class)->getAllOptions($merId);
  82. $options = [];
  83. foreach ($data as $value => $label) {
  84. $options[] = compact('value', 'label');
  85. }
  86. return $options;
  87. })->multiple(true),
  88. Elm::input('real_name', '管理员姓名'),
  89. Elm::input('account', '账号')->required(),
  90. Elm::input('phone', ' 联系电话'),
  91. ];
  92. if (!$id) {
  93. $rules[] = Elm::password('pwd', '密码')->required();
  94. $rules[] = Elm::password('againPassword', '确认密码')->required();
  95. }
  96. $rules[] = Elm::switches('status', '是否开启', 1)->inactiveValue(0)->activeValue(1)->inactiveText('关闭')->activeText('开启');
  97. $form->setRule($rules);
  98. return $form->setTitle(is_null($id) ? '添加管理员' : '编辑管理员')->formData($formData);
  99. }
  100. /**
  101. * @param int $merId
  102. * @param int $id
  103. * @return Form
  104. * @throws DataNotFoundException
  105. * @throws DbException
  106. * @throws FormBuilderException
  107. * @throws ModelNotFoundException
  108. * @author zfy
  109. * @day 2020-04-18
  110. */
  111. public function updateForm(int $merId, int $id)
  112. {
  113. return $this->form($merId, $id, $this->dao->get($id)->toArray());
  114. }
  115. /**
  116. * @param Merchant $merchant
  117. * @param $account
  118. * @param $pwd
  119. * @return BaseDao|Model
  120. * @author zfy
  121. * @day 2020-04-17
  122. */
  123. public function createMerchantAccount(Merchant $merchant, $account, $pwd)
  124. {
  125. $pwd = $this->passwordEncode($pwd);
  126. $data = compact('pwd', 'account') + [
  127. 'mer_id' => $merchant->mer_id,
  128. 'real_name' => $merchant->real_name,
  129. 'phone' => $merchant->mer_phone,
  130. 'level' => 0
  131. ];
  132. return $this->create($data);
  133. }
  134. /**
  135. * @param $password
  136. * @return bool|string
  137. * @author zfy
  138. * @day 2020-04-17
  139. */
  140. public function passwordEncode($password)
  141. {
  142. return password_hash($password, PASSWORD_BCRYPT);
  143. }
  144. /**
  145. * @param string $account
  146. * @param string $password
  147. * @return array|Model|null
  148. * @throws DataNotFoundException
  149. * @throws DbException
  150. * @throws ModelNotFoundException
  151. * @author zfy
  152. * @day 2020-04-17
  153. */
  154. public function login(string $account, string $password)
  155. {
  156. $accountInfo = explode('@', $account, 2);
  157. if (count($accountInfo) === 1) {
  158. $adminInfo = $this->dao->accountByTopAdmin($accountInfo[0]);
  159. } else {
  160. $merId = $this->dao->accountByMerchantId($accountInfo[0]);
  161. if (!$merId)
  162. throw new ValidateException('账号不存在');
  163. $adminInfo = $this->dao->accountByAdmin($accountInfo[1], $merId);
  164. }
  165. if (!$adminInfo)
  166. throw new ValidateException('账号不存在');
  167. if ($adminInfo['status'] != 1)
  168. throw new ValidateException('账号已关闭');
  169. if (!password_verify($password, $adminInfo->pwd)) $this->loginFailure($account);
  170. /**
  171. * @var MerchantRepository $merchantRepository
  172. */
  173. $merchantRepository = app()->make(MerchantRepository::class);
  174. $merchant = $merchantRepository->get($adminInfo->mer_id);
  175. if (!$merchant)
  176. throw new ValidateException('商户不存在');
  177. if (!$merchant['status'])
  178. throw new ValidateException('商户已被锁定');
  179. $adminInfo->last_time = date('Y-m-d H:i:s');
  180. $adminInfo->last_ip = app('request')->ip();
  181. $adminInfo->login_count++;
  182. $adminInfo->save();
  183. return $adminInfo;
  184. }
  185. /**
  186. * TODO 登录尝试次数限制
  187. * @param $account
  188. * @param int $number
  189. * @param int $n
  190. * @author Qinii
  191. * @day 7/6/21
  192. */
  193. public function loginFailure($account,$number = 5,$n = 3)
  194. {
  195. $key = 'mer_login_failuree_'.$account;
  196. $numb = Cache::get($key) ?? 0;
  197. $numb++;
  198. if($numb >= $number){
  199. $fail_key = 'mer_login_freeze_'.$account;
  200. Cache::set($fail_key,1,15*60);
  201. throw new ValidateException('账号或密码错误次数太多,请稍后在尝试');
  202. }else{
  203. Cache::set($key,$numb,5*60);
  204. $msg = '账号或密码错误';
  205. $_n = $number - $numb;
  206. if($_n <= $n){
  207. $msg .= ',还可尝试'.$_n.'次';
  208. }
  209. throw new ValidateException($msg);
  210. }
  211. }
  212. /**
  213. * @param string $token
  214. * @param int $exp
  215. * @author zfy
  216. * @day 2020-04-10
  217. */
  218. public function cacheToken(string $token, int $exp)
  219. {
  220. Cache::set('mer_' . $token, time() + $exp, $exp);
  221. }
  222. /**
  223. * @param string $token
  224. * @author zfy
  225. * @day 2020-04-17
  226. */
  227. public function checkToken(string $token)
  228. {
  229. $has = Cache::has('mer_' . $token);
  230. if (!$has)
  231. throw new AuthException('无效的token');
  232. $lastTime = Cache::get('mer_' . $token);
  233. if (($lastTime + (intval(Config::get('admin.token_valid_exp', 15))) * 60) < time())
  234. throw new AuthException('token 已过期');
  235. }
  236. /**
  237. * @param string $token
  238. * @author zfy
  239. * @day 2020-04-17
  240. */
  241. public function updateToken(string $token)
  242. {
  243. Cache::set('mer_' . $token, time(), intval(Config::get('admin.token_valid_exp', 15)) * 60);
  244. }
  245. /**
  246. * @param string $token
  247. * @author zfy
  248. * @day 2020-04-17
  249. */
  250. public function clearToken(string $token)
  251. {
  252. Cache::delete('mer_' . $token);
  253. }
  254. /**
  255. * @param MerchantAdmin $admin
  256. * @return array
  257. * @author zfy
  258. * @day 2020-04-17
  259. */
  260. public function createToken(MerchantAdmin $admin)
  261. {
  262. $service = new JwtTokenService();
  263. $exp = intval(Config::get('admin.token_exp', 3));
  264. $token = $service->createToken($admin->merchant_admin_id, 'mer', strtotime("+ {$exp}hour"));
  265. $this->cacheToken($token['token'], $token['out']);
  266. return $token;
  267. }
  268. /**
  269. * @param string $key
  270. * @param string $code
  271. * @author zfy
  272. * @day 2020-04-17
  273. */
  274. public function checkCode(string $key, string $code)
  275. {
  276. $_code = Cache::get('am_captcha' . $key);
  277. if (!$_code) {
  278. throw new ValidateException('验证码过期');
  279. }
  280. if (strtolower($_code) != strtolower($code)) {
  281. throw new ValidateException('验证码错误');
  282. }
  283. //删除code
  284. Cache::delete('am_captcha' . $key);
  285. }
  286. /**
  287. * @param string $code
  288. * @return string
  289. * @author zfy
  290. * @day 2020-04-17
  291. */
  292. public function createLoginKey(string $code)
  293. {
  294. $key = uniqid(microtime(true), true);
  295. Cache::set('am_captcha' . $key, $code, Config::get('admin.captcha_exp', 5) * 60);
  296. return $key;
  297. }
  298. /**
  299. * @param int $id
  300. * @param int $userType
  301. * @return Form
  302. * @throws FormBuilderException
  303. * @author zfy
  304. * @day 2020-04-20
  305. */
  306. public function passwordForm(int $id, $userType = 2)
  307. {
  308. $action = 'merchantAdminPassword';
  309. if ($userType == self::PASSWORD_TYPE_ADMIN)
  310. $action = 'systemMerchantAdminPassword';
  311. else if ($userType == self::PASSWORD_TYPE_SELF)
  312. $action = 'merchantAdminEditPassword';
  313. $form = Elm::createForm(Route::buildUrl($action, $userType == self::PASSWORD_TYPE_SELF ? [] : compact('id'))->build(), [
  314. $rules[] = Elm::password('pwd', '密码')->required(),
  315. $rules[] = Elm::password('againPassword', '确认密码')->required(),
  316. ]);
  317. return $form->setTitle('修改密码');
  318. }
  319. /**
  320. * @param array $formData
  321. * @return Form
  322. * @throws FormBuilderException
  323. * @author zfy
  324. * @day 2020-04-20
  325. */
  326. public function editForm(array $formData)
  327. {
  328. $form = Elm::createForm(Route::buildUrl('merchantAdminEdit')->build());
  329. $form->setRule([
  330. Elm::input('real_name', '管理员姓名')->required(),
  331. Elm::input('phone', '联系电话')
  332. ]);
  333. return $form->setTitle('修改信息')->formData($formData);
  334. }
  335. /**
  336. * @param int $id
  337. * @param array $data
  338. * @return int
  339. * @throws DbException
  340. * @author zfy
  341. * @day 2020-04-18
  342. */
  343. public function update(int $id, array $data)
  344. {
  345. if (isset($data['roles']))
  346. $data['roles'] = implode(',', $data['roles']);
  347. return $this->dao->update($id, $data);
  348. }
  349. }