sync h888 server

main
Wayne Hsu 3 years ago
parent 50424b7505
commit 87cad64b18

@ -19,7 +19,9 @@ class User extends ApiController
->where('user_id', input('user_id'))
// ->whereNotNull('delete_time')
->find();
if(!$user){
return $this->error('SSO用戶不存在');
}
return $this->success($user);
} catch (\Exception $e) {
return $this->error('操作失敗');

@ -0,0 +1,130 @@
<?php
declare (strict_types = 1);
namespace app\appapi;
use think\App;
use think\Response;
// use think\exception\ValidateException;
// use think\Validate;
/**
* 控制器基础类
*/
abstract class ApiController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
protected $uid = '';
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{
header('Access-Control-Allow-Origin: *');
// //允許的請求頭信息
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
// //允許的請求類型
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH');
header('Access-Control-Expose-Headers: authorization');
// //允許攜帶證書式訪問攜帶cookie
header('Access-Control-Allow-Credentials:true');
$this->uid = input('uid');
}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array|string|true
* @throws ValidateException
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
[$validate, $scene] = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
return $v->failException(true)->check($data);
}
public function Success($data,$code=200,$message='請求成功',$type='json',$header=[]){
$result = [
'code' => $code,
'message' => $message,
'time'=>time(),
'data'=>$data
];
return Response::create($result,$type)->header($header);
}
public function Error($data,$code=500,$message='請求失敗',$type='json',$header=[]){
$result = [
'code' => $code,
'message' => $message,
'time'=>time(),
'data'=>$data
];
return Response::create($result,$type)->header($header);
}
}

