diff --git a/app/Constants/v3/ActivityType.php b/app/Constants/v3/ActivityType.php index 1ef89e7..c1abead 100644 --- a/app/Constants/v3/ActivityType.php +++ b/app/Constants/v3/ActivityType.php @@ -3,7 +3,11 @@ namespace App\Constants\v3; use Hyperf\Constants\AbstractConstants; +use Hyperf\Constants\Annotation\Constants; +/** + * @Constants + */ class ActivityType extends AbstractConstants { /** diff --git a/app/Constants/v3/ErrorCode.php b/app/Constants/v3/ErrorCode.php index f70ea9a..b49c2ea 100644 --- a/app/Constants/v3/ErrorCode.php +++ b/app/Constants/v3/ErrorCode.php @@ -3,32 +3,73 @@ namespace App\Constants\v3; use Hyperf\Constants\AbstractConstants; +use Hyperf\Constants\Annotation\Constants; +/** + * @Constants + */ class ErrorCode extends AbstractConstants { /************************************/ /* 应用或系统相关,参考HTTP STATUS */ /************************************/ /** + * 服务器内部错误 * @Message("服务器内部错误") */ - const SERVER_ERROR=500; + const SERVER_ERROR = 500; /************************************/ /* 订单相关 601-650 */ /************************************/ - /************************************/ /* 支付相关 651-700 */ /************************************/ - /************************************/ /* 用户相关 701-750 */ /************************************/ + /** + * 验证码错误或已失效 + * @Message("验证码错误或已失效") + */ + const INVALID_VERIFY_CODE = 701; + + /** + * 电话号码绑定失败 + * @Message("电话号码绑定失败") + */ + const BIND_TEL_ERROR = 702; + + /** + * 电话号码解绑失败 + * @Message("电话号码解绑失败") + */ + const UNBIND_TEL_ERROR = 703; /************************************/ /* 定位相关 751-800 */ /************************************/ + + /************************************/ + /* 公共相关 1001-1100 */ + /************************************/ + /** + * 获取验证码失败 + * @Message("获取验证码失败") + */ + const VERIFY_CODE_ERROR = 1001; + + /** + * 验证码已发送,请勿重复请求 + * @Message("验证码已发送,请勿重复请求") + */ + const VERIFY_CODE_SENDED = 1002; + + /** + * 短信发送失败 + * @Message("短信发送失败") + */ + const SMS_SEND_FAILURE = 1003; } \ No newline at end of file diff --git a/app/Constants/v3/OrderState.php b/app/Constants/v3/OrderState.php index 8b9bff9..d0c6fb8 100644 --- a/app/Constants/v3/OrderState.php +++ b/app/Constants/v3/OrderState.php @@ -3,11 +3,10 @@ namespace App\Constants\v3; use Hyperf\Constants\AbstractConstants; +use Hyperf\Constants\Annotation\Constants; /** - * 订单状态 - * Class OrderState - * @package App\Constants\v3 + * @Constants */ class OrderState extends AbstractConstants { diff --git a/app/Constants/v3/OrderType.php b/app/Constants/v3/OrderType.php index 48c1cf7..04de630 100644 --- a/app/Constants/v3/OrderType.php +++ b/app/Constants/v3/OrderType.php @@ -3,11 +3,10 @@ namespace App\Constants\v3; use Hyperf\Constants\AbstractConstants; +use Hyperf\Constants\Annotation\Constants; /** - * 订单类型 - * Class OrderType - * @package App\Constants\v3 + * @Constants */ class OrderType extends AbstractConstants { diff --git a/app/Constants/v3/Payment.php b/app/Constants/v3/Payment.php index eede0bb..fecae2b 100644 --- a/app/Constants/v3/Payment.php +++ b/app/Constants/v3/Payment.php @@ -3,11 +3,10 @@ namespace App\Constants\v3; use Hyperf\Constants\AbstractConstants; +use Hyperf\Constants\Annotation\Constants; /** - * 支付相关 - * Class Payment - * @package App\Constants\v3 + * @Constants */ class Payment extends AbstractConstants { diff --git a/app/Constants/v3/SmsTemplateCode.php b/app/Constants/v3/SmsTemplateCode.php new file mode 100644 index 0000000..3a2b1d1 --- /dev/null +++ b/app/Constants/v3/SmsTemplateCode.php @@ -0,0 +1,17 @@ +response diff --git a/app/Controller/v3/SmsController.php b/app/Controller/v3/SmsController.php new file mode 100644 index 0000000..4d6eaa2 --- /dev/null +++ b/app/Controller/v3/SmsController.php @@ -0,0 +1,41 @@ +validated(); + // 获取并发送验证码 + $this->verifyCodeService->make($params['user_id'], $params['tel']); + + return $this->success([]); + } +} \ No newline at end of file diff --git a/app/Controller/v3/UserController.php b/app/Controller/v3/UserController.php new file mode 100644 index 0000000..58112ac --- /dev/null +++ b/app/Controller/v3/UserController.php @@ -0,0 +1,44 @@ +validated(); + // 校验验证码 + $this->verifyCodeService->check($params['user_id'], $params['tel'], $params['verify_code']); + // 绑定 + $this->userBindService->makeTel($params['user_id'], $params['tel']); + + return $this->success([]); + } +} \ No newline at end of file diff --git a/app/Exception/ErrorCodeException.php b/app/Exception/ErrorCodeException.php new file mode 100644 index 0000000..aabf9be --- /dev/null +++ b/app/Exception/ErrorCodeException.php @@ -0,0 +1,29 @@ +logger = $logger; + } + + public function handle(Throwable $throwable, ResponseInterface $response) + { + $this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile())); + $this->logger->error($throwable->getTraceAsString()); + + $this->stopPropagation(); + + $content = json_encode([ + "status" => 'error', + "code" => $throwable->getCode(), + "result" => [], + "message" => $throwable->getMessage() + ]); + + return $response->withHeader('Content-Type', 'application/json') + ->withStatus(200) + ->withBody(new SwooleStream($content)); + } + + public function isValid(Throwable $throwable): bool + { + return $throwable instanceof ErrorCodeException; + } +} \ No newline at end of file diff --git a/app/Middleware/Auth/UserMiddleware.php b/app/Middleware/Auth/UserMiddleware.php index d843008..2341ceb 100644 --- a/app/Middleware/Auth/UserMiddleware.php +++ b/app/Middleware/Auth/UserMiddleware.php @@ -2,14 +2,39 @@ namespace App\Middleware\Auth; +use Hyperf\HttpServer\Contract\RequestInterface as HttpRequest; +use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse; +use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -class UserMiddleware implements MiddlewareInterface +class UserMiddleware implements MiddlewareInterface { + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @var HttpResponse + */ + protected $response; + + /** + * @var HttpRequest + */ + protected $request; + + public function __construct(ContainerInterface $container, HttpResponse $response, HttpRequest $request) + { + $this->container = $container; + $this->response = $response; + $this->request = $request; + } + /** * @inheritDoc */ diff --git a/app/Model/v3/User.php b/app/Model/v3/User.php new file mode 100644 index 0000000..af37927 --- /dev/null +++ b/app/Model/v3/User.php @@ -0,0 +1,10 @@ + 'required|nonempty|integer|exists:ims_cjdc_user,id', + 'user_id' => 'required|nonempty|integer|exists:lanzu_user,id', ]; } diff --git a/app/Request/v3/UserBindTelRequest.php b/app/Request/v3/UserBindTelRequest.php new file mode 100644 index 0000000..0020a6a --- /dev/null +++ b/app/Request/v3/UserBindTelRequest.php @@ -0,0 +1,44 @@ + 'required|nonempty|exists_enable:ims_cjdc_user,id', + 'tel' => 'required|nonempty|tel', + 'verify_code' => 'required|nonempty|numeric|strlen:6,6', + ]; + } + + /** + * @return array + */ + public function messages(): array + { + return [ + 'user_id.*' => ':attribute未登录或无效', + 'tel.*' => ':attribute无效', + 'verify_code.*' => ':attribute格式有误', + ]; + } + + public function attributes(): array + { + return [ + 'user_id' => '用户', + 'tel' => '手机号码', + 'verify_code' => '验证码', + ]; + } +} diff --git a/app/Request/v3/VerifyCodeRequest.php b/app/Request/v3/VerifyCodeRequest.php new file mode 100644 index 0000000..425d875 --- /dev/null +++ b/app/Request/v3/VerifyCodeRequest.php @@ -0,0 +1,41 @@ + 'required|nonempty|exists_enable:ims_cjdc_user,id', + 'tel' => 'required|nonempty|tel', + ]; + } + + /** + * @return array + */ + public function messages(): array + { + return [ + 'user_id.*' => ':attribute未登录或无效', + 'tel.*' => ':attribute无效', + ]; + } + + public function attributes(): array + { + return [ + 'user_id' => '用户', + 'tel' => '手机号码', + ]; + } +} diff --git a/app/Service/v3/Implementations/HelperService.php b/app/Service/v3/Implementations/HelperService.php new file mode 100644 index 0000000..22766a6 --- /dev/null +++ b/app/Service/v3/Implementations/HelperService.php @@ -0,0 +1,20 @@ +regionId($aliSms['regionid']) + ->asDefaultClient(); + + $result = AlibabaCloud::rpc() + ->product($aliSms['product']) + ->version('2017-05-25') + ->action('SendSms') + ->method('POST') + ->host($aliSms['host']) + ->options([ + 'query' => [ + 'RegionId' => $aliSms['regionid'], + 'PhoneNumbers' => $tel, + 'SignName' => $aliSms['sign_name'], + 'TemplateCode' => $template, + 'TemplateParam' => $templateParams, + ], + ]) + ->request(); + return $result->toArray(); + } catch (ClientException $e) { + $this->log->event('alisms', ['alisms_error_ClientException' => $e->getErrorMessage()]); + throw new ErrorCodeException(ErrorCode::SMS_SEND_FAILURE); + } catch (ServerException $e) { + $this->log->event('alisms', ['alisms_error_ServerException' => $e->getErrorMessage()]); + throw new ErrorCodeException(ErrorCode::SMS_SEND_FAILURE); + } catch (Exception $e) { + $this->log->event('alisms', ['alisms_error_Exception' => $e->getErrorMessage()]); + throw new ErrorCodeException(ErrorCode::SMS_SEND_FAILURE); + } + } + + public function makeVerifyCode($tel, $code) + { + $params = ['user_name' => '疯狂的水叔叔', 'market_name' => '验证码', 'money' => $code]; + return $this->send($tel, SmsTemplateCode::ALI_VERIFY_CODE, json_encode($params)); + } + + public function checkVerifyCode($tel, $code) + { + // TODO: Implement checkVerifyCode() method. + } + + public function removeVerifyCode($tel, $code) + { + // TODO: Implement removeVerifyCode() method. + } +} \ No newline at end of file diff --git a/app/Service/v3/Implementations/UserBindService.php b/app/Service/v3/Implementations/UserBindService.php new file mode 100644 index 0000000..3dc6b88 --- /dev/null +++ b/app/Service/v3/Implementations/UserBindService.php @@ -0,0 +1,38 @@ +tel = $tel; + if (!$user->save()) { + throw new ErrorCodeException(ErrorCode::BIND_TEL_ERROR); + } + return true; + } + + public function checkTel($userId) + { + $user = User::find($userId); + return $user->tel ? true : false; + } + + public function removeTel($userId) + { + $user = User::find($userId); + $user->tel = ''; + if (!$user->save()) { + throw new ErrorCodeException(ErrorCode::UNBIND_TEL_ERROR); + } + return true; + } +} \ No newline at end of file diff --git a/app/Service/v3/Implementations/VerifyCodeService.php b/app/Service/v3/Implementations/VerifyCodeService.php new file mode 100644 index 0000000..abb48cd --- /dev/null +++ b/app/Service/v3/Implementations/VerifyCodeService.php @@ -0,0 +1,89 @@ +helperService->makeNumCode(6); + + // 存到SSDB + $ssdbClient = ApplicationContext::getContainer()->get(SSDBTask::class); + $setRes = $ssdbClient->exec( + "setnx", + SsdbKeys::VERIFY_CODE.$userId.'_'.$tel, + $verifyCode + ); + if (!$setRes) { + throw new ErrorCodeException(ErrorCode::VERIFY_CODE_SENDED); + } + + $expireRes = $ssdbClient->exec( + 'expire', + SsdbKeys::VERIFY_CODE.$userId.'_'.$tel, + 900 + ); + if (!$expireRes) { + throw new ErrorCodeException(ErrorCode::VERIFY_CODE_ERROR); + } + + // 发送短信 + $smsRes = $this->smsService->makeVerifyCode($tel, $verifyCode); + if (!$smsRes) { + throw new ErrorCodeException(ErrorCode::VERIFY_CODE_ERROR); + } + + return true; + } + + public function check($userId, $tel, $verifyCode) + { + // 获取验证码并验证 + $ssdbClient = ApplicationContext::getContainer()->get(SSDBTask::class); + $code = $ssdbClient->exec( + "get", + SsdbKeys::VERIFY_CODE.$userId.'_'.$tel + ); + if (empty($code) || $verifyCode!=$code) { + throw new ErrorCodeException(ErrorCode::INVALID_VERIFY_CODE); + } + + $this->remove($userId, $tel); + return true; + + } + + public function remove($userId, $tel) + { + $ssdbClient = ApplicationContext::getContainer()->get(SSDBTask::class); + return $ssdbClient->exec( + 'del', + SsdbKeys::VERIFY_CODE.$userId.'_'.$tel + ); + } +} \ No newline at end of file diff --git a/app/Service/v3/Interfaces/HelperServiceInterface.php b/app/Service/v3/Interfaces/HelperServiceInterface.php new file mode 100644 index 0000000..4c0088c --- /dev/null +++ b/app/Service/v3/Interfaces/HelperServiceInterface.php @@ -0,0 +1,8 @@ + \App\Service\SmsAliService::class, \App\Service\OrderListServiceInterface::class => \App\Service\OrderListService::class, \App\Service\v3\Interfaces\GoodsServiceInterface::class => \App\Service\v3\Implementations\GoodsService::class, + \App\Service\v3\Interfaces\SmsServiceInterface::class => \App\Service\v3\Implementations\SmsAliService::class, + \App\Service\v3\Interfaces\HelperServiceInterface::class => \App\Service\v3\Implementations\HelperService::class, + \App\Service\v3\Interfaces\VerifyCodeServiceInterface::class => \App\Service\v3\Implementations\VerifyCodeService::class, + \App\Service\v3\Interfaces\UserBindServiceInterface::class => \App\Service\v3\Implementations\UserBindService::class, + ]; diff --git a/config/autoload/exceptions.php b/config/autoload/exceptions.php index 8d97cf6..8e650c7 100644 --- a/config/autoload/exceptions.php +++ b/config/autoload/exceptions.php @@ -13,10 +13,11 @@ return [ 'handler' => [ 'http' => [ Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class, - App\Exception\Handler\AppExceptionHandler::class, App\Exception\Handler\ValidationExceptionHandler::class, + App\Exception\Handler\ErrorCodeExceptionHandler::class, App\Exception\Handler\SsdbExceptionHandler::class, - \App\Exception\Handler\FilesystemExceptionHandler::class, + App\Exception\Handler\FilesystemExceptionHandler::class, + App\Exception\Handler\AppExceptionHandler::class, ], ], ]; diff --git a/config/config.php b/config/config.php index 66529cf..d731652 100644 --- a/config/config.php +++ b/config/config.php @@ -47,6 +47,7 @@ return [ 'regionid' => env('ALI_SMS_REGION_ID', ''), 'product' => env('ALI_SMS_PRODUCT', ''), 'host' => env('ALI_SMS_HOST', ''), + 'sign_name' => env('ALI_SMS_SIGN_NAME', ''), ], 'alioss' => [ 'img_host' => env('OSS_IMG_HOST', ''), diff --git a/config/routes.php b/config/routes.php index d975362..3a7e042 100644 --- a/config/routes.php +++ b/config/routes.php @@ -85,5 +85,6 @@ Router::addGroup('/v3/', function () { // 需要登录的路由 Router::addGroup('/v3/', function () { - + Router::post('sms/getVerifyCode', 'App\Controller\v3\SmsController@getVerifyCode'); + Router::post('user/bindTel', 'App\Controller\v3\UserController@bindTel'); },['middleware' => [\App\Middleware\Auth\ApiMiddleware::class, \App\Middleware\Auth\UserMiddleware::class]]); \ No newline at end of file