From 5be3c4ff32058249d948d5f9c54245b11fafd11e Mon Sep 17 00:00:00 2001 From: callmeyan Date: Sun, 23 Jun 2019 22:28:55 +0800 Subject: [PATCH] update user api --- .example.env | 2 +- app/ExceptionHandle.php | 16 +++- app/controller/Admin.php | 4 + app/controller/User.php | 149 +++++++++++++++++------------- app/middleware.php | 2 +- app/middleware/ApiCheck.php | 5 +- app/model/UserInfo.php | 2 +- app/service/EvaluationService.php | 16 ++++ app/service/UserService.php | 37 +++++++- app/util/ErrorResponse.php | 16 +++- app/util/WechatUtil.php | 89 +++++++++++++++--- config/app.php | 2 +- config/database.php | 2 +- config/trace.php | 2 +- 14 files changed, 254 insertions(+), 90 deletions(-) diff --git a/.example.env b/.example.env index 1063a8e..313a877 100644 --- a/.example.env +++ b/.example.env @@ -1 +1 @@ -APP_DEBUG = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai ADMIN_MULTI_LOGIN = true [WECHAT] KEY = wxba6738e3d81f8461 SECRET = wxba6738e3d81f8461 [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = test USERNAME = username PASSWORD = password HOSTPORT = 3306 CHARSET = utf8 DEBUG = true [LANG] default_lang = zh-cn \ No newline at end of file +APP_DEBUG = true APP_TRACE = true [APP] DEFAULT_TIMEZONE = Asia/Shanghai ADMIN_MULTI_LOGIN = true [WECHAT] KEY = wxba6738e3d81f8461 SECRET = 23176f3fa94fbaded5942b1061a19d0e [DATABASE] TYPE = mysql HOSTNAME = 127.0.0.1 DATABASE = test USERNAME = username PASSWORD = password HOSTPORT = 3306 CHARSET = utf8mb4 DEBUG = true [LANG] default_lang = zh-cn \ No newline at end of file diff --git a/app/ExceptionHandle.php b/app/ExceptionHandle.php index 375e841..5daa0df 100644 --- a/app/ExceptionHandle.php +++ b/app/ExceptionHandle.php @@ -11,6 +11,9 @@ namespace app; +use app\util\ErrorCode; +use app\util\ErrorResponse; +use InvalidArgumentException; use think\db\exception\DataNotFoundException; use think\db\exception\ModelNotFoundException; use think\exception\Handle; @@ -60,8 +63,19 @@ class ExceptionHandle extends Handle */ public function render($request, Throwable $e): Response { - // 添加自定义异常处理机制 + if($e instanceof \InvalidArgumentException){ + return ErrorResponse::createError( + ErrorCode::ERROR_PARAM_ERROR,'参数错误' + )->header(['Access-Control-Allow-Origin' => '*']); + } + // 添加自定义异常处理机制 + if($request->isAjax()){ + return ErrorResponse::createError( + ErrorCode::ERROR_PARAM_ERROR,'服务暂时不可用(service unavailable)' + )->header(['Access-Control-Allow-Origin' => '*']); + } + //print_r($e->getMessage());//exit; // 其他错误交给系统处理 return parent::render($request, $e); } diff --git a/app/controller/Admin.php b/app/controller/Admin.php index 3190af9..be4b5b7 100644 --- a/app/controller/Admin.php +++ b/app/controller/Admin.php @@ -96,6 +96,10 @@ class Admin extends BaseController return AdminInfo::find(4); } + /** + * 后台用户搜索 + * @return \think\Response + */ public function searchUser() { // 获取参数 diff --git a/app/controller/User.php b/app/controller/User.php index 07a8a57..4acda7c 100644 --- a/app/controller/User.php +++ b/app/controller/User.php @@ -12,12 +12,16 @@ namespace app\controller; use app\BaseController; use app\common\ApiController; use app\model\UserInfo; +use app\service\EvaluationService; +use app\service\UserService; use app\util\ErrorCode; use app\util\ErrorResponse; +use app\util\SuccessResponse; use app\util\WechatUtil; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Csv; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; +use think\facade\Log; class User extends ApiController { @@ -25,75 +29,105 @@ class User extends ApiController '\app\middleware\ApiCheck' => ['except' => ['create', 'login']], ]; - public function search() - { - list($is_first, $gender, $city, $name) = $this->getParams( - 'is_first_to_tibet', 'gender', 'city', 'name' - ); - $user = new UserInfo(); - $userList = UserInfo::with('detail')->select(); - return json($userList -// ->visible([ -// 'detail'=>['address'] -// ]) - ->toArray()); - } - /** * 小程序login * 通过login获得code到微信服务器换区open_id等数据 * 并可以将数据直接保存到数据库 * @param string $code + * @return \think\response\Json */ public function login(string $code) { - $wechat = new WechatUtil(); - return json( - [ - WX_APP_ID, - WX_APP_SECRET - ] - ); + try { + $session = UserService::getSessionByCode($code); +// Log::debug("session data,".print_r($session,1)); + return SuccessResponse::create($session); // ['openid' => $session['openid']] + } catch (\Exception $e) { + return ErrorResponse::createFromException($e); + } } + /** + * 创建微信用户 但是不会创建用户基本数据 + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ public function create() { - $dataType = $this->request->post('type'); -// print_r($data); - - $spreadsheet = new Spreadsheet(); - $sheet = $spreadsheet->getActiveSheet(); - $sheet->setCellValue('A1', 'Hello World !'); -// header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); - $filename = urlencode("评估记录_") . date('mdHi'); -// $ua = $_SERVER["HTTP_USER_AGENT"]; -// $encoded_filename = urlencode($filename); -// $encoded_filename = str_replace("+", "%20", $encoded_filename); -// if (preg_match("/MSIE/", $ua)) { -// header('Content-Disposition: attachment; filename="' . $encoded_filename . '"'); -// } else if (preg_match("/Firefox/", $ua)) { -// header('Content-Disposition: attachment; filename*="utf8\'\'' . $filename . '"'); -// } else { -// header('Content-Disposition: attachment; filename="' . $filename . '"'); -// } - - $writer = new Csv($spreadsheet); - if ($dataType == 'xlsx') { - $writer = new Xlsx($spreadsheet); - $filename .= '.xlsx'; - } else { - $filename .= '.csv'; + $data = $this->request->post(array_keys($_POST)); + if (empty($data)) { + return ErrorResponse::createError( + ErrorCode::ERROR_PARAM_REQUIRED, '用户数据缺失' + ); + } + $existsUser = UserInfo::where('open_id', $data['open_id'])->find(); + if (empty($existsUser)) { + $userInfo = UserInfo::create($data); + if ($userInfo->id > 0) { + //创建用户成功 并返回数据 + $data = $userInfo->toArray(); + $data['realname'] = $data['nickname']; + $data['lastEvaluation'] = null; + return SuccessResponse::create($data); + } + return ErrorResponse::createError( + ErrorCode::USER_SAVE_FAIL, '保存用户数据失败' + ); + } else { + return SuccessResponse::create( + $this->getUserInfo($existsUser) + ); } - header('Content-Disposition: attachment;filename=' . $filename); - $writer->save('php://output'); - exit; } + /** + * 更新数据 + * @return \think\Response + */ public function update() { - + $data = $this->request->post(array_keys($_POST)); + try { + $detail = UserService::saveDetail($data,$this->getCurrentUserInfo()); + return SuccessResponse::create(); + } catch (\Exception $e) { + return ErrorResponse::createFromException($e); + } } + /** + * 用户基本信息,详情,最后一次评估 + * @param UserInfo $userInfo + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + private function getUserInfo(UserInfo $userInfo) + { + $userInfo = $this->getCurrentUserInfo(); + $detail = $userInfo->getParsedDetail(); + $userData = $userInfo->toArray(); + if (empty($detail)) { + $userData['realname'] = $userInfo->nickname; + $userData['lastEvaluation'] = null; + } else { + $lastEvaluation = EvaluationService::getLastEvaluationByUid($userInfo->id); + if (!empty($lastEvaluation)) { + $userData['lastEvaluation'] = $lastEvaluation['create_time']; + } + } + return $userData; + } + + /** + * @return \think\Response + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ public function info() { // if (empty($open_id)) { @@ -108,24 +142,11 @@ class User extends ApiController // ); // } - return $this->getCurrentUserInfo(); + return SuccessResponse::create($this->getUserInfo($this->getCurrentUserInfo())); } public function detail() { -// if ($id < 1) { -// return ErrorResponse::createError( -// ErrorCode::ERROR_PARAM_ERROR, '用户编号错误' -// ); -// } -// $user = UserInfo::find($id); -// if (empty($user)) { -// return ErrorResponse::createError( -// ErrorCode::ERROR_USER_NOT_EXISTS, '用户不存在' -// ); -// } -// $userData = $this->getCurrentUser()->getData(); -// $userData['detail'] = $this->getCurrentUser()->getParsedDetail(); return json( array_merge( $this->getCurrentUserInfo()->toArray(), diff --git a/app/middleware.php b/app/middleware.php index 9d1845c..ab8b714 100644 --- a/app/middleware.php +++ b/app/middleware.php @@ -10,5 +10,5 @@ return [ \app\middleware\Cors::class, // \app\middleware\ApiCheck::class, // 页面Trace调试 - \think\middleware\TraceDebug::class, +// \think\middleware\TraceDebug::class, ]; diff --git a/app/middleware/ApiCheck.php b/app/middleware/ApiCheck.php index b521c40..1e69ab2 100644 --- a/app/middleware/ApiCheck.php +++ b/app/middleware/ApiCheck.php @@ -29,7 +29,10 @@ class ApiCheck */ public function handle(Request $request, \Closure $next) { - $open_id = Env::get('app_debug') ? 'wxaffadsf31Dfaf93wxaffadsf31Dfaf93' : $request->param('open_id');//'wxaffadsf31Dfaf93'; + $open_id = $request->param('open_id'); + if(empty($open_id)){ + $open_id = Env::get('app_debug') ? 'wxaffadsf31Dfaf93wxaffadsf31Dfaf93' : ''; + } if (empty($open_id)) { return ErrorResponse::createError( diff --git a/app/model/UserInfo.php b/app/model/UserInfo.php index 08dcf4f..09f14a2 100644 --- a/app/model/UserInfo.php +++ b/app/model/UserInfo.php @@ -36,7 +36,7 @@ class UserInfo extends BaseModel * 获取已经格式过的用户详情 * @return UserDetail */ - public function getParsedDetail(): UserDetail + public function getParsedDetail() { return $this->detail; } diff --git a/app/service/EvaluationService.php b/app/service/EvaluationService.php index 830edd7..0b99b99 100644 --- a/app/service/EvaluationService.php +++ b/app/service/EvaluationService.php @@ -173,4 +173,20 @@ class EvaluationService return $data; } + /** + * 获取用户最后一次评估数据 + * @param int $uid + * @return array|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function getLastEvaluationByUid(int $uid) + { + $evaluation = EvaluationHistory::where('uid',$uid) + ->order('id','desc')->limit(1)->find(); + if(empty($evaluation)) return null; + return self::parseEvaluationData($evaluation->toArray()); + } + } diff --git a/app/service/UserService.php b/app/service/UserService.php index 7e967f9..bd1c20a 100644 --- a/app/service/UserService.php +++ b/app/service/UserService.php @@ -11,7 +11,9 @@ namespace app\service; use app\model\UserDetail; use app\model\UserInfo; +use app\util\ErrorCode; use app\util\ListCountData; +use app\util\WechatUtil; use think\facade\Config; class UserService @@ -51,7 +53,7 @@ class UserService } $dataArray = $model->limit(($page - 1) & $pageSize, $pageSize)// 分页 - ->field('u.nickname,u.open_id,u.avatar,d.*')// 查询字段 + ->field('u.nickname,u.open_id,u.avatarUrl,d.*')// 查询字段 ->select()->toArray(); // 获取结果 $count = $userInfo->count(); // 查询总数 self::parseArray($dataArray); @@ -65,7 +67,7 @@ class UserService foreach ($dataArray as $key => &$item) { // $item['is_first_to_tibet'] = $item['is_first_to_tibet'] == 1 ? '是' : '否'; $item['smoke'] = $userData['smoke'][$item['smoke']]; - $item['medical_history'] = empty($item['medical_history']) ?[]: self::getDataFromArray( + $item['medical_history'] = empty($item['medical_history']) ? [] : self::getDataFromArray( $userData['medical_history'], explode(',', $item['medical_history']) ); @@ -79,4 +81,35 @@ class UserService } return $keys; } + + public static function getSessionByCode(string $code): array + { + $wechat = new WechatUtil(); + $session = $wechat->codeToSession($code); + if (isset($session['errcode']) && $session['errcode'] != 0) { + throw new \Exception($session['errmsg'], ErrorCode::User_Login_Fail); + } + return $session; + } + + /** + * 更新数据 + * @param $data + * @param UserInfo $userInfo + * @return UserDetail|array|null|\think\Model + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public static function saveDetail($data, UserInfo $userInfo) + { + $detail = UserDetail::where('uid', $userInfo->id)->find(); + $data['uid'] = $userInfo->id; + if (empty($detail)) { + $detail = UserDetail::create($data); + } else { + $detail = UserDetail::update($data, ['uid' => $userInfo->id]); + } + return $detail; + } } \ No newline at end of file diff --git a/app/util/ErrorResponse.php b/app/util/ErrorResponse.php index eeaa297..da63d81 100644 --- a/app/util/ErrorResponse.php +++ b/app/util/ErrorResponse.php @@ -45,25 +45,37 @@ class ErrorCode * 用户不存在 */ const ERROR_USER_NOT_EXISTS = 22001; + const User_Login_Fail = 22002; + const USER_SAVE_FAIL = 22003; + const USER_EXISTS = 22004; /** * 评估 */ const EVALUATION_SAVE_FAIL = 23005; const EVALUATION_NOT_EXISTS = 23006; + } class ErrorResponse extends Json { - public static function createError($errorCode, $errorMessage = '',$extData = null): Response + public static function createError($errorCode, $errorMessage = '', $extData = null): Response { $ret = [ "code" => $errorCode, "message" => $errorMessage ]; - if($extData){ + if ($extData) { $ret['data'] = $extData; } return parent::create($ret); // TODO: Change the autogenerated stub } + + public static function createFromException(\Throwable $e) + { + return parent::create([ + 'code' => $e->getCode(), + 'message' => $e->getMessage() + ]); + } } \ No newline at end of file diff --git a/app/util/WechatUtil.php b/app/util/WechatUtil.php index 396b2ce..37dd8aa 100644 --- a/app/util/WechatUtil.php +++ b/app/util/WechatUtil.php @@ -7,27 +7,28 @@ */ namespace app\util; + use think\facade\Config; +use think\facade\Log; define('WX_SERVER_URL', 'https://api.weixin.qq.com'); define('CODE_2_SESSION', WX_SERVER_URL . '/sns/jscode2session'); -define('WX_APP_ID',Config::get('wechat.key')); -define('WX_APP_SECRET',Config::get('wechat.secret')); +define('WX_APP_ID', Config::get('wechat.key')); +define('WX_APP_SECRET', Config::get('wechat.secret')); + class WechatUtil { public function __construct() { } - public function codeToSession(strign $code): array + public function codeToSession(string $code): array { - return json_decode( - $this->request( - CODE_2_SESSION, [ - 'js_code' => 'JSCODE', - 'grant_type' => 'authorization_code' - ] - ), true + return $this->request( + CODE_2_SESSION, [ + 'js_code' => $code, + 'grant_type' => 'authorization_code' + ] ); } @@ -35,10 +36,70 @@ class WechatUtil { $params['appid'] = WX_APP_ID; $params['secret'] = WX_APP_SECRET; - $url = WX_SERVER_URL . $api; - if (strtolower($method) == 'get') { - $url .= http_build_query($params); + $method = strtolower($method); + if ($method == 'get') { + $api .= '?' . http_build_query($params); } - return file_get_contents($url); + $ch = null; + try { + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $api); + + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 1); //定义是否显示状态头 1:显示 ; 0:不显示 + curl_setopt($ch, CURLINFO_HEADER_OUT, 0); + + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); +// + $postHeader = array( + 'Expect: ', + 'User-Agent: YCF HTTP API V2', + 'Content-Type: application/json;charset=UTF-8' + ); + curl_setopt($ch, CURLOPT_HTTPHEADER, $postHeader); + + if ($method != 'get') { + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + } + switch ($method) { + case 'get': + break; + case 'post': + curl_setopt($ch, CURLOPT_POST, true); + break; + default: + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + break; + } + + $res = curl_exec($ch); + $info = curl_getinfo($ch); + Log::debug("WechatUtil res=>".print_r($res,1)); +// Log::debug("WechatUtil info=>".print_r($info,1)); + + list($header, $res) = explode("\r\n\r\n", $res, 2); + + if (curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200) { + throw new \Exception('Server response error' . print_r($header, 1)); + } + + if ($res && is_string($res)) { + return json_decode($res, 1); + } else { + throw new YCHttpException('Server response data was empty'); + } + return $res; + } catch (\Exception $e) { + throw $e; + } finally { + if (null != $ch) { + curl_close($ch); + } + } + return null; } } \ No newline at end of file diff --git a/config/app.php b/config/app.php index 15299f4..8b69156 100644 --- a/config/app.php +++ b/config/app.php @@ -41,7 +41,7 @@ return [ 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl', // 错误显示信息,非调试模式有效 - 'error_message' => '页面错误!请稍后再试~', + 'error_message' => '服务不可用', // 显示错误信息 'show_error_msg' => false, diff --git a/config/database.php b/config/database.php index 71774a0..ff8c18a 100644 --- a/config/database.php +++ b/config/database.php @@ -35,7 +35,7 @@ return [ // 数据库连接参数 'params' => [], // 数据库编码默认采用utf8 - 'charset' => Env::get('database.charset', 'utf8'), + 'charset' => Env::get('database.charset', 'utf8mb4'), // 数据库表前缀 'prefix' => Env::get('database.prefix', ''), // 数据库调试模式 diff --git a/config/trace.php b/config/trace.php index 2391481..81f0396 100644 --- a/config/trace.php +++ b/config/trace.php @@ -14,7 +14,7 @@ // +---------------------------------------------------------------------- return [ // 内置Html 支持扩展 - 'type' => 'Console', + 'type' => 'Console', // Console 'trace_tabs' => [ 'base'=>'基本', 'file'=>'文件',