2025-05-15 16:25:33 +08:00

507 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\common\model;
use app\common\library\Auth;
use app\common\library\Sms;
use app\common\model\manystore\UserAuth;
use app\common\model\school\classes\Order;
use app\common\model\school\classes\Teacher;
use app\common\model\school\classes\Verification;
use fast\Random;
use think\Db;
use think\Model;
/**
* 会员模型
*/
class User extends BaseModel
{
// 开启自动写入时间戳字段
protected $autoWriteTimestamp = 'int';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = 'updatetime';
// 追加属性
protected $append = [
'url',
];
/**
* 获取个人URL
* @param string $value
* @param array $data
* @return string
*/
public function getUrlAttr($value, $data)
{
return "/u/" . $data['id'];
}
/**
* 获取头像
* @param string $value
* @param array $data
* @return string
*/
public function getAvatarAttr($value, $data)
{
if (!$value) {
//如果不需要启用首字母头像,请使用
//$value = '/assets/img/avatar.png';
$value = letter_avatar($data['nickname']);
}
return cdnurl($value,true);
}
/**
* 获取会员的组别
*/
public function getGroupAttr($value, $data)
{
return UserGroup::get($data['group_id']);
}
public function usergroup()
{
return $this->belongsTo(UserGroup::class, 'group_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
/**
* 获取验证字段数组值
* @param string $value
* @param array $data
* @return object
*/
public function getVerificationAttr($value, $data)
{
$value = array_filter((array)json_decode($value, true));
$value = array_merge(['email' => 0, 'mobile' => 0, 'wechat_miniapp' => 0], $value);
return (object)$value;
}
/**
* 设置验证字段
* @param mixed $value
* @return string
*/
public function setVerificationAttr($value)
{
$value = is_object($value) || is_array($value) ? json_encode($value) : $value;
return $value;
}
/**
* 变更会员余额
* @param int $money 余额
* @param int $user_id 会员ID
* @param string $memo 备注
*/
public static function money($money, $user_id, $memo,$type='',$ext = [])
{
Db::startTrans();
try {
$user = self::lock(true)->find($user_id);
if ($user && $money != 0) {
$before = $user->money;
//$after = $user->money + $money;
$after = function_exists('bcadd') ? bcadd($user->money, $money, 2) : $user->money + $money;
//更新会员信息
$user->save(['money' => $after]);
//写入日志
MoneyLog::create(['user_id' => $user_id, 'money' => $money, 'before' => $before, 'after' => $after, 'memo' => $memo, 'ext' => $ext?:"","type" =>$type]);
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
}
}
/**
* 变更会员积分
* @param int $score 积分
* @param int $user_id 会员ID
* @param string $memo 备注
*/
public static function score($score, $user_id, $memo,$type='',$ext = [])
{
Db::startTrans();
try {
$user = self::lock(true)->find($user_id);
if ($user && $score != 0) {
$before = $user->score;
$after = $user->score + $score;
$level = self::nextlevel($after);
//更新会员信息
$user->save(['score' => $after, 'level' => $level]);
//写入日志
ScoreLog::create(['user_id' => $user_id, 'score' => $score, 'before' => $before, 'after' => $after, 'memo' => $memo, 'ext' => $ext?:"","type" =>$type]);
}
Db::commit();
} catch (\Exception $e) {
Db::rollback();
}
}
/**
* 根据积分获取等级
* @param int $score 积分
* @return int
*/
public static function nextlevel($score = 0)
{
$lv = array(1 => 0, 2 => 30, 3 => 100, 4 => 500, 5 => 1000, 6 => 2000, 7 => 3000, 8 => 5000, 9 => 8000, 10 => 10000);
$level = 1;
foreach ($lv as $key => $value) {
if ($score >= $value) {
$level = $key;
}
}
return $level;
}
/**是否有核销权限
* @return boolean
*/
public static function verificationAuth($user_id){
$have_auth = false;
//判断用户是否有核销权限
//判断是否是员工
$verification = Verification::where("user_id",$user_id)->where("status",'1')->find();
if($verification)$have_auth = true;
//判断是否是教师
$teacher = Teacher::where("user_id",$user_id)->find();
if($teacher)$have_auth = true;
return $have_auth;
}
/**是否有老师权限
* @return boolean
*/
public static function teacherAuth($user_id){
$have_auth = false;
//判断是否是教师
$teacher = Teacher::where("user_id",$user_id)->find();
if($teacher)$have_auth = true;
return $have_auth;
}
/**检测用户设置密码情况
* @param $user_id
* @param $password
* @param bool $check
*/
public static function checkPayPassword($user_id,$password=null,$check=true){
$user = self::where('id',$user_id)->find();
if(!$user) throw new \Exception("用户不存在!");
// if(!$user["mobile"]) throw new \Exception("您未绑定手机号,请您先去绑定手机号!");
$mobile = $user["mobile"];
$auth = Auth::instance();
//是否设置支付密码
$is_setting = false;
//密码是否正确
$is_right = false;
//检测是否设置支付密码
if($user['pay_password'])$is_setting = true;
if($check){
//校验密码是否正确
$pay_password = $auth->getEncryptPassword($password, $user['pay_salt']);
if($user['pay_password']==$pay_password)$is_right = true;
}
return compact('is_setting','is_right','mobile');
}
/** 设置用户支付密码
* @param $user_id
* @param $code
* @param $password
* @param bool $trans
* @return bool
* @throws \Exception
*/
public static function setPayPassword($user_id, $code,$password,$trans=false,$check_sms=true){
$user = self::where('id',$user_id)->find();
if(!$user) throw new \Exception("用户不存在!");
if($check_sms){
$ret = Sms::check($user['mobile'], $code, 'pay_password');
if (!$ret)throw new \Exception("验证码错误");
}
if(!is_numeric($password) || strlen($password)!=6)throw new \Exception("支付密碼只能設置六位數字!");
//判断逻辑
if($trans){
self::beginTrans();
}
$res = true;
try{
$auth = Auth::instance();
//事务逻辑
$user['pay_salt'] = Random::alnum();
$user['pay_password'] = $auth->getEncryptPassword($password, $user['pay_salt']);
$user->save();
//清除验证码
if($check_sms)Sms::flush($user['mobile'], 'pay_password');
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage());
}
return $res;
}
/**添加用户:通过 手机号 和昵称
* @param $mobile
* @param $nickname
*/
public function addUserByMobile($mobile,$nickname,$check=true){
//去除空格
$nickname = trim($nickname);
$mobile = trim($mobile);
if(!is_numeric($mobile))throw new \Exception("不是合法手机号!");
if(strlen($mobile)!=11)throw new \Exception("请输入11位手机号");
if($check){
if (!preg_match("/[\x7f-\xff]/", $nickname)) throw new \Exception("名称必须是汉字,请去除空格和其他特殊符号!");
preg_match_all("/[\x{4e00}-\x{9fa5}]/u","$nickname",$result);
if(!$result || join('',$result[0])!=$nickname)throw new \Exception("名称必须是汉字,请去除空格和其他特殊符号!");
}
//判断用户存不存在
$user = self::where("mobile",$mobile)->find();
if($user){
//如果存在,直接返回
return $user;
}else{
//如果不存在,创建并返回
//得到认证实例
$auth = Auth::instance();
//拼装提交参数
// $extend = $this->getUserDefaultFields();
$extend=[];
$extend['nickname'] = $nickname;
$extend['avatar'] = config("site.default_avatar");
//调用注册方法
$user = $auth->registerNoLogin("{$mobile}_user", rand(100000,999999), "{$mobile}@user.com", $mobile,$extend);
if(!$user)throw new \Exception($auth->getError());
//更新已认证方式
$user = self::where("id", $user->id)->find();
$verification = $user->verification;
$verification->mobile = 1;
$user->verification = $verification;
$user->save();
//返回对象
return self::where("id", $user->id)->find();
}
}
/**得到基础条件
* @param $status
* @param null $model
* @param string $alisa
*/
public static function getBaseWhere($whereData = [], $model = null, $alisa = '',$with = false)
{
if (!$model) {
$model = new static;
if ($alisa&&!$with) $model = $model->alias($alisa);
}
if ($alisa) $alisa = $alisa . '.';
$tableFields = (new static)->getTableFields();
foreach ($tableFields as $fields)
{
if(in_array($fields, ["id",'status']))continue;
// if (isset($whereData[$fields]) && $whereData[$fields]) $model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
if (isset($whereData[$fields]) && $whereData[$fields]){
if(is_array($whereData[$fields])){
$model = $model->where("{$alisa}{$fields}", $whereData[$fields][0], $whereData[$fields][1]);
}else{
$model = $model->where("{$alisa}{$fields}", '=', $whereData[$fields]);
}
}
}
if (isset($whereData['status']) && $whereData['status']) $model = $model->where("{$alisa}status", 'in', $whereData['status']);
if (isset($whereData['not_status']) && $whereData['not_status']) $model = $model->where("{$alisa}status", 'not in', $whereData['not_status']);
if (isset($whereData['id']) && $whereData['id']) $model = $model->where("{$alisa}id", 'in', $whereData['id']);
if (isset($whereData['keywords'])&&$whereData['keywords']){
$model = $model->where("{$alisa}nickname|{$alisa}realname|{$alisa}work|{$alisa}email|{$alisa}mobile|{$alisa}bio", 'LIKE', '%'.$whereData['keywords'] . '%');
}
if (isset($whereData['time'])&&$whereData['time']){
// $model = $model->time([$whereData['time']]);
$model = $model->time(["{$alisa}createtime",$whereData['time']]);
}
if (isset($whereData['group_id']) && $whereData['group_id']) $model = $model->where("{$alisa}group_id", 'in', $whereData['group_id']);
return $model;
}
public static function allList($page, $limit,$params=[]){
$with_field = [
'usergroup'=>['name','rules','status'],
'base'=>['*'],
];
$alisa = (new self)->getWithAlisaName();
$sort = "{$alisa}.id desc";
// if(!empty($params['status'])){
// $params['status'] = '1';
// }
return (new self)->getBaseList($params, $page, $limit,$sort,$with_field);
}
public static function getShopUserList($page, $limit,$params=[],$shop_id=null,$has_order_user=false){
$where_params = [];
//得到授权的用户
if($shop_id){
if($has_order_user){
$classes_lib_id = $params["classes_lib_id"] ?? 0;
$classes_activity_id = $params["classes_activity_id"] ?? 0;
$classeswhere = $activitywhere = [[]];
if($classes_lib_id)$classeswhere = ["classes_lib_id","in",$classes_lib_id];
if($classes_activity_id)$activitywhere = ["classes_activity_id","in",$classes_activity_id];
//只查下过单的
$user_ids = Order::where("shop_id",$shop_id)->where(...$classeswhere)->column("user_id");
$user_ids = array_merge($user_ids,\app\common\model\school\classes\activity\order\Order::where(...$activitywhere)->where("shop_id",$shop_id)->column("user_id"));
$where_params = [
'id'=> implode(',',$user_ids),
];
}else{
//查机构授权的
$user_ids = UserAuth::where("shop_id",$shop_id)->where("status",1)->column("user_id");
$where_params = [
'id'=> implode(',',$user_ids),
];
}
}
return (new self)->allList($page, $limit,array_merge($where_params,$params));
}
public static function getSign(){
$timestamp = time();
$data = [
"timestamp"=>$timestamp,
];
return self::encryptedData($data);
}
public static function encryptedData($data){
//私钥
$activity_private_key = config("site.activity_private_key");
//转成json保留格式
$data = json_encode($data,JSON_UNESCAPED_UNICODE);
// 私钥加密(数字签名)
$signed = '';
if (!openssl_private_encrypt($data, $signed, $activity_private_key)) {
throw new \Exception("私钥加密失败: " . openssl_error_string());
}
return base64_encode($signed);
}
public static function getUserInfoByActivityToken($token){
//用token换取用户信息
//获取自签名
$sign = self::getSign();
//加密参数数据
$encryption_data = self::encryptedData(["token"=>$token]);
$key = "hschool";
$activity_da_domain = config("site.activity_da_domain");
$curl_url = "{$activity_da_domain}/api/openapi.user/index";
$post_data = [
"sign"=>$sign,
"encryption_data"=>$encryption_data,
"key"=>$key,
];
//执行curl的post请求php原生写法无封装 content_type走json
//content_type走json
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $curl_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
));
$result = curl_exec($ch);
curl_close($ch);
$result = json_decode($result,true);
if($result['code']==1){
$data = $result['data'];
$data['token'] = $data;
return $data;
}
return [];
}
/** 根据活动微信小程序的的登录token 登录或注册本小程序用户
* @param $token
* @return void
*/
public static function loginByActivityToken($token,$trans=false){
//用token换取用户信息
$user_info = self::getUserInfoByActivityToken($token);
if(!$user_info) throw new \Exception("登录失败!");
if($trans){
self::beginTrans();
}
$res = true;
try{
//凭此用户信息注册或登录本小程序用户
$user = self::where("mobile",$user_info["mobile"])->find();
//检测更新教练下单学员账号创建状态 2022/8/27 new
if(!$user)$user = (new self)->addUserByMobile($user_info["mobile"],$user_info["nickname"]);
// $user['nickname'] = $people_name;
// $user->save();
if($trans){
self::commitTrans();
}
}catch (\Exception $e){
if($trans){
self::rollbackTrans();
}
throw new \Exception($e->getMessage().$e->getFile().$e->getLine());
}
return $user;
}
}