321 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			321 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			PHP
		
	
	
| <?php
 | |
| namespace app\controller\api;
 | |
| 
 | |
| use app\exception\RepositoryException;
 | |
| use app\model\Account;
 | |
| use app\repository\AccountRepository;
 | |
| use app\repository\BusinessRepository;
 | |
| use app\repository\CouponRepository;
 | |
| use app\service\File;
 | |
| use app\service\Jwt;
 | |
| use app\service\Tool;
 | |
| use app\service\wx\WechatApplets;
 | |
| use app\validate\User as UserValidate;
 | |
| use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
 | |
| use Exception;
 | |
| use think\exception\ValidateException;
 | |
| use think\facade\Config;
 | |
| use think\response\Json;
 | |
| 
 | |
| /**
 | |
|  * 用户相关
 | |
|  *
 | |
|  * Class User
 | |
|  * @package app\controller\api
 | |
|  */
 | |
| class User extends Base
 | |
| {
 | |
|     protected $noNeedLogin = [
 | |
|         'login','checkNewAccount',"decodeMobile"
 | |
|     ];
 | |
| 
 | |
|     /**
 | |
|      * 登录  成功返回token及用户信息
 | |
|      *
 | |
|      * @return Json
 | |
|      * @throws InvalidConfigException
 | |
|      */
 | |
|     public function login(): Json
 | |
|     {
 | |
|         $params = [
 | |
|             'code'          => $this->request->param('code', ''),
 | |
|             'nick_name'     => $this->request->param('nickName', ''),
 | |
|             'avatar_url'    => $this->request->param('avatarUrl', ''),
 | |
|             'gender'        => $this->request->param('gender/d', 0),
 | |
|             'real_name'     => $this->request->param('real_name/s', '',"trim"),
 | |
|             'mobile'        => $this->request->param('mobile/s', ''),
 | |
|             'lat'           => $this->request->param('lat/f', 0),
 | |
|             'lng'           => $this->request->param('lng/f', 0),
 | |
|         ];
 | |
| 
 | |
|         $validate = new UserValidate();
 | |
|         if (!$validate->scene('wx_applets')->check($params)) {
 | |
|             return $this->json(4000, $validate->getError());
 | |
|         }
 | |
|         $minApp = WechatApplets::getInstance();
 | |
|         $jsCode = $params['code'];
 | |
|         $wxUser = $minApp->auth->session($jsCode);
 | |
| 
 | |
|         if (isset($wxUser['errcode']) && $wxUser['errcode'] != 0) {
 | |
|             return $this->json(4001, $wxUser['errcode'].';'.$wxUser['errmsg'] ?? '登录失败');
 | |
|         }
 | |
|         // $wxUser success has [session_key, openid, unionid]
 | |
|         // 有效期2小时
 | |
|         $wxUser['expire_time'] = time() + 7200;
 | |
|         $wxUser['session_key'] = $wxUser['session_key'] ?? '';
 | |
|         $openID                = $wxUser['openid'] ?? '';
 | |
| 
 | |
|         if (empty($openID)) {
 | |
|             return $this->json(4002, '登录失败');
 | |
|         }
 | |
| 
 | |
|         try {
 | |
|             $repo       = AccountRepository::getInstance();
 | |
|             $account    = $repo->findByOpenID($openID);
 | |
|             $nowDate    = date('Y-m-d H:i:s');
 | |
| 
 | |
|             if (!$account) {
 | |
|                 if(empty($params['real_name'])){
 | |
|                     return $this->json(4001, '真实姓名不能为空');
 | |
|                 }
 | |
|                 if(!is_mobile($params['mobile'])){
 | |
|                     return $this->json(4001, '手机号格式错误');
 | |
|                 }
 | |
|                 // 自动注册
 | |
|                 $account = $repo->create([
 | |
|                     'user_code'         => createUuid(), // 用户UUID
 | |
|                     'open_id'           => $openID,
 | |
|                     'create_time'       => $nowDate,
 | |
|                     'login_time'        => $nowDate,
 | |
|                     'type'              => Account::type_consumer, // 默认为普通消费者
 | |
|                     'nick_name'         => $params['nick_name'] ?: generateDefaultNickName(),
 | |
|                     'avatar_url'        => $params['avatar_url'] ?: Account::DEFAULT_AVATAR,
 | |
|                     'gender'            => $params['gender'],
 | |
|                     'real_name'         => $params['real_name'],
 | |
|                     'mobile'            => $params['mobile'],
 | |
|                     'lat'               => $params['lat'],
 | |
|                     'lng'               => $params['lng'],
 | |
|                 ]);
 | |
| 
 | |
|             } else {
 | |
|                 $updateData     = [
 | |
|                     'login_time'    => $nowDate,
 | |
|                     'lat'           => empty($account->lat)?$params['lat']   :$account->lat,//如果之前的位置信息是空的
 | |
|                     'lng'           => empty($account->lng)?$params['lng']   :$account->lng,//如果之前的位置信息是空的
 | |
|                     'mobile'        => (!is_mobile($account->mobile))?$params['mobile']:$account->mobile,//如果之前的电话信息是空的
 | |
|                     'real_name'     => empty($account->real_name)?$params['real_name']:$account->real_name,//如果之前的电话信息是空的
 | |
|                 ];
 | |
| 
 | |
|                 // 更新资料
 | |
|                 $modifyStringList = ['nick_name', 'avatar_url'];
 | |
|                 foreach ($modifyStringList as $modifyKey) {
 | |
|                     if (isset($params[$modifyKey]) && !empty($params[$modifyKey])) {
 | |
|                         $updateData[$modifyKey] = $params[$modifyKey];
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 $repo->update($updateData, ['id' => $account['id']]);
 | |
|                 $account = $repo->findById($account['id']);
 | |
|             }
 | |
| 
 | |
|         } catch (RepositoryException | Exception $e) {
 | |
|             return $this->json(4003, '登录失败!'.$e->getMessage());
 | |
|         }
 | |
| 
 | |
|         $account = $account->toArray();
 | |
|         $account['avatar_url'] = File::convertCompleteFileUrl($account['avatar_url']);
 | |
|         $jwtData = [
 | |
|             'user_id'       => $account['id'],
 | |
|             'user_code'     => $account['user_code'],
 | |
|             'open_id'       => $openID,
 | |
|             'session_key'   => $wxUser['session_key'],
 | |
|             'expire_time'   => $wxUser['expire_time'],
 | |
|         ];
 | |
| 
 | |
| 
 | |
|         $data   = [
 | |
|             'avatar'        => File::convertCompleteFileUrl($account['avatar_url']),
 | |
|             'nickName'      => $account['nick_name'],
 | |
|             'token'         => Jwt::generate($jwtData),
 | |
|             'userType'      => $account['type'],
 | |
|             'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
 | |
|         ];
 | |
|         return $this->json(0, 'success', $data);
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * 获取个人中心资料
 | |
|      */
 | |
|     public function getUserCenterInfo()
 | |
|     {
 | |
|         $accountId = $this->request->user['user_id'] ?? 0;
 | |
| 
 | |
|         try {
 | |
|             $accountRepo    = AccountRepository::getInstance();
 | |
|             $couponRepo     = CouponRepository::getInstance();
 | |
|             $busRepo        = BusinessRepository::getInstance();
 | |
| 
 | |
|             $account        = $accountRepo->findById($accountId, [], function ($q) {
 | |
|                 return $q->with(['business', 'parent']);
 | |
|             });
 | |
|             if (empty($account)) {
 | |
|                 throw new ValidateException('用户无效!');
 | |
|             }
 | |
| 
 | |
|             if ($account['type'] == Account::type_business) {
 | |
|                 // 商家用户
 | |
|                 if (empty($account['business'])) {
 | |
|                     throw new ValidateException('用户无效!没有相关的商户信息记录');
 | |
|                 }
 | |
| 
 | |
|                 $businessRes    = [
 | |
|                     'avatar'    => File::convertCompleteFileUrl($account['avatar_url']),
 | |
|                     'nickName'  => $account['nick_name'],
 | |
|                     'userType'  => $account['type'],
 | |
|                     'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
 | |
|                     'couponCount'   => 0,
 | |
|                     'business'      => [
 | |
|                         'code'          => $account['business']['code'],
 | |
|                         'businessName'  => $account['business']['business_name'],
 | |
|                         'state'         => $account['business']['state'],
 | |
|                         'reason'        => $account['business']['reason'],
 | |
|                         'balance'       => $account['business']['balance'],
 | |
|                         'enable'        => $account['business']['enable'],
 | |
|                         // 商家优惠卷情况统计
 | |
|                         'couponCountList'   => $busRepo->getCountBusinessOnShelf($account['business']['code'], 29),
 | |
|                     ],
 | |
|                     "alertMoney"=>config("wechat.balance"),
 | |
|                     "redPrice"=>CouponRepository::getInstance()->getUserRedPrice( $account['user_code']),
 | |
|                 ];
 | |
| 
 | |
|                 return $this->json(0, 'success', $businessRes);
 | |
|             } else {
 | |
|                 // 用户领取的优惠卷总数量
 | |
|                 $couponCount    = $couponRepo->getModel()::getCountByWhere(['consumer_code' => $account['user_code']]);
 | |
|                 $personalRes    = [
 | |
|                     'avatar'    => File::convertCompleteFileUrl($account['avatar_url']),
 | |
|                     'nickName'  => $account['nick_name'],
 | |
|                     'userType'  => $account['type'],
 | |
|                     'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
 | |
|                     'couponCount'   => $couponCount,
 | |
|                     "alertMoney"=>config("wechat.balance"),
 | |
|                     "redPrice"=>CouponRepository::getInstance()->getUserRedPrice( $account['user_code']),
 | |
| 
 | |
|                 ];
 | |
| 
 | |
| 
 | |
|                 if ($account['type'] == Account::type_staff) {
 | |
|                     // 员工
 | |
|                     $businessCode = $account['parent']['business_code'] ?? '';
 | |
|                     if (!empty($businessCode)) {
 | |
|                         $business = $busRepo->findOneByWhere(['code' => $businessCode]);
 | |
|                         if ($business) {
 | |
|                             $personalRes['business'] = [
 | |
|                                 'code'          => $business['code'],
 | |
|                                 'businessName'  => $business['business_name'],
 | |
|                                 'state'         => $business['state'],
 | |
|                                 'reason'        => $business['reason'],
 | |
|                                 'balance'       => $business['balance'],
 | |
|                                 'enable'        => $business['enable'],
 | |
|                             ];
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     $personalRes['parent'] = [];
 | |
|                     if (!empty($account['parent'])) {
 | |
|                         $personalRes['parent'] = [
 | |
|                             'avatar'    => File::convertCompleteFileUrl($account['parent']['avatar_url']),
 | |
|                             'nickName'  => $account['parent']['nick_name'],
 | |
|                             'userType'  => $account['parent']['type'],
 | |
|                             'userTypeDes'   => Account::accountTypeDescList()[$account['parent']['type']] ?? '',
 | |
|                             'couponCount'   => 0,
 | |
|                             'businessCode'  => $account['parent']['business_code'],
 | |
|                         ];
 | |
|                     }
 | |
| 
 | |
|                 } elseif(!empty($account['business'])) {
 | |
|                     // 商户认证记录
 | |
|                     $personalRes['business'] = [
 | |
|                         'state'     => $account['business']['state'],
 | |
|                         'reason'    => $account['business']['reason'],
 | |
|                     ];
 | |
|                 }
 | |
| 
 | |
|                 return $this->json(0, 'success', $personalRes);
 | |
|             }
 | |
| 
 | |
|         } catch (ValidateException $e) {
 | |
|             return $this->json(4001, $e->getError());
 | |
|         } catch (Exception $e) {
 | |
|             return $this->json(5001, '服务器繁忙!获取用户个人信息失败'.$e->getMessage());
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     //检查是新用户还是老用户
 | |
|     public function checkNewAccount()
 | |
|     {
 | |
|         Config::load('extra/wechat', 'wechat');
 | |
|         $config = config('wechat');
 | |
|         $code = $this->request->param('code/s');
 | |
|         $appId = $config["applets_appId"]??'';//appid
 | |
|         $appSecret = $config["applets_appSecret"]??'';//appsecret
 | |
|         $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='
 | |
|             . $appId
 | |
|             . '&secret='
 | |
|             . $appSecret
 | |
|             . '&js_code='
 | |
|             . $code
 | |
|             . '&grant_type=authorization_code';
 | |
|         $data = json_decode(Tool::httpRequest($url, "get"), true);
 | |
| 
 | |
|         //返回状态
 | |
|         if (isset($data["openid"])) {
 | |
|             $account = AccountRepository::getInstance()->findByOpenID($data["openid"]);
 | |
|             if(empty($account)){
 | |
|                 return $this->json(0, "success",[
 | |
|                     "showMobile"=>true,
 | |
|                     "showRealName"=>true,
 | |
|                     "session_key"=>$data["session_key"]]);
 | |
|             }
 | |
|             return $this->json(0, "success",[
 | |
|                 "showMobile"=>is_mobile($account->mobile)?false:true,
 | |
|                 "showRealName"=>(!empty($account->real_name))?false:true,
 | |
|                 "session_key"=>$data["session_key"]
 | |
|             ]);
 | |
|         }
 | |
|         return $this->json(5001, "获取登录状态失败", ["showMobile"=>true,
 | |
|                 "showRealName"=>true,
 | |
|                 "session_key"=>'']);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 解密手机号
 | |
|      * */
 | |
|     public function decodeMobile()
 | |
|     {
 | |
|         $params    = input('post.');
 | |
|         $rules = [
 | |
|             'encryptedData|加密数据'        => 'require',
 | |
|             'iv|IV'                         => 'require',
 | |
|             'session_key|会话标识'          => 'require',
 | |
|         ];
 | |
| 
 | |
|         $validate = $this->validateByApi($params, $rules);
 | |
| 
 | |
|         if ($validate !== true) {
 | |
|             return $validate;
 | |
|         }
 | |
| 
 | |
|         // 解密手机相关数据
 | |
|         $minApp      = WechatApplets::getInstance();
 | |
|         $sessionKey  = $params['session_key'] ?? '';
 | |
|         $decryptData = $minApp->encryptor->decryptData($sessionKey, $params['iv'], $params['encryptedData']);
 | |
|         $phone       = $decryptData['phoneNumber'] ?? ''; // 通过iv和加密数据 解密出手机号
 | |
| 
 | |
|         if ($phone) {
 | |
|          return $this->json(0,"success",["mobile"=>$phone]);
 | |
|         }
 | |
|         return $this->json(5001,"获取手机号失败");
 | |
|     }
 | |
| 
 | |
| } |