354 lines
15 KiB
PHP
354 lines
15 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('用户无效!没有相关的商户信息记录');
|
|
}
|
|
|
|
$businessModel = $account->business["model"];
|
|
// 指定时间段内发布的签到券个数
|
|
$TimeListModeReleaseCount = BusinessRepository::getInstance()
|
|
->getTimeListModeReleaseCount($account->business["code"],$account->business["time_limit_start"],$account->business["time_limit_end"]);
|
|
|
|
if($account->business["model"] == Business::model_time_limit){
|
|
//如果到了时间 或者发布数量到达规定 更改商家模式
|
|
if( strtotime($account->business["time_limit_end"] ) < time()
|
|
||
|
|
($TimeListModeReleaseCount >= $account->business["time_limit_release_count"])
|
|
){
|
|
$businessModel = Business::model_ordinary;
|
|
$account->business->save(["model"=> Business::model_ordinary]);
|
|
}
|
|
}
|
|
|
|
// 指定时间段内发布的签到券个数
|
|
$TimeListModeReleaseCount = BusinessRepository::getInstance()
|
|
->getTimeListModeReleaseCount($account->business["code"],$account->business["time_limit_start"],$account->business["time_limit_end"]);
|
|
|
|
|
|
$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'],
|
|
'model' => $businessModel,
|
|
'time_limit_end' => $account['business']['time_limit_end'],
|
|
'time_limit_release_count' => $account['business']['time_limit_release_count'] - $TimeListModeReleaseCount,
|
|
// 商家优惠卷情况统计
|
|
'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,"获取手机号失败");
|
|
}
|
|
|
|
/**
|
|
* 静默登录
|
|
* */
|
|
|
|
} |