Account.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. namespace app\api\controller;
  3. use ba\Date;
  4. use Throwable;
  5. use ba\Captcha;
  6. use ba\Random;
  7. use app\common\model\User;
  8. use think\facade\Validate;
  9. use app\common\facade\Token;
  10. use app\common\model\UserScoreLog;
  11. use app\common\model\UserMoneyLog;
  12. use app\common\controller\Frontend;
  13. use app\api\validate\Account as AccountValidate;
  14. class Account extends Frontend
  15. {
  16. protected array $noNeedLogin = ['retrievePassword'];
  17. public function initialize(): void
  18. {
  19. parent::initialize();
  20. }
  21. public function overview(): void
  22. {
  23. $sevenDays = Date::unixTime('day', -6);
  24. $score = $money = $days = [];
  25. for ($i = 0; $i < 7; $i++) {
  26. $days[$i] = date("Y-m-d", $sevenDays + ($i * 86400));
  27. $tempToday0 = strtotime($days[$i]);
  28. $tempToday24 = strtotime('+1 day', $tempToday0) - 1;
  29. $score[$i] = UserScoreLog::where('user_id', $this->auth->id)
  30. ->where('create_time', 'BETWEEN', $tempToday0 . ',' . $tempToday24)
  31. ->sum('score');
  32. $userMoneyTemp = UserMoneyLog::where('user_id', $this->auth->id)
  33. ->where('create_time', 'BETWEEN', $tempToday0 . ',' . $tempToday24)
  34. ->sum('money');
  35. $money[$i] = bcdiv($userMoneyTemp, 100, 2);
  36. }
  37. $this->success('', [
  38. 'days' => $days,
  39. 'score' => $score,
  40. 'money' => $money,
  41. ]);
  42. }
  43. /**
  44. * 会员资料
  45. * @throws Throwable
  46. */
  47. public function profile(): void
  48. {
  49. if ($this->request->isPost()) {
  50. $data = $this->request->only(['id', 'avatar', 'username', 'nickname', 'gender', 'birthday', 'motto']);
  51. if (!isset($data['birthday'])) $data['birthday'] = null;
  52. try {
  53. $validate = new AccountValidate();
  54. $validate->scene('edit')->check($data);
  55. } catch (Throwable $e) {
  56. $this->error($e->getMessage());
  57. }
  58. $model = $this->auth->getUser();
  59. $model->startTrans();
  60. try {
  61. $model->save($data);
  62. $model->commit();
  63. } catch (Throwable $e) {
  64. $model->rollback();
  65. $this->error($e->getMessage());
  66. }
  67. $this->success(__('Data updated successfully~'));
  68. }
  69. $this->success('', [
  70. 'accountVerificationType' => get_account_verification_type()
  71. ]);
  72. }
  73. /**
  74. * 通过手机号或邮箱验证账户
  75. * 此处检查的验证码是通过 api/Ems或api/Sms发送的
  76. * 验证成功后,向前端返回一个 email-pass Token或着 mobile-pass Token
  77. * 在 changBind 方法中,通过 pass Token来确定用户已经通过了账户验证(用户未绑定邮箱/手机时通过账户密码验证)
  78. * @throws Throwable
  79. */
  80. public function verification(): void
  81. {
  82. $captcha = new Captcha();
  83. $params = $this->request->only(['type', 'captcha']);
  84. if ($captcha->check($params['captcha'], ($params['type'] == 'email' ? $this->auth->email : $this->auth->mobile) . "user_{$params['type']}_verify")) {
  85. $uuid = Random::uuid();
  86. Token::set($uuid, $params['type'] . '-pass', $this->auth->id, 600);
  87. $this->success('', [
  88. 'type' => $params['type'],
  89. 'accountVerificationToken' => $uuid,
  90. ]);
  91. }
  92. $this->error(__('Please enter the correct verification code'));
  93. }
  94. /**
  95. * 修改绑定信息(手机号、邮箱)
  96. * 通过 pass Token来确定用户已经通过了账户验证,也就是以上的 verification 方法,同时用户未绑定邮箱/手机时通过账户密码验证
  97. * @throws Throwable
  98. */
  99. public function changeBind(): void
  100. {
  101. $captcha = new Captcha();
  102. $params = $this->request->only(['type', 'captcha', 'email', 'mobile', 'accountVerificationToken', 'password']);
  103. $user = $this->auth->getUser();
  104. if ($user[$params['type']]) {
  105. if (!Token::check($params['accountVerificationToken'], $params['type'] . '-pass', $user->id, false)) {
  106. $this->error(__('You need to verify your account before modifying the binding information'));
  107. }
  108. } else {
  109. // 验证账户密码
  110. if (!isset($params['password']) || $user->password != encrypt_password($params['password'], $user->salt)) {
  111. $this->error(__('Password error'));
  112. }
  113. }
  114. // 检查验证码
  115. if ($captcha->check($params['captcha'], $params[$params['type']] . "user_change_{$params['type']}")) {
  116. if ($params['type'] == 'email') {
  117. $validate = Validate::rule(['email' => 'require|email|unique:user'])->message([
  118. 'email.require' => 'email format error',
  119. 'email.email' => 'email format error',
  120. 'email.unique' => 'email is occupied',
  121. ]);
  122. if (!$validate->check(['email' => $params['email']])) {
  123. $this->error(__($validate->getError()));
  124. }
  125. $user->email = $params['email'];
  126. } elseif ($params['type'] == 'mobile') {
  127. $validate = Validate::rule(['mobile' => 'require|mobile|unique:user'])->message([
  128. 'mobile.require' => 'mobile format error',
  129. 'mobile.mobile' => 'mobile format error',
  130. 'mobile.unique' => 'mobile is occupied',
  131. ]);
  132. if (!$validate->check(['mobile' => $params['mobile']])) {
  133. $this->error(__($validate->getError()));
  134. }
  135. $user->mobile = $params['mobile'];
  136. }
  137. Token::delete($params['accountVerificationToken']);
  138. $user->save();
  139. $this->success();
  140. }
  141. $this->error(__('Please enter the correct verification code'));
  142. }
  143. public function changePassword(): void
  144. {
  145. if ($this->request->isPost()) {
  146. $params = $this->request->only(['oldPassword', 'newPassword']);
  147. if (!$this->auth->checkPassword($params['oldPassword'])) {
  148. $this->error(__('Old password error'));
  149. }
  150. $model = $this->auth->getUser();
  151. $model->startTrans();
  152. try {
  153. $validate = new AccountValidate();
  154. $validate->scene('changePassword')->check(['password' => $params['newPassword']]);
  155. $model->resetPassword($this->auth->id, $params['newPassword']);
  156. $model->commit();
  157. } catch (Throwable $e) {
  158. $model->rollback();
  159. $this->error($e->getMessage());
  160. }
  161. $this->auth->logout();
  162. $this->success(__('Password has been changed, please login again~'));
  163. }
  164. }
  165. /**
  166. * 积分日志
  167. * @throws Throwable
  168. */
  169. public function integral(): void
  170. {
  171. $limit = $this->request->request('limit');
  172. $integralModel = new UserScoreLog();
  173. $res = $integralModel->where('user_id', $this->auth->id)
  174. ->order('create_time desc')
  175. ->paginate($limit);
  176. $this->success('', [
  177. 'list' => $res->items(),
  178. 'total' => $res->total(),
  179. ]);
  180. }
  181. /**
  182. * 余额日志
  183. * @throws Throwable
  184. */
  185. public function balance(): void
  186. {
  187. $limit = $this->request->request('limit');
  188. $moneyModel = new UserMoneyLog();
  189. $res = $moneyModel->where('user_id', $this->auth->id)
  190. ->order('create_time desc')
  191. ->paginate($limit);
  192. $this->success('', [
  193. 'list' => $res->items(),
  194. 'total' => $res->total(),
  195. ]);
  196. }
  197. /**
  198. * 找回密码
  199. * @throws Throwable
  200. */
  201. public function retrievePassword(): void
  202. {
  203. $params = $this->request->only(['type', 'account', 'captcha', 'password']);
  204. try {
  205. $validate = new AccountValidate();
  206. $validate->scene('retrievePassword')->check($params);
  207. } catch (Throwable $e) {
  208. $this->error($e->getMessage());
  209. }
  210. if ($params['type'] == 'email') {
  211. $user = User::where('email', $params['account'])->find();
  212. } else {
  213. $user = User::where('mobile', $params['account'])->find();
  214. }
  215. if (!$user) {
  216. $this->error(__('Account does not exist~'));
  217. }
  218. $captchaObj = new Captcha();
  219. if (!$captchaObj->check($params['captcha'], $params['account'] . 'user_retrieve_pwd')) {
  220. $this->error(__('Please enter the correct verification code'));
  221. }
  222. if ($user->resetPassword($user->id, $params['password'])) {
  223. $this->success(__('Password has been changed~'));
  224. } else {
  225. $this->error(__('Failed to modify password, please try again later~'));
  226. }
  227. }
  228. }