├── .gitignore ├── src ├── Utils │ ├── LuoCaptchaRequestInterface.php │ ├── Contracts │ │ └── LuoCaptcha.php │ └── LuoCaptchaException.php ├── LuoCaptchaServiceProvider.php └── LuoCaptcha.php ├── composer.json ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor 3 | .env 4 | .DS_Store 5 | .bak 6 | -------------------------------------------------------------------------------- /src/Utils/LuoCaptchaRequestInterface.php: -------------------------------------------------------------------------------- 1 | '验证码服务器挂了', 11 | -10 => 'API_KEY为空', 12 | -11 => '验证码为空', 13 | -20 => '验证码验证失败', 14 | -40 => 'API_KEY错误 请勿把使用SITE_KEY当做API_KEY使用', 15 | ]; 16 | protected $data = []; 17 | 18 | public function __construct($message, $code, $data = null) 19 | { 20 | if($data != null) $this->data = $data; 21 | parent::__construct($message, $code); 22 | } 23 | 24 | public function getData() 25 | { 26 | return $this->data; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xiaohuilam/luo-captcha", 3 | "type": "library", 4 | "authors": [ 5 | { 6 | "name": "xiaohuilam" 7 | } 8 | ], 9 | "prefer-stable": true, 10 | "minimum-stability": "dev", 11 | "require": { 12 | "php": ">=5.6", 13 | "ext-curl": "*", 14 | "ext-json": "*", 15 | "guzzlehttp/guzzle": "^6.3", 16 | "laravelcollective/html": "~5.4" 17 | }, 18 | "require-dev": { 19 | "arcanedev/laravel-html": "~5.0", 20 | "phpunit/phpcov": "~2.0|~3.0", 21 | "phpunit/phpunit": "~4.0|~5.0" 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "Luosimao\\Captcha\\": "src/" 26 | } 27 | }, 28 | "autoload-dev": { 29 | "psr-4": { 30 | "Luosimao\\Captcha\\Tests\\": "tests/" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Xiaohui Lam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LARAVEL-LUOSIMAO 2 | The ultimate captcha for chinese end users, luosimao. This package brings you a fast method to install the captcha function into your project. 3 | 4 | 5 | # HOW TO GET LUOSIMAO CAPTCHA 6 | https://luosimao.com/service/captcha 7 | 8 | 9 | # INSTALL 10 | ``` 11 | composer require xiaohuilam/luo-captcha 12 | ``` 13 | ``` 14 | vim .env 15 | #NOCAPTCHA_SITEKEY={site key} 16 | #NOCAPTCHA_SECRET={api key} 17 | ``` 18 | ``` 19 | vim config/app.php 20 | #add bellow into providers 21 | Luosimao\Captcha\LuoCaptchaServiceProvider::class, 22 | 23 | #add bellow into aliases: 24 | 'Captcha' => Luosimao\Captcha\LuoCaptcha::class, 25 | ``` 26 | 27 | # CODE 28 | add this into your form 29 | ``` 30 | {!! Form::captcha() !!} 31 | ``` 32 | 33 | and add this script into your script 34 | ``` 35 | {!! Captcha::script() !!} 36 | ``` 37 | 38 | add validator 39 | ``` 40 | $this->validate($request, [ 41 | 'luotest_response' => 'required|captcha', 42 | ]); 43 | ``` 44 | 45 | # DEMO 46 | 47 |  49 |  50 | 51 | https://api.wallet.casa/login 52 | 53 | -------------------------------------------------------------------------------- /src/LuoCaptchaServiceProvider.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class LuoCaptchaServiceProvider extends IlluminateServiceProvider 14 | { 15 | /* ------------------------------------------------------------------------------------------------ 16 | | Properties 17 | | ------------------------------------------------------------------------------------------------ 18 | */ 19 | /** 20 | * Package name. 21 | * 22 | * @var string 23 | */ 24 | protected $package = 'luo-captcha'; 25 | 26 | /* ------------------------------------------------------------------------------------------------ 27 | | Main Functions 28 | | ------------------------------------------------------------------------------------------------ 29 | */ 30 | /** 31 | * Register the service provider. 32 | */ 33 | public function register() 34 | { 35 | $this->registerLuoCaptcha(); 36 | } 37 | 38 | /** 39 | * Bootstrap the application events. 40 | */ 41 | public function boot() 42 | { 43 | $this->registerFormMacros($this->app); 44 | $this->registerValidatorRules($this->app); 45 | } 46 | 47 | /** 48 | * Get the services provided by the provider. 49 | * 50 | * @return array 51 | */ 52 | public function provides() 53 | { 54 | return [ 55 | \Luosimao\Captcha\Utils\Contracts\LuoCaptcha::class, 56 | ]; 57 | } 58 | 59 | /* ------------------------------------------------------------------------------------------------ 60 | | Other Functions 61 | | ------------------------------------------------------------------------------------------------ 62 | */ 63 | /** 64 | * Register NoCaptcha service. 65 | */ 66 | private function registerLuoCaptcha() 67 | { 68 | $this->singleton(\Luosimao\Captcha\Utils\Contracts\LuoCaptcha::class, function($app) { 69 | /** @var \Illuminate\Contracts\Config\Repository $config */ 70 | $config = $app['config']; 71 | 72 | return new LuoCaptcha( 73 | $config->get('no-captcha.sitekey'), 74 | $config->get('no-captcha.secret') 75 | ); 76 | }); 77 | } 78 | 79 | /** 80 | * Register Validator rules. 81 | * 82 | * @param \Illuminate\Foundation\Application $app 83 | */ 84 | private function registerValidatorRules($app) 85 | { 86 | $callback = function($attribute, $value) use ($app) { 87 | unset($attribute); 88 | $ip = $app['request']->getClientIp(); 89 | return $app[\Luosimao\Captcha\Utils\Contracts\LuoCaptcha::class]->verify($value, $ip); 90 | }; 91 | 92 | if ($app->bound('validator')) { 93 | $app['validator']->extend('captcha', $callback); 94 | } else { 95 | \Illuminate\Support\Facades\Validator::extend('captcha', $callback); 96 | } 97 | } 98 | 99 | /** 100 | * Register Form Macros. 101 | * 102 | * @param \Illuminate\Foundation\Application $app 103 | */ 104 | private function registerFormMacros($app) 105 | { 106 | if ($app->bound('form')) { 107 | $app['form']->macro('captcha', function($name = null, array $attributes = []) use ($app) { 108 | return $app[\Luosimao\Captcha\LuoCaptcha::class]->display($name, $attributes); 109 | }); 110 | } 111 | } 112 | 113 | protected function singleton($abstract, $concrete = null) 114 | { 115 | $this->app->singleton($abstract, $concrete); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/LuoCaptcha.php: -------------------------------------------------------------------------------- 1 | setSecret($secret); 58 | $this->setSiteKey($siteKey); 59 | } 60 | 61 | public function display($name = null, array $attributes = []) 62 | { 63 | return '
'; 64 | } 65 | 66 | public static function script() 67 | { 68 | $script = ''; 69 | if ( ! self::$scriptLoaded) { 70 | $script = ''; 71 | self::$scriptLoaded = true; 72 | } 73 | return $script; 74 | } 75 | 76 | /** 77 | * Calls the reCAPTCHA siteverify API to verify whether the user passes CAPTCHA 78 | * test using a PSR-7 ServerRequest object. 79 | * 80 | * @param \Psr\Http\Message\ServerRequestInterface $request 81 | * 82 | * @return bool 83 | */ 84 | public function verifyRequest(ServerRequestInterface $request) 85 | { 86 | $ip_header = getenv('REQUEST_IP_HEADER', 'REMOTE_ADDR'); 87 | $body = $request->getParsedBody(); 88 | $server = $request->getServerParams(); 89 | $response = isset($body[self::CAPTCHA_NAME]) ? $body[self::CAPTCHA_NAME] : ''; 90 | $remoteIp = isset($server[$ip_header]) ? $server[$ip_header] : null; 91 | 92 | return $this->verify($response, $remoteIp); 93 | } 94 | 95 | public function verify($response, $clientIp = null) 96 | { 97 | if (!$response) 98 | $response = $this->request->input[self::CAPTCHA_NAME]; 99 | 100 | if (!$response) 101 | throw new LuoCaptchaException(LuoCaptchaException::ERR_MSG[LuoCaptchaException::BAD_RESPONSE], LuoCaptchaException::BAD_RESPONSE); 102 | 103 | $response = $this->sendVerifyRequest([ 104 | 'api_key' => $this->secret, 105 | 'response' => $response, 106 | 'remoteip' => $clientIp 107 | ]); 108 | if($response['error'] != 0) 109 | return false; //throw new LuoCaptchaException(LuoCaptchaException::ERR_MSG[$response['error']], $response['error']); 110 | 111 | return (isset($response['error']) && (0 === $response['error'])) === true; 112 | } 113 | 114 | /** 115 | * Set the secret key. 116 | * 117 | * @param string $secret 118 | * @return self 119 | */ 120 | protected function setSecret($secret) 121 | { 122 | $this->secret = $secret; 123 | return $this; 124 | } 125 | 126 | protected function getSecret() 127 | { 128 | return $this->secret; 129 | } 130 | 131 | /** 132 | * Set Site key. 133 | * 134 | * @param string $siteKey 135 | * @return self 136 | */ 137 | protected function setSiteKey($siteKey) 138 | { 139 | $this->siteKey = $siteKey; 140 | return $this; 141 | } 142 | 143 | protected function getSiteKey() 144 | { 145 | return $this->siteKey; 146 | } 147 | 148 | protected function setRequest(LuoCaptchaRequestInterface $request) 149 | { 150 | $this->request = $request; 151 | return $this; 152 | } 153 | 154 | /** 155 | * 发送验证请求 156 | */ 157 | protected function sendVerifyRequest($params) 158 | { 159 | $client = new Client(); 160 | $response = $client->request('POST', self::VERIFY_URL, [ 161 | 'form_params' => $params, 162 | ]); 163 | if($response->getStatusCode() != 200) 164 | throw new LuoCaptchaException(LuoCaptchaException::ERR_MSG[LuoCaptchaException::API_SERVER_FAIL], LuoCaptchaException::API_SERVER_FAIL); 165 | 166 | $json = $response->getBody(); 167 | $json = json_decode($json, true); 168 | 169 | return $json; 170 | } 171 | } 172 | --------------------------------------------------------------------------------