vendor and env first commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Anhskohbo\NoCaptcha\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class NoCaptcha extends Facade
|
||||
{
|
||||
/**
|
||||
* Get the registered name of the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'captcha';
|
||||
}
|
||||
}
|
||||
+246
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace Anhskohbo\NoCaptcha;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class NoCaptcha
|
||||
{
|
||||
const CLIENT_API = 'https://www.google.com/recaptcha/api.js';
|
||||
const VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
|
||||
|
||||
/**
|
||||
* The recaptcha secret key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secret;
|
||||
|
||||
/**
|
||||
* The recaptcha sitekey key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sitekey;
|
||||
|
||||
/**
|
||||
* @var \GuzzleHttp\Client
|
||||
*/
|
||||
protected $http;
|
||||
|
||||
/**
|
||||
* The cached verified responses.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $verifiedResponses = [];
|
||||
|
||||
/**
|
||||
* NoCaptcha.
|
||||
*
|
||||
* @param string $secret
|
||||
* @param string $sitekey
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($secret, $sitekey, $options = [])
|
||||
{
|
||||
$this->secret = $secret;
|
||||
$this->sitekey = $sitekey;
|
||||
$this->http = new Client($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render HTML captcha.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function display($attributes = [])
|
||||
{
|
||||
$attributes = $this->prepareAttributes($attributes);
|
||||
return '<div' . $this->buildAttributes($attributes) . '></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* @see display()
|
||||
*/
|
||||
public function displayWidget($attributes = [])
|
||||
{
|
||||
return $this->display($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a Invisible reCAPTCHA by embedding a callback into a form submit button.
|
||||
*
|
||||
* @param string $formIdentifier the html ID of the form that should be submitted.
|
||||
* @param string $text the text inside the form button
|
||||
* @param array $attributes array of additional html elements
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function displaySubmit($formIdentifier, $text = 'submit', $attributes = [])
|
||||
{
|
||||
$javascript = '';
|
||||
if (!isset($attributes['data-callback'])) {
|
||||
$functionName = 'onSubmit' . str_replace(['-', '=', '\'', '"', '<', '>', '`'], '', $formIdentifier);
|
||||
$attributes['data-callback'] = $functionName;
|
||||
$javascript = sprintf(
|
||||
'<script>function %s(){document.getElementById("%s").submit();}</script>',
|
||||
$functionName,
|
||||
$formIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
$attributes = $this->prepareAttributes($attributes);
|
||||
|
||||
$button = sprintf('<button%s><span>%s</span></button>', $this->buildAttributes($attributes), $text);
|
||||
|
||||
return $button . $javascript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render js source
|
||||
*
|
||||
* @param null $lang
|
||||
* @param bool $callback
|
||||
* @param string $onLoadClass
|
||||
* @return string
|
||||
*/
|
||||
public function renderJs($lang = null, $callback = false, $onLoadClass = 'onloadCallBack')
|
||||
{
|
||||
return '<script src="'.$this->getJsLink($lang, $callback, $onLoadClass).'" async defer></script>'."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify no-captcha response.
|
||||
*
|
||||
* @param string $response
|
||||
* @param string $clientIp
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyResponse($response, $clientIp = null)
|
||||
{
|
||||
if (empty($response)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true if response already verfied before.
|
||||
if (in_array($response, $this->verifiedResponses)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$verifyResponse = $this->sendRequestVerify([
|
||||
'secret' => $this->secret,
|
||||
'response' => $response,
|
||||
'remoteip' => $clientIp,
|
||||
]);
|
||||
|
||||
if (isset($verifyResponse['success']) && $verifyResponse['success'] === true) {
|
||||
// A response can only be verified once from google, so we need to
|
||||
// cache it to make it work in case we want to verify it multiple times.
|
||||
$this->verifiedResponses[] = $response;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify no-captcha response by Symfony Request.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyRequest(Request $request)
|
||||
{
|
||||
return $this->verifyResponse(
|
||||
$request->get('g-recaptcha-response'),
|
||||
$request->getClientIp()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recaptcha js link.
|
||||
*
|
||||
* @param string $lang
|
||||
* @param boolean $callback
|
||||
* @param string $onLoadClass
|
||||
* @return string
|
||||
*/
|
||||
public function getJsLink($lang = null, $callback = false, $onLoadClass = 'onloadCallBack')
|
||||
{
|
||||
$client_api = static::CLIENT_API;
|
||||
$params = [];
|
||||
|
||||
$callback ? $this->setCallBackParams($params, $onLoadClass) : false;
|
||||
$lang ? $params['hl'] = $lang : null;
|
||||
|
||||
return $client_api . '?'. http_build_query($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
* @param $onLoadClass
|
||||
*/
|
||||
protected function setCallBackParams(&$params, $onLoadClass)
|
||||
{
|
||||
$params['render'] = 'explicit';
|
||||
$params['onload'] = $onLoadClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send verify request.
|
||||
*
|
||||
* @param array $query
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function sendRequestVerify(array $query = [])
|
||||
{
|
||||
$response = $this->http->request('POST', static::VERIFY_URL, [
|
||||
'form_params' => $query,
|
||||
]);
|
||||
|
||||
return json_decode($response->getBody(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare HTML attributes and assure that the correct classes and attributes for captcha are inserted.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function prepareAttributes(array $attributes)
|
||||
{
|
||||
$attributes['data-sitekey'] = $this->sitekey;
|
||||
if (!isset($attributes['class'])) {
|
||||
$attributes['class'] = '';
|
||||
}
|
||||
$attributes['class'] = trim('g-recaptcha ' . $attributes['class']);
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build HTML attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function buildAttributes(array $attributes)
|
||||
{
|
||||
$html = [];
|
||||
|
||||
foreach ($attributes as $key => $value) {
|
||||
$html[] = $key.'="'.$value.'"';
|
||||
}
|
||||
|
||||
return count($html) ? ' '.implode(' ', $html) : '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Anhskohbo\NoCaptcha;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class NoCaptchaServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$app = $this->app;
|
||||
|
||||
$this->bootConfig();
|
||||
|
||||
$app['validator']->extend('captcha', function ($attribute, $value) use ($app) {
|
||||
return $app['captcha']->verifyResponse($value, $app['request']->getClientIp());
|
||||
});
|
||||
|
||||
if ($app->bound('form')) {
|
||||
$app['form']->macro('captcha', function ($attributes = []) use ($app) {
|
||||
return $app['captcha']->display($attributes, $app->getLocale());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Booting configure.
|
||||
*/
|
||||
protected function bootConfig()
|
||||
{
|
||||
$path = __DIR__.'/config/captcha.php';
|
||||
|
||||
$this->mergeConfigFrom($path, 'captcha');
|
||||
|
||||
if (function_exists('config_path')) {
|
||||
$this->publishes([$path => config_path('captcha.php')]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('captcha', function ($app) {
|
||||
return new NoCaptcha(
|
||||
$app['config']['captcha.secret'],
|
||||
$app['config']['captcha.sitekey'],
|
||||
$app['config']['captcha.options']
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return ['captcha'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'secret' => env('NOCAPTCHA_SECRET'),
|
||||
'sitekey' => env('NOCAPTCHA_SITEKEY'),
|
||||
'options' => [
|
||||
'timeout' => 30,
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user