330 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			330 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
<?php
 | 
						|
namespace app\controller\api;
 | 
						|
 | 
						|
use app\exception\RepositoryException;
 | 
						|
use app\model\Account;
 | 
						|
use app\model\Business;
 | 
						|
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'     => filterEmoji($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 ( in_array($account['type'],[Account::type_business,Account::type_staff]) ) {
 | 
						|
                // 商家用户
 | 
						|
                if (empty($account['business'])) {
 | 
						|
                    throw new ValidateException('用户无效!没有相关的商户信息记录');
 | 
						|
                }
 | 
						|
 | 
						|
                $businessRes    = [
 | 
						|
                    'avatar'    => File::convertCompleteFileUrl($account['avatar_url']),
 | 
						|
                    'nickName'  => $account['nick_name'],
 | 
						|
                    'user_code' => $account['user_code'],
 | 
						|
                    '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") ?? 300,
 | 
						|
                    "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'],
 | 
						|
                    'user_code'     => $account['user_code'],
 | 
						|
                    'userType'      => $account['type'],
 | 
						|
                    'userTypeDes'   => Account::accountTypeDescList()[$account['type']] ?? '游客',
 | 
						|
                    'couponCount'   => $couponCount,
 | 
						|
                    "alertMoney"    => config("wechat.balance")?? 300,
 | 
						|
                    "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'],
 | 
						|
//                        ];
 | 
						|
//                    }
 | 
						|
//
 | 
						|
//                }
 | 
						|
                $personalRes['business'] =[
 | 
						|
                    "state"     =>  Business::state_consumer,//未认证
 | 
						|
                    "reason"    =>  "",//未认证
 | 
						|
                ];
 | 
						|
                if(!empty($account['business'])) {
 | 
						|
                    // 商户认证记录
 | 
						|
                    $personalRes['business']["state"]   = $account['business']['state'];
 | 
						|
                    $personalRes['business']["reason"]  = $account['business']['reason'];
 | 
						|
                }
 | 
						|
                $personalRes['refundCustomerService']   = config("wechat.refundCustomerService")?? '';
 | 
						|
                return $this->json(0, 'success', $personalRes);
 | 
						|
            }
 | 
						|
 | 
						|
        } catch (ValidateException $e) {
 | 
						|
            return $this->json(4001, $e->getError());
 | 
						|
        } catch (Exception $e) {
 | 
						|
            return $this->json(5001, '服务器繁忙!获取用户个人信息失败');
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    //检查是新用户还是老用户
 | 
						|
    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,"获取手机号失败");
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 静默登录
 | 
						|
     * */
 | 
						|
 | 
						|
} |