WechatUserService.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeadmin快速开发前后端分离管理后台(PHP版)
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
  8. // | github下载:https://github.com/likeshop-github/likeadmin
  9. // | 访问官网:https://www.likeadmin.cn
  10. // | likeadmin团队 版权所有 拥有最终解释权
  11. // +----------------------------------------------------------------------
  12. // | author: likeadminTeam
  13. // +----------------------------------------------------------------------
  14. namespace app\api\service;
  15. use app\common\enum\YesNoEnum;
  16. use app\common\model\user\{User, UserAuth};
  17. use app\common\enum\user\UserTerminalEnum;
  18. use app\common\service\{ConfigService, storage\Driver as StorageDriver};
  19. use think\Exception;
  20. /**
  21. * 用户功能类(主要微信登录后创建和更新用户)
  22. * Class WechatUserService
  23. * @package app\api\service
  24. */
  25. class WechatUserService
  26. {
  27. protected int $terminal = UserTerminalEnum::WECHAT_MMP;
  28. protected array $response = [];
  29. protected ?string $code = null;
  30. protected ?string $openid = null;
  31. protected ?string $unionid = null;
  32. protected ?string $nickname = null;
  33. protected ?string $headimgurl = null;
  34. protected User $user;
  35. public function __construct(array $response, int $terminal)
  36. {
  37. $this->terminal = $terminal;
  38. $this->setParams($response);
  39. }
  40. /**
  41. * @notes 设置微信返回的用户信息
  42. * @param $response
  43. * @author cjhao
  44. * @date 2021/8/2 11:49
  45. */
  46. private function setParams($response): void
  47. {
  48. $this->response = $response;
  49. $this->openid = $response['openid'];
  50. $this->unionid = $response['unionid'] ?? '';
  51. $this->nickname = $response['nickname'] ?? '';
  52. $this->headimgurl = $response['headimgurl'] ?? '';
  53. }
  54. /**
  55. * @notes 根据opendid或unionid获取系统用户信息
  56. * @return $this
  57. * @author 段誉
  58. * @date 2022/9/23 16:09
  59. */
  60. public function getResopnseByUserInfo(): self
  61. {
  62. $openid = $this->openid;
  63. $unionid = $this->unionid;
  64. $user = User::alias('u')
  65. ->field('u.id,u.sn,u.mobile,u.nickname,u.avatar,u.mobile,u.is_disable,u.is_new_user')
  66. ->join('user_auth au', 'au.user_id = u.id')
  67. ->where(function ($query) use ($openid, $unionid) {
  68. $query->whereOr(['au.openid' => $openid]);
  69. if (isset($unionid) && $unionid) {
  70. $query->whereOr(['au.unionid' => $unionid]);
  71. }
  72. })
  73. ->findOrEmpty();
  74. $this->user = $user;
  75. return $this;
  76. }
  77. /**
  78. * @notes 获取用户信息
  79. * @param bool $isCheck 是否验证账号是否可用
  80. * @return array
  81. * @throws Exception
  82. * @author cjhao
  83. * @date 2021/8/3 11:42
  84. */
  85. public function getUserInfo($isCheck = true): array
  86. {
  87. if (!$this->user->isEmpty() && $isCheck) {
  88. $this->checkAccount();
  89. }
  90. if (!$this->user->isEmpty()) {
  91. $this->getToken();
  92. }
  93. return $this->user->toArray();
  94. }
  95. /**
  96. * @notes 校验账号
  97. * @throws Exception
  98. * @author 段誉
  99. * @date 2022/9/16 10:14
  100. */
  101. private function checkAccount()
  102. {
  103. if ($this->user->is_disable) {
  104. throw new Exception('您的账号异常,请联系客服。');
  105. }
  106. }
  107. /**
  108. * @notes 创建用户
  109. * @throws Exception
  110. * @author 段誉
  111. * @date 2022/9/16 10:06
  112. */
  113. private function createUser(): void
  114. {
  115. //设置头像
  116. if (empty($this->headimgurl)) {
  117. // 默认头像
  118. $defaultAvatar = config('project.default_image.user_avatar');
  119. $avatar = ConfigService::get('default_image', 'user_avatar', $defaultAvatar);
  120. } else {
  121. // 微信获取到的头像信息
  122. $avatar = $this->getAvatarByWechat();
  123. }
  124. $userSn = User::createUserSn();
  125. $this->user->sn = $userSn;
  126. $this->user->account = 'u' . $userSn;
  127. $this->user->nickname = "用户" . $userSn;
  128. $this->user->avatar = $avatar;
  129. $this->user->channel = $this->terminal;
  130. $this->user->is_new_user = YesNoEnum::YES;
  131. if ($this->terminal != UserTerminalEnum::WECHAT_MMP && !empty($this->nickname)) {
  132. $this->user->nickname = $this->nickname;
  133. }
  134. $this->user->save();
  135. UserAuth::create([
  136. 'user_id' => $this->user->id,
  137. 'openid' => $this->openid,
  138. 'unionid' => $this->unionid,
  139. 'terminal' => $this->terminal,
  140. ]);
  141. }
  142. /**
  143. * @notes 更新用户信息
  144. * @throws Exception
  145. * @author 段誉
  146. * @date 2022/9/16 10:06
  147. * @remark 该端没授权信息,重新写入一条该端的授权信息
  148. */
  149. private function updateUser(): void
  150. {
  151. // 无头像需要更新头像
  152. if (empty($this->user->avatar)) {
  153. $this->user->avatar = $this->getAvatarByWechat();
  154. $this->user->save();
  155. }
  156. $userAuth = UserAuth::where(['user_id' => $this->user->id, 'openid' => $this->openid])
  157. ->findOrEmpty();
  158. // 无该端授权信息,新增一条
  159. if ($userAuth->isEmpty()) {
  160. $userAuth->user_id = $this->user->id;
  161. $userAuth->openid = $this->openid;
  162. $userAuth->unionid = $this->unionid;
  163. $userAuth->terminal = $this->terminal;
  164. $userAuth->save();
  165. } else {
  166. if (empty($userAuth['unionid']) && !empty($this->unionid)) {
  167. $userAuth->unionid = $this->unionid;
  168. $userAuth->save();
  169. }
  170. }
  171. }
  172. /**
  173. * @notes 获取token
  174. * @throws \think\db\exception\DataNotFoundException
  175. * @throws \think\db\exception\DbException
  176. * @throws \think\db\exception\ModelNotFoundException
  177. * @author cjhao
  178. * @date 2021/8/2 16:45
  179. */
  180. private function getToken(): void
  181. {
  182. $user = UserTokenService::setToken($this->user->id, $this->terminal);
  183. $this->user->token = $user['token'];
  184. }
  185. /**
  186. * @notes 用户授权登录,
  187. * 如果用户不存在,创建用户;用户存在,更新用户信息,并检查该端信息是否需要写入
  188. * @return WechatUserService
  189. * @throws Exception
  190. * @author cjhao
  191. * @date 2021/8/2 16:35
  192. */
  193. public function authUserLogin(): self
  194. {
  195. if ($this->user->isEmpty()) {
  196. $this->createUser();
  197. } else {
  198. $this->updateUser();
  199. }
  200. return $this;
  201. }
  202. /**
  203. * @notes 处理从微信获取到的头像信息
  204. * @return string
  205. * @throws Exception
  206. * @author 段誉
  207. * @date 2022/9/16 9:50
  208. */
  209. public function getAvatarByWechat(): string
  210. {
  211. // 存储引擎
  212. $config = [
  213. 'default' => ConfigService::get('storage', 'default', 'local'),
  214. 'engine' => ConfigService::get('storage')
  215. ];
  216. $fileName = md5($this->openid . time()) . '.jpeg';
  217. if ($config['default'] == 'local') {
  218. // 本地存储
  219. $avatar = download_file($this->headimgurl, 'uploads/user/avatar/', $fileName);
  220. } else {
  221. // 第三方存储
  222. $avatar = 'uploads/user/avatar/' . $fileName;
  223. $StorageDriver = new StorageDriver($config);
  224. if (!$StorageDriver->fetch($this->headimgurl, $avatar)) {
  225. throw new Exception('头像保存失败:' . $StorageDriver->getError());
  226. }
  227. }
  228. return $avatar;
  229. }
  230. }