diff --git a/app/Constants/ErrorCode.php b/app/Constants/ErrorCode.php index 229e25e..506e36c 100644 --- a/app/Constants/ErrorCode.php +++ b/app/Constants/ErrorCode.php @@ -24,6 +24,11 @@ class ErrorCode extends AbstractConstants */ const SERVER_ERROR = 500; + /** + * @Message("Params Invalid!") + */ + const PARAMS_INVALID = 900; + /** * @Message("Ssdb Error!") */ diff --git a/app/Constants/LogLabel.php b/app/Constants/LogLabel.php new file mode 100644 index 0000000..2265cf4 --- /dev/null +++ b/app/Constants/LogLabel.php @@ -0,0 +1,19 @@ +success($this->adService->banners()); + } +} diff --git a/app/Controller/ParamsTokenController.php b/app/Controller/ParamsTokenController.php index 8182bbd..db1cdca 100644 --- a/app/Controller/ParamsTokenController.php +++ b/app/Controller/ParamsTokenController.php @@ -1,11 +1,15 @@ paramsTokenService->generate($this->request->all()); - return $this->success(['token' => $res]); + $token = $this->paramsTokenService->generate($this->request->all()); + return $this->success(['token' => $token]); } + /** + * 解析token获取对应参数数据 + * @return \Psr\Http\Message\ResponseInterface + */ public function analyze() { - $res = $this->paramsTokenService->analyze($this->request->input('token')); - return $this->success($res); + $params = $this->paramsTokenService->analyze($this->request->input('token')); + return $this->success($params); } } \ No newline at end of file diff --git a/app/Exception/Handler/SsdbExceptionHandler.php b/app/Exception/Handler/SsdbExceptionHandler.php index 8eeaa0e..118d5ef 100644 --- a/app/Exception/Handler/SsdbExceptionHandler.php +++ b/app/Exception/Handler/SsdbExceptionHandler.php @@ -16,18 +16,14 @@ class SsdbExceptionHandler extends ExceptionHandler { $this->stopPropagation(); - $content = json_encode( - [ + $content = json_encode([ "status" => 'error', - "code" => ErrorCode::SSDB_ERROR, + "code" => $throwable->getCode(), "result" => [], - "message" => $throwable->getMessage() ?: ErrorCode::getMessage(ErrorCode::SSDB_ERROR) - ] - ); + "message" => $throwable->getMessage() + ]); - return $response->withHeader('Content-Type', 'application/json') - ->withStatus($throwable->status) - ->withBody(new SwooleStream($content)); + return $response->withHeader('Content-Type', 'application/json')->withBody(new SwooleStream($content)); } public function isValid(Throwable $throwable): bool diff --git a/app/Exception/Handler/ValidationExceptionHandler.php b/app/Exception/Handler/ValidationExceptionHandler.php new file mode 100644 index 0000000..cc2384c --- /dev/null +++ b/app/Exception/Handler/ValidationExceptionHandler.php @@ -0,0 +1,35 @@ +stopPropagation(); + + $content = json_encode([ + "status" => 'error', + "code" => ErrorCode::PARAMS_INVALID, + "result" => [], + "message" => $throwable->validator->errors()->first() + ]); + + return $response->withHeader('Content-Type', 'application/json') + ->withStatus($throwable->status) + ->withBody(new SwooleStream($content)); + } + + public function isValid(Throwable $throwable): bool + { + return $throwable instanceof ValidationException; + } +} \ No newline at end of file diff --git a/app/Listener/ValidatorFactoryResolvedListener.php b/app/Listener/ValidatorFactoryResolvedListener.php new file mode 100644 index 0000000..75b3a36 --- /dev/null +++ b/app/Listener/ValidatorFactoryResolvedListener.php @@ -0,0 +1,113 @@ +validatorFactory; + + // 注册了 nonempty 验证器规则 + $validatorFactory->extend('nonempty', function ($attribute, $value, $parameters, $validator) { + + return isset($value) + && $value + && !empty($value) + && !is_null($value) + && $value != 'undefined' + && $value != 'unknown' + && $value != 'null' + && $value != 'false'; + + }); + + // 注册了 strlen 验证器规则,参数是min,max,最小长度和最大长度 + $validatorFactory->extend('strlen', function ($attribute, $value, $parameters, $validator) { + return mb_strlen($value)>=$parameters[0] && mb_strlen($value)<=$parameters[1]; + }); + $validatorFactory->replacer('strlen', function ($message, $attribute, $rule, $parameters) { + $message = str_replace(':min', $parameters[0], $message); + $message = str_replace(':max', $parameters[1], $message); + return $message; + }); + + // 注册了 base64 验证器规则 + $validatorFactory->extend('base64', function ($attribute, $value, $parameters, $validator) { + + preg_match('/^(data:\s*image\/(\w+);base64,)/', $value, $result); + + if (empty($result)) { + return false; + } + + if ( + in_array('image', $parameters) + && !in_array($result[2], ['jpg','jpeg','png','gif','svg','bmp']) + ) { + return false; + } + + return true; + + }); + + // 注册了 ext_not_in 验证器规则 + $validatorFactory->extend('ext_not_in', function ($attribute, $value, $parameters, $validator) { + + if (empty($parameters)) { + $parameters = ['', 'php', 'exe', 'sql', 'sh', 'bat', 'py', 'go', 'c', 'cpp']; + } + return !in_array($value->getExtension(), $parameters); + + }); + + // 注册了 exists_enable 验证器规则,参数是table,field,where1,where2... + $validatorFactory->extend('exists_enable', function ($attribute, $value, $parameters, $validator) { + + // 查询 + $builder = Db::table($parameters[0])->where($parameters[1], '=', $value); + + $whereArr = array_slice($parameters,2); + if (!empty($whereArr)) { + foreach ($whereArr as $key => $where) { + $builder->whereRaw($where); + } + } + + return $builder->exists(); + }); + + // 注册了 not_equal 验证器规则,参数是anotherfield,table,primary_field,foreign_field + // 要排除对比的字段请求参数名、表名、本参数对应表id、比较字段 + $validatorFactory->extend('not_equal', function ($attribute, $value, $parameters, $validator) { + + // 获取比较字段参数值 + $foreignValue = $validator->getData()[$parameters[0]]; + + // 查询 + $builder = Db::table($parameters[1]) + ->where($parameters[2], '=', $value) + ->where($parameters[3], '!=', $foreignValue) + ; + + return $builder->exists(); + }); + } +} \ No newline at end of file diff --git a/app/Model/Ad.php b/app/Model/Ad.php new file mode 100644 index 0000000..71cdbf9 --- /dev/null +++ b/app/Model/Ad.php @@ -0,0 +1,70 @@ + 'page', + 2 => 'webview', + 3 => 'applet', + ]; + + /** + * 类型 1 = 首页banners + */ + const TYPE_BANNER = 1; + + /** + * 启用状态 + */ + const STATUS_YES = 1; + const STATUS_NO = 2; + + /** + * The table associated with the model. + * + * @var string + */ + protected $table = 'ims_cjdc_ad'; + /** + * The attributes that are mass assignable. + * + * @var array + */ + protected $fillable = []; + /** + * The attributes that should be cast to native types. + * + * @var array + */ + protected $casts = []; + + protected $appends = [ + 'item_text', + 'redirect_url' + ]; + + /** + * 获取跳转说明 + */ + public function getItemTextAttribute() + { + return self::ITEM[$this->item]; + } + + /** + * 获取跳转连接 + */ + public function getRedirectUrlAttribute() + { + return $this->src ?: $this->src2; + } +} \ No newline at end of file diff --git a/app/Service/AdService.php b/app/Service/AdService.php new file mode 100644 index 0000000..77170ac --- /dev/null +++ b/app/Service/AdService.php @@ -0,0 +1,20 @@ +select(['id','title','logo','item','src','src2']) + ->where([ + 'type' => Ad::TYPE_BANNER, + 'status' => Ad::STATUS_YES + ])->get(); + } +} \ No newline at end of file diff --git a/app/Service/AdServiceInterface.php b/app/Service/AdServiceInterface.php new file mode 100644 index 0000000..f488422 --- /dev/null +++ b/app/Service/AdServiceInterface.php @@ -0,0 +1,11 @@ +exec('multi_hset', self::HASH_PREFIX.$token, $kvs)) { + if(false === $ssdb->exec('multi_hset', SsdbKeysPrefix::PARAMS_TOKEN.$token, $kvs)) { + + $this->log->event( + LogLabel::SSDB_LOG, + ['method' => 'multi_hset', 'key' => SsdbKeysPrefix::PARAMS_TOKEN.$token, 'kvs' => $kvs] + ); + throw new SsdbException(ErrorCode::SSDB_ERROR, 'token生成失败'); } return $token; } + /** + * 解析token获取对应数据参数 + * @param $token + */ public function analyze($token) { $ssdb = ApplicationContext::getContainer()->get(SSDBTask::class); - $params = $ssdb->exec('hgetall', self::HASH_PREFIX.$token); + $params = $ssdb->exec('hgetall', SsdbKeysPrefix::PARAMS_TOKEN.$token); if (false === $params) { + + $this->log->event( + LogLabel::SSDB_LOG, + ['method' => 'hgetall', 'key' => SsdbKeysPrefix::PARAMS_TOKEN.$token, 'params' => $params] + ); + throw new SsdbException(ErrorCode::SSDB_ERROR, 'token解析失败'); } if (empty($params)) { + + $this->log->event( + LogLabel::SSDB_LOG, + ['method' => 'hgetall', 'key' => SsdbKeysPrefix::PARAMS_TOKEN.$token, 'params' => $params] + ); + throw new SsdbException(ErrorCode::SSDB_ERROR, 'token不存在'); } diff --git a/config/autoload/dependencies.php b/config/autoload/dependencies.php index a26c378..2559546 100644 --- a/config/autoload/dependencies.php +++ b/config/autoload/dependencies.php @@ -13,6 +13,7 @@ return [ \App\Service\ServiceEvaluateServiceInterface::class => \App\Service\ServiceEvaluateService::class, \App\Service\AttachmentServiceInterface::class => \App\Service\AttachmentService::class, \App\Service\ParamsTokenServiceInterface::class => \App\Service\ParamsTokenSsdbService::class, + \App\Service\AdServiceInterface::class => \App\Service\AdService::class, \App\Commons\Log::class => \App\Commons\Log::class, \App\CouponRebate\CouponRebateInterface::class => \App\CouponRebate\CouponRebate::class, ]; diff --git a/config/autoload/exceptions.php b/config/autoload/exceptions.php index 6417a73..0aa0812 100644 --- a/config/autoload/exceptions.php +++ b/config/autoload/exceptions.php @@ -14,6 +14,7 @@ return [ 'http' => [ Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class, App\Exception\Handler\AppExceptionHandler::class, + App\Exception\Handler\ValidationExceptionHandler::class, App\Exception\Handler\SsdbExceptionHandler::class, ], ], diff --git a/config/autoload/listeners.php b/config/autoload/listeners.php index 55b80d5..2741751 100644 --- a/config/autoload/listeners.php +++ b/config/autoload/listeners.php @@ -10,4 +10,5 @@ declare(strict_types=1); * @license https://github.com/hyperf/hyperf/blob/master/LICENSE */ return [ + \App\Listener\ValidatorFactoryResolvedListener::class, ]; diff --git a/config/autoload/middlewares.php b/config/autoload/middlewares.php index 292a74a..5eb19a5 100644 --- a/config/autoload/middlewares.php +++ b/config/autoload/middlewares.php @@ -12,6 +12,7 @@ declare(strict_types=1); return [ 'http' => [ \App\Middleware\Auth\ApiMiddleware::class, + \Hyperf\Validation\Middleware\ValidationMiddleware::class, \App\Middleware\CorsMiddleware::class, ], ]; diff --git a/config/routes.php b/config/routes.php index 7305ea3..83a8e13 100644 --- a/config/routes.php +++ b/config/routes.php @@ -25,5 +25,6 @@ Router::addGroup('/v1/',function (){ Router::get('test/index1', 'App\Controller\TestController@index1'); Router::post('ParamsToken/generate', 'App\Controller\ParamsTokenController@generate'); Router::post('ParamsToken/analyze', 'App\Controller\ParamsTokenController@analyze'); - Router::post('CouponRebate/isCouponRebate', 'App\Controller\CouponRebateController@isCouponRebate'); + Router::post('Ad/banners', 'App\Controller\AdController@banners'); + Router::post('CouponRebate/isCouponRebate', 'App\Controller\CouponRebateController@isCouponRebate'); }); \ No newline at end of file