@ -0,0 +1,337 @@
<?php
namespace app\appapi\controller\v1;
use app\appapi\ApiController;
use think\facade\Db;
use think\facade\Session;
use think\facade\Log;
use Lcobucci\JWT\Parser;
use thans\jwt\facade\JWTAuth;
use GuzzleHttp\Client;
use app\common\lib\Vcard;
use app\common\lib\Aes;
class Auth extends ApiController
{
/**
* return 200 成功
* 201 不是會員
*/
public function login(){
$id_token = input('token');
$line_id = input('line_id');
// $profile = (new Parser())->parse($id_token);
// print_r($token->getClaim('name'));
//驗證id_token
$user=Db::name('user')
->where('line_id',$line_id)
->find();
if(!$user){
return $this->success('非會員',201);
}
$token = JWTAuth::builder(
[
'id' => $user['id'],
'user_id' => $user['user_id'],
'level' => $user['level']
]);
if(empty($user['uniqid'])){
return $this->success(['uid'=>$user['user_id'],'token'=>'Bearer '.$token],202);
}
return $this->success(['uid'=>$user['user_id'],'token'=>'Bearer '.$token]);
}
public function bindCard(){
$uid = input('uid');
$verify = input('verify');
try{
Db::name('user')
->where('user_id',$uid)
->update(['uniqid'=>$verify]);
Db::name('precard')
->where('verify_code',$verify)
->update(['status'=>2]);
return $this->success('綁定成功');
}catch(\Exception $e){
return $this->error('綁定失敗');
}
}
public function checkLineId(){
$line_id=input('lineid');
$user = Db::name('user')
->where('line_id',$line_id)
->find();
if($user){
return $this->error('會員已存在');
}
return $this->success('檢查成功');
}
public function register(){
$data = input();
unset($data['version']);
unset($data['controller']);
unset($data['action']);
unset($data['uid']);
unset($data['userid']);
unset($data['verify']);
unset($data['token']);
$data=array_map('asc_trim',$data);
//檢查line id是否己經是會員
//TODO
$user=Db::name('user')
->where('line_id',input('line_id'))
->find();
if($user){
return $this->error('已是會員',501);
}
//驗證id_token
$verify_line = $this->verifyIdToken(input('token'));
if(!$verify_line){
return $this->error('id token expire',500);
}
$data['line_name'] = $verify_line['name'];
$data['line_picture'] = $verify_line['picture'];
//推薦人
// if(strlen($data['refer'])>0){
// $pid = decodeRefer($data['refer']);
// $data['parent_id'] = $pid;
// }else{
// $data['parent_id'] = 0;
// }
// unset($data['refer']);
if(input('verify')){
$action = 'openright';
$user_id=genUniqid();
$data['user_id'] = $user_id;
$data['uniqid'] = input('verify');
$precard = Db::name('precard')
->where('verify_code',input('verify'))
->find();
if(!$precard){
return $this->error('查無預開卡',401);
}
$data['agent_id'] = $precard['agent_id'];
//TODO
}else{
$action = 'register';
if(!isset($data['aid'])){
$data['agent_id'] = 1;
}else{
$data['agent_id'] = Db::name('agent')->where('prefix',$data['aid'])->value('id');
unset($data['aid']);
}
$user_id=genUniqid();
$data['user_id'] = $user_id;
}
$avatar=$this->saveLineImage($data['line_picture'],$data['user_id']);
$data['line_picture']= getUrl().'/storage/'.$data['user_id'].'/'.$avatar;
if(!isset($data['avatar'])){
$data['avatar']=$data['line_picture'];
}else{
$file_path = $_SERVER['DOCUMENT_ROOT'].'/storage/'.$data['user_id'].'/'.date('Ymd').'/';
if(!is_dir($file_path)){
mkdir($file_path, 0777, true);
}
$temp_file = str_replace(getUrl(),"",$data['avatar']);
$avatar_file = $file_path.basename($temp_file);
if(!rename($_SERVER['DOCUMENT_ROOT'].$temp_file, $avatar_file)){
return $this->error('搬移檔案失敗');
}
$data['avatar']=getUrl().'/storage/'.$data['user_id'].'/'.date('Ymd').'/'.basename($temp_file);
}
$agent = Db::name('agent')->where('id',$data['agent_id'])->find();
if($agent['try_days']==0){
$data['status'] = 1;
$data['level'] = $agent['base_level'];
$data['overdue_time'] = strtotime(date('Y-m-d',time() + (60 * 60 * 24 * $agent['base_days'])));
}else{
$data['status'] = 2;
$data['level'] = $agent['try_level'];
$data['overdue_time'] = strtotime(date('Y-m-d',time() + (60 * 60 * 24 * $agent['try_days'])));
}
if($agent['parent_id']==0){
$data['agent_id'] = $agent['id'];
}else{
$data['agent_id'] = $agent['parent_id'];
}
$level_option = Db::name('user_level')
->where('agent_id',$data['agent_id'])
->where('level_id',$data['level'])
->find();
$data['nc_type']=$level_option['nc_type'];
$data['nc_func']=$level_option['nc_func'];
$data['cus_card'] = '';
$data['create_time'] = date('Y-m-d H:i:s');
try{
$id = Db::name('user')
->insertGetId($data);
$refer_code = encodeRefer($id);
$result = Db::name('user')
->where('id',$id)
->update(['code'=>$refer_code]);
$qrcodeUrl = genQrCode('https://'.$_SERVER['HTTP_HOST'].'/home/?aid='.$agent['prefix'],$data['user_id'],'refer');
$aes = new Aes([]);
$params = urlencode($aes->encrypt('user_id='.$data['user_id'].'&verify_code='.input('verify')));
$nfcUrl = genQrCode('https://'.$_SERVER['HTTP_HOST'].'/card/?params='.$params,$data['user_id'],'nfc');
Vcard::genVcf($data['user_id']);
$token = JWTAuth::builder(
[
'id' => $id,
'user_id' => $data['user_id'],
'level' => 0
]);
if($action == 'openright'){
Db::name('precard')
->where('verify_code',input('verify'))
->update(['status'=>2]);
}
return $this->success(['uid'=>$data['user_id'],'token'=>'Bearer'.$token]);
}catch(\Exception $e){
print_r($e);
return $this->error('註冊失敗');
}
}
private function verifyIdToken($token){
try{
$client = new Client();
$response = $client->request('POST', 'https://api.line.me/oauth2/v2.1/verify', [
'form_params' => [
'id_token' => $token,
'client_id'=> env('utel.line_channel_id')
]
]);
$body = $response->getBody()->getContents();
return json_decode($body, true);
} catch (\Exception $e) {
return false;
}
// print_r($response);
// $body = $response->getBody()->getContents();
// print_r($body);
}
private function saveLineImage($pictureUrl,$uid)
{
if($pictureUrl){
$curl = curl_init($pictureUrl);
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
$imageData=curl_exec($curl);
curl_close($curl);
$filename=$uid."_line.jpg";
$filedir=$_SERVER['DOCUMENT_ROOT'].'/storage/'.$uid;
if (!file_exists($filedir)) {
mkdir($filedir , 0777 , true);
}
$fp=fopen($filedir.'/'.$filename,'a');
fwrite($fp,$imageData);
fclose($fp);
return $filename;
}else{
return false;
}
}
public function getSiteConfig(){
$result = Db::name('site_config')
->where('parent_id','<>',0)
->select();
foreach($result as $key => $val){
$rtn[$val['code']]=$val['value'];
}
return $this->success($rtn);
}
public function uploadAvatar(){
$files = request()->file('file');
$savename = \think\facade\Filesystem::disk('public')->putFile( 'temp' , $files);
$avatar = getUrl().'/storage/'.$savename;
// Db::name('user')
// ->where('user_id',input('user_id'))
// ->update(['avatar'=>$avatar]);
return $this->Success($avatar);
}
public function test(){
Vcard::genVcf('mc63de2a162b218');
}
}

@ -0,0 +1,246 @@
<?php
namespace app\appapi\controller\v1;
use app\appapi\ApiController;
use think\facade\Db;
use app\common\lib\Aes;
use app\common\lib\Vcard;
class Card extends ApiController
{
/**
* 檢查nfc用户
*
* @author wayne <wwayne.hsu@gmail.com>
*
* @param string token 加密參數
*
* @return json
*/
public function checkUser(){
$token = input('token');
if(!$token){
return $this->error('參數錯誤');
}
$aes = new Aes([]);
parse_str($aes->descrypt($token),$params);
if(!isset($params['verify_code'])){
if(!isset($params['user_id'])){
return $this->error('參數錯誤');
}
$user_id = $params['user_id'];
}else{
if(strlen($params['verify_code'])>0){
$user_id = getUseridByCuid(strtoupper($params['verify_code']));
}else{
return $this->error('參數錯誤');
}
}
if($user_id){
Db::name('user')
->where('user_id',$user_id)
->inc('nfc_count')
->update();
return $this->success($user_id);
}
//檢查是否為預開卡會員
$is_precard=Db::name('precard')
->where('verify_code',strtoupper($params['verify_code']))
->count();
if($is_precard){
return $this->success(['verify'=>strtoupper($params['verify_code'])],201);
}
return $this->error('請求錯誤');
}
public function getCard(){
$do=Db::name('user');
if(input('userid')){
$do->where('user_id',input('userid'));
}elseif(input('line_id')){
$do->where('line_id',input('line_id'));
}else{
return $this->error('查無會員資料');
}
$user = $do->find();
if(!$user){
return $this->error('查無會員資料');
}
$aes = new Aes([]);
if(strlen($user['uniqid'])>0){
$params = urlencode($aes->encrypt('verify_code='.$user['uniqid']));
}else{
$params = urlencode($aes->encrypt('user_id='.$user['user_id']));
}
$user['nfcurl'] = getUrl().'/card/?params='.$params;
$result = [
"address" => $user['address']?$user['address']:' ',
"company" => $user['company']?$user['company']:' ',
"email" => $user['email']?$user['email']:' ',
"logo" => "https://i.imgur.com/GclvYFK.png",
"maps" => "https://www.google.com/maps/search/?api=1&query_place_id=ChIJAaZEqCYWaTQRMv6fuIsJEuo&query=%E5%BE%AE%E7%A8%8B%E5%BC%8F%E8%B3%87%E8%A8%8A&openExternalBrowser=1",
"name" => $user['real_name']?$user['real_name']:' ',
"phone" => $user['phone']?$user['phone']:' ',
"tel" => $user['tel']?$user['tel']:' ',
"title" => $user['title']?$user['title']:' ',
"url" => $user['url']?$user['url']:' ',
"line" => $user['line']?$user['line']:'',
"facebook" => $user['facebook']?$user['facebook']:'',
"youtube" => $user['youtube']?$user['youtube']:'',
"ig" => $user['ig']?$user['ig']:'',
"level" => $user['level']?$user['level']:0,
"user_id" => $user['user_id']?$user['user_id']:'',
"line_picture" => $user['line_picture']?$user['line_picture']:'',
"avatar" => $user['avatar']?$user['avatar']:'',
"card_title" => $user['card_title']?$user['card_title']:'',
"has_cuscard" => strlen($user['cus_card'])?1:0,
"nc_type" => $user['nc_type']?$user['nc_type']:0,
"nc_func" => explode(',',$user['nc_func']),
"nc_template" => $user['nc_template'],
"mark" => nl2br($user['mark']),
"nfcurl" => $user['nfcurl'],
"show_cus" => $user['show_cus'],
"nfc_addon" => json_decode($user['nfc_addon'])
];
return $this->Success($result);
}
public function getCusCard(){
$data=input();
unset($data['version']);
unset($data['controller']);
unset($data['action']);
try{
$do=Db::name('user');
if(input('userid')){
$do->where('user_id',input('userid'));
}elseif(input('line_id')){
$do->where('line_id',input('line_id'));
}else{
return $this->error('查無會員資料');
}
$card = $do->field('cus_card,card_title')
->find();
}catch(Exception $e){
return $this->error('操作失敗');
}
return $this->success($card);
}
public function getVipCard(){
$data=input();
unset($data['version']);
unset($data['controller']);
unset($data['action']);
try{
$do=Db::name('user_card');
if(input('userid')){
$id = getIdByUid(input('userid'));
}elseif(input('line_id')){
$id = getIdByUid(input('lineid'));
}else{
return $this->error('查無會員資料');
}
$do->where('user_id',$id);
$card = $do->field('*')
->select();
}catch(Exception $e){
return $this->error('操作失敗');
}
return $this->success($card);
}
public function updateCard(){
$data=input();
unset($data['uid']);
unset($data['version']);
unset($data['controller']);
unset($data['action']);
unset($data['nfcurl']);
unset($data['agent_prefix']);
unset($data['level_name']);
unset($data['addon']);
unset($data['delete_time']);
if(!empty(input('addon'))){
$data['nfc_addon']=json_encode(input('addon'));
}else{
$data['nfc_addon']='';
}
try{
Db::name('user')
->where('user_id',$data['user_id'])
->update($data);
Vcard::genVcf($data['user_id']);
}catch(Exception $e){
return $this->error('操作失敗');
}
return $this->success(['code'=>200]);
}
public function updateCusCard(){
$data=input();
unset($data['version']);
unset($data['controller']);
unset($data['action']);
$data['show_cus'] = input('show_cus')?1:0;
try{
Db::name('user')
->where('user_id',$data['user_id'])
->update(['card_title'=>$data['card_title'],'show_cus'=>$data['show_cus'],'cus_card'=>$data['cus_card']]);
}catch(Exception $e){
return $this->error('操作失敗');
}
return $this->success(['code'=>200]);
}
public function uploadFile(){
// print_r(input());
$files = request()->file('file');
$savename = \think\facade\Filesystem::disk('public')->putFile( 'card', $files);;
$image_url = getUrl().'/storage/'.$savename;
return $this->success($image_url);
}
}

@ -0,0 +1,82 @@
<?php
namespace app\appapi\controller\v1;
use app\appapi\ApiController;
use think\facade\Db;
use app\common\lib\Aes;
class User extends ApiController
{
public function getUserInfo(){
$user=Db::name('user')
->where('user_id',$this->uid)
->find();
$aes = new Aes([]);
if(strlen(trim($user['uniqid']))>0){
$params = urlencode($aes->encrypt('verify_code='.$user['uniqid']));
}else{
$params = urlencode($aes->encrypt('user_id='.$user['user_id']));
}
$user['level_name'] = Db::name('user_level')->where('agent_id',$user['agent_id'])->where('level_id',$user['level'])->value('name');
$user['nfcurl'] = getUrl().'/card/?params='.$params;
$user['nc_func'] = explode(',',$user['nc_func']);
$user['agent_prefix'] = Db::name('agent')->where('id',$user['agent_id'])->value('prefix');
return $this->Success($user);
}
public function setUserLevel(){
$result=Db::name('user')
->where('user_id',$this->uid)
->update(['level'=>input('level')]);
return $this->Success($result);
}
public function setUserTpl(){
try{
$result=Db::name('user')
->where('user_id',$this->uid)
->update(['nc_template'=>input('tpl')]);
}catch(\Excenption $e){
return $this->Error('更新失敗');
}
return $this->Success($result);
}
public function uploadAvatar(){
$files = request()->file('file');
$savename = \think\facade\Filesystem::disk('public')->putFile( input('user_id'), $files);
$avatar = getUrl().'/storage/'.$savename;
// Db::name('user')
// ->where('user_id',input('user_id'))
// ->update(['avatar'=>$avatar]);
return $this->Success($avatar);
}
public function updateSendCount(){
$user_id = input('userid');
Db::name('user')
->where('user_id',input('userid'))
->exp('send_count', 'send_count+1')
->update();
// ->inc('send_count',1);
return $this->Success('更新成功');
}
}

@ -0,0 +1,6 @@
<?php
return [
\think\middleware\SessionInit::class,
\think\middleware\AllowCrossDomain::class,
// app\api\middleware\CheckSiteCode::class
];

@ -0,0 +1,62 @@
<?php
declare (strict_types=1);
namespace app\appapi\middleware;
use thans\jwt\exception\JWTException;
use thans\jwt\exception\TokenBlacklistException;
use thans\jwt\exception\TokenBlacklistGracePeriodException;
use thans\jwt\exception\TokenExpiredException;
use thans\jwt\middleware\JWTAuth;
use think\exception\HttpException;
/**
* JWT驗證刷新token機制
* Class JWTToken
* @package app\api\middleware
*/
class JWT extends JWTAuth
{
/**
* 刷新token
* @param $request
* @param \Closure $next
* @return mixed
* @throws JWTException
* @throws TokenBlacklistException
* @throws TokenBlacklistGracePeriodException
*/
public function handle($request, \Closure $next): object
{
try {
$payload = $this->auth->auth();
} catch (TokenExpiredException $e) { // token過期
// 嘗試刷新token會將舊token加入黑名單
try {
$this->auth->setRefresh();
$token = $this->auth->refresh();
$payload = $this->auth->auth(false);
} catch (TokenBlacklistGracePeriodException $e) {
$payload = $this->auth->auth(false);
} catch (JWTException $exception) {
// 如果捕獲到此異常,即代表 refresh 也過期了,用户無法刷新令牌,需要重新登錄。
throw new HttpException(401, $exception->getMessage());
}
} catch (TokenBlacklistGracePeriodException $e) { // 捕獲黑名單寬限期
$payload = $this->auth->auth(false);
} catch (TokenBlacklistException $e) { // 捕獲黑名單退出登錄或者已經自動刷新當前token就會被拉黑
throw new HttpException(401, 'not login...');
}
$request->uid = $payload['user_id']->getValue();
$response = $next($request);
if (isset($token)) {
$this->setAuthentication($response, $token);
}
return $response;
}
}

@ -0,0 +1,10 @@
<?php
use think\facade\Route;
Route::group(function () {
// Route::rule(':version/user/:action', 'appapi/:version.user/:action');
// Route::rule(':version/user/:action', 'api/:version.user/:action');
})->middleware(\app\api\middleware\JWT::class);
Route::rule(':version/:controller/:action','appapi/:version.:controller/:action');

@ -0,0 +1,15 @@
<?php
namespace app\common\lib;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class Token{
/**
* 構造方法
*/
public function __construct(){
}
}
Loading…
Cancel
Save