Account.php 9.0 KB

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