Para entrar en materia quiesiera mencionar que Prestashop a día de hoy (versión 1.6) carece de un módulo gratuito que integre un captcha bien para dicha versión (SlideCaptcha a mí por lo menos no me dejaba configurarlo una vez instalado manualmente además) y los módulos que no son gratuitos tienen un precio que los programadores como yo nos negamos a pagar cuando puede hacerlo uno mismo.
No hace falta decir que hoy en día un formulario sin un captcha es «una diana de 20m» para los ataques masivos de mails, con lo que se me hace imprescindible implementar un captcha en la tienda online. Y la forma más rápida es utilizando el captcha de Google: reCaptcha, que está al servicio del usuario.
Pues bien, me he liado tanto pensado que era más dificil que no me he dado cuenta de que en realidad es más sencillo de lo que parecía, mucho más sencillo. Empecemos con el ejemplo del formulario de contacto, aunque se puede utilizar también en el resto de formularios (de registro, de login, etc…).
1º. Vamos a la página de reCaptcha y ponemos una etiqueta que equivale a un título e introducimos el dominio del captcha, en el caso de querer hacerlo para esta web sería: ivanros.com
2º Seguimos los pasos de Google para implementarlo. Copiamos este código en el archivo header.tpl que encontrarás en la carpeta raíz del servidor:
<script src='https://www.google.com/recaptcha/api.js'></script>
Y copiamos este código en /themes/[TU TEMA ACTIVO*]/contact-form.tpl (que es el archivo que muestra el html del formulario de contacto)
<div class="g-recaptcha" data-sitekey="[aquí la clave del sitio que te facilita Google]"></div>
*El tema activo por defecto es: default-bootstrap.
Hasta aquí tenemos la parte que Google te deja bien clarito, pero ahora los que como yo todavía nos queda mucho por aprender nos quedamos atascados hasta que de repente nos viene la inspiración y entre eso y algunos comentarios de soluciones en anteriores versiones de Prestashop damos con la solución.
3º Para terminar tenemos que ir a /controllers/front/ContactController.php (que es el archivo que realiza las comprobaciones del formulario de contacto) y donde pone
if (!($from = trim(Tools::getValue('from'))) || !Validate::isEmail($from)) $this->errors[] = Tools::displayError('Invalid email address.'); else if (!$message) $this->errors[] = Tools::displayError('The message cannot be blank.'); else if (!Validate::isCleanHtml($message)) $this->errors[] = Tools::displayError('Invalid message'); else if (!($id_contact = (int)(Tools::getValue('id_contact'))) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) $this->errors[] = Tools::displayError('Please select a subject from the list provided. '); else if (!empty($fileAttachment['name']) && $fileAttachment['error'] != 0) $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); else if (!empty($fileAttachment['name']) && !in_array( Tools::strtolower(substr($fileAttachment['name'], -4)), $extension) && !in_array( Tools::strtolower(substr($fileAttachment['name'], -5)), $extension)) $this->errors[] = Tools::displayError('Bad file extension'); else {
Añadimos esto antes del último else:
else if (!($gcaptcha = (int)(Tools::getValue('g-recaptcha-response')))) $this->errors[] = Tools::displayError('Captcha no verificado');
Lo que hacemos con esto es recoger en $gcaptcha el valor de g-recaptcha-response que es el resultado que envía Google de la operación del captcha y si no tiene valor añadimos al error que muestre «Captcha no verificado».
Quedando el código así:
if (!($from = trim(Tools::getValue('from'))) || !Validate::isEmail($from)) $this->errors[] = Tools::displayError('Invalid email address.'); else if (!$message) $this->errors[] = Tools::displayError('The message cannot be blank.'); else if (!Validate::isCleanHtml($message)) $this->errors[] = Tools::displayError('Invalid message'); else if (!($id_contact = (int)(Tools::getValue('id_contact'))) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) $this->errors[] = Tools::displayError('Please select a subject from the list provided. '); else if (!empty($fileAttachment['name']) && $fileAttachment['error'] != 0) $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); else if (!empty($fileAttachment['name']) && !in_array( Tools::strtolower(substr($fileAttachment['name'], -4)), $extension) && !in_array( Tools::strtolower(substr($fileAttachment['name'], -5)), $extension)) $this->errors[] = Tools::displayError('Bad file extension'); else if (!($gcaptcha = (int)(Tools::getValue('g-recaptcha-response')))) $this->errors[] = Tools::displayError('Captcha no verificado'); else {
Puedes comprobar ahora a realizar rellenar el formulario de contacto que si no escribes el captcha te saldrá «Captcha no verificado» y si lo rellenas todo correctamente se enviará el correo sin problemas.
Y eso es todo. Fácil, ¿no?. Pues me ha llevado mucho más tiempo pensarlo que escribirlo. Por lo que os lo facilito al resto de comunidad internauta, puesto que seguro no seré ni el primero ni el último con este dilema.
Un saludo!
Iván Ros
EDITO: lo mejor es ponerlo en un override. Creamos un archivo llamado ContactController.php dentro de /override/controllers/front/ con este código:
<?php /* * 2015 Iván Ros * * RECAPTCHA */ class ContactController extends ContactControllerCore { /** * Sobreescritura del método postProcess para añadir el requisito del reCaptcha */ public function postProcess() { if (Tools::isSubmit('submitMessage')) { $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); $file_attachment = Tools::fileAttachment('fileUpload'); $message = Tools::getValue('message'); // Html entities is not usefull, iscleanHtml check there is no bad html tags. $seguir = true; if (!($from = trim(Tools::getValue('from'))) || !Validate::isEmail($from)) $this->errors[] = Tools::displayError('Invalid email address.'); $seguir = false; if (!$message) $this->errors[] = Tools::displayError('The message cannot be blank.'); $seguir = false; if (!Validate::isCleanHtml($message)) $this->errors[] = Tools::displayError('Invalid message'); $seguir = false; if (!($id_contact = (int)Tools::getValue('id_contact')) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) $this->errors[] = Tools::displayError('Please select a subject from the list provided. '); $seguir = false; if (!empty($file_attachment['name']) && $file_attachment['error'] != 0) $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); $seguir = false; if (!empty($file_attachment['name']) && !in_array(Tools::strtolower(substr($file_attachment['name'], -4)), $extension) && !in_array(Tools::strtolower(substr($file_attachment['name'], -5)), $extension)) $this->errors[] = Tools::displayError('Bad file extension'); $seguir = false; // EDITO IVÁN - Añadimos el reCaptcha if (!($gcaptcha = (int)(Tools::getValue('g-recaptcha-response')))) $this->errors[] = Tools::displayError('Captcha no verificado'); $seguir = false; if ($seguir == true) { $customer = $this->context->customer; if (!$customer->id) $customer->getByEmail($from); $id_order = (int)$this->getOrder(); if (!(( ($id_customer_thread = (int)Tools::getValue('id_customer_thread')) && (int)Db::getInstance()->getValue(' SELECT cm.id_customer_thread FROM '._DB_PREFIX_.'customer_thread cm WHERE cm.id_customer_thread = '.(int)$id_customer_thread.' AND cm.id_shop = '.(int)$this->context->shop->id.' AND token = \''.pSQL(Tools::getValue('token')).'\'') ) || ( $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($from, $id_order) ))) { $fields = Db::getInstance()->executeS(' SELECT cm.id_customer_thread, cm.id_contact, cm.id_customer, cm.id_order, cm.id_product, cm.email FROM '._DB_PREFIX_.'customer_thread cm WHERE email = \''.pSQL($from).'\' AND cm.id_shop = '.(int)$this->context->shop->id.' AND ('. ($customer->id ? 'id_customer = '.(int)$customer->id.' OR ' : '').' id_order = '.(int)$id_order.')'); $score = 0; foreach ($fields as $key => $row) { $tmp = 0; if ((int)$row['id_customer'] && $row['id_customer'] != $customer->id && $row['email'] != $from) continue; if ($row['id_order'] != 0 && $id_order != $row['id_order']) continue; if ($row['email'] == $from) $tmp += 4; if ($row['id_contact'] == $id_contact) $tmp++; if (Tools::getValue('id_product') != 0 && $row['id_product'] == Tools::getValue('id_product')) $tmp += 2; if ($tmp >= 5 && $tmp >= $score) { $score = $tmp; $id_customer_thread = $row['id_customer_thread']; } } } $old_message = Db::getInstance()->getValue(' SELECT cm.message FROM '._DB_PREFIX_.'customer_message cm LEFT JOIN '._DB_PREFIX_.'customer_thread cc on (cm.id_customer_thread = cc.id_customer_thread) WHERE cc.id_customer_thread = '.(int)$id_customer_thread.' AND cc.id_shop = '.(int)$this->context->shop->id.' ORDER BY cm.date_add DESC'); if ($old_message == $message) { $this->context->smarty->assign('alreadySent', 1); $contact->email = ''; $contact->customer_service = 0; } if ($contact->customer_service) { if ((int)$id_customer_thread) { $ct = new CustomerThread($id_customer_thread); $ct->status = 'open'; $ct->id_lang = (int)$this->context->language->id; $ct->id_contact = (int)$id_contact; $ct->id_order = (int)$id_order; if ($id_product = (int)Tools::getValue('id_product')) $ct->id_product = $id_product; $ct->update(); } else { $ct = new CustomerThread(); if (isset($customer->id)) $ct->id_customer = (int)$customer->id; $ct->id_shop = (int)$this->context->shop->id; $ct->id_order = (int)$id_order; if ($id_product = (int)Tools::getValue('id_product')) $ct->id_product = $id_product; $ct->id_contact = (int)$id_contact; $ct->id_lang = (int)$this->context->language->id; $ct->email = $from; $ct->status = 'open'; $ct->token = Tools::passwdGen(12); $ct->add(); } if ($ct->id) { $cm = new CustomerMessage(); $cm->id_customer_thread = $ct->id; $cm->message = $message; if (isset($file_attachment['rename']) && !empty($file_attachment['rename']) && rename($file_attachment['tmp_name'], _PS_UPLOAD_DIR_.basename($file_attachment['rename']))) { $cm->file_name = $file_attachment['rename']; @chmod(_PS_UPLOAD_DIR_.basename($file_attachment['rename']), 0664); } $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); $cm->user_agent = $_SERVER['HTTP_USER_AGENT']; if (!$cm->add()) $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } else $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } if (!count($this->errors)) { $var_list = array( '{order_name}' => '-', '{attached_file}' => '-', '{message}' => Tools::nl2br(stripslashes($message)), '{email}' => $from, '{product_name}' => '', ); if (isset($file_attachment['name'])) $var_list['{attached_file}'] = $file_attachment['name']; $id_product = (int)Tools::getValue('id_product'); if (isset($ct) && Validate::isLoadedObject($ct) && $ct->id_order) { $order = new Order((int)$ct->id_order); $var_list['{order_name}'] = $order->getUniqReference(); $var_list['{id_order}'] = (int)$order->id; } if ($id_product) { $product = new Product((int)$id_product); if (Validate::isLoadedObject($product) && isset($product->name[Context::getContext()->language->id])) $var_list['{product_name}'] = $product->name[Context::getContext()->language->id]; } if (empty($contact->email)) Mail::Send($this->context->language->id, 'contact_form', ((isset($ct) && Validate::isLoadedObject($ct)) ? sprintf(Mail::l('Your message has been correctly sent #ct%1$s #tc%2$s'), $ct->id, $ct->token) : Mail::l('Your message has been correctly sent')), $var_list, $from, null, null, null, $file_attachment); else { if (!Mail::Send($this->context->language->id, 'contact', Mail::l('Message from contact form').' [no_sync]', $var_list, $contact->email, $contact->name, $from, ($customer->id ? $customer->firstname.' '.$customer->lastname : ''), $file_attachment) || !Mail::Send($this->context->language->id, 'contact_form', ((isset($ct) && Validate::isLoadedObject($ct)) ? sprintf(Mail::l('Your message has been correctly sent #ct%1$s #tc%2$s'), $ct->id, $ct->token) : Mail::l('Your message has been correctly sent')), $var_list, $from, null, $contact->email, $contact->name, $file_attachment)) $this->errors[] = Tools::displayError('An error occurred while sending the message.'); } } if (count($this->errors) > 1) array_unique($this->errors); elseif (!count($this->errors)) $this->context->smarty->assign('confirmation', 1); } } } } ?>
Lo que conseguimos con esto, además de tenerlo en un override, si os dais cuenta, he quitado los elseif por if solo para que, como en el registro, muestre todos los errores de una vez, y no pare por cada error. Mucho más útil.
Sencillo, breve y muy UTIL!!!
La verdad es que yo había conseguido modificar bien la plantilla, me quedaba el ContactController, que no me «atrevía» a tocarlo.
Un 10 para este artículo!
Muchas gracias!
Gracias a ti por leer mi artículo.
Espero que además de ayudarte en este caso en específico, te ayude a «atreverte» a que, como yo, toques y encuentres más soluciones.
Un saludo.
Gracias por el aporte estimado, todo funciona perfectamente! Saludos.
Buenas,
Lo primero, gracias por el articulo. En mi caso no me funciona, pero no lo he seguido al pie de la letra. lo mismo es por eso.
La modificacion en cuestion es usar /themes/[TU TEMA ACTIVO*]/header.tpl en lugar del header.tpl (que me parecia muy bestia) para el js de google….
Me sale el recaptcha lo hago y va. Pero si lo pongo mal a posta sigue tragando¿Deberia funcionar, no?
Un saludo
Vale, parece que la forma correcta de hacerlo (para que no se nos vaya el codigo en actualizaciones) seria crearse un archivo
/override/controllers/front/ContactController.php
Para que extienda la clase
—-
<?php
class ContactController extends ContactControllerCore
{
public function postProcess()
{
——
y a partir de aqui ya extenderla…. lo mismo con el resto de controladores que queramos sobre escribir como el del creacion de usuarios que estoy buscando ahora mismo
Mi granito de arena 🙂
Un saludo y gracias por el post original
Muchas gracias por tu aporte.
Perdona por no haber respondido antes. Espero le pueda valer a más gente, por lo menos a indagar sobre el tema y crear su solución.
Un saludo!
Hola,
Gracias por el aporte.
He seguido todos los pasos, tan solo cambiando que, en vez de colocar el primer script en heder.php, lo he hecho en heder.tpl como comentaba Enrique.
Bien, el reCaptcha ahora me aparece, cosa que no pasaba antes, pero al validarlo, y enviar el mensaje sigue apareciendo el mensaje de error
Error 1
El captcha no se ha introducido correctamente. Por favor, pruebe de nuevo
y por supuesto no envía el mensaje.
Alguna solución?
Gracias de antemano.
Como siempre, perdona la tardanza en responder, tengo poco tiempo para dedicarle a mi propia web. AntonioC, ¿qué formulario está teniendo el problema?¿Formulario de contacto, de alta?
Si es el de contacto copia la parte de la validación del archivo /controllers/front/ContactController.php para que vea si es un problema dentro de la validación.
Un saludo.
A mi me ocurre lo mismo pero en el formulario donde se valida el correo para crear un nuevo usuario, sin embargo en el formulario de contacto funciona sin problemas.
Dejo aquie el codigo:
protected function processSubmitCreate()
{
if (!Validate::isEmail($email = Tools::getValue(‘email_create’)) || empty($email))
$this->errors[] = Tools::displayError(‘Invalid email address.’);
elseif (Customer::customerExists($email))
{
$this->errors[] = Tools::displayError(‘An account using this email address has already been registered. Please enter a valid password or request a new one. ‘, false);
$_POST[‘email’] = Tools::getValue(‘email_create’);
unset($_POST[‘email_create’]);
}else if (!($gcaptcha = (int)(Tools::getValue(‘g-recaptcha-response’))))
$this->errors[] = Tools::displayError(‘Captcha no verificado’);
else
{
$this->create_account = true;
$this->context->smarty->assign(‘email_create’, Tools::safeOutput($email));
$_POST[‘email’] = $email;
}
En efecto son apartados diferentes, el ContactController.php sirve para el formulario de contacto, y el AuthController.php sirve para el registro y login de usuarios.
Ivan, por lo que veo ese código es del AuthController.php, pero ¿te funciona así? Porque yo al principio también lo puse en esa función dado que es la del propio Create, sin embargo no me guardaba bien la respuesta del captcha al pasar a rellenar los datos de usuario y terminar la operación, dado que siempre me decía «Captcha no verificado». Sin embargo al ponerla en la función «protected function processSubmitAccount()» me funcionó a la perfección. No existe ese primer paso que deseamos, pero tenemos el captcha justo donde lo queremos, antes de ingresar los datos a la base de datos. Te pongo donde puse yo el código para el captcha:
— Línea 377 (AuthController.php) – protected function processSubmitAccount() —
—-
Compruébalo a ver si fue un problema mío o si realmente no funciona como se espera.
Gracias por tu aporte.
Efectivamente se trata del authcontroller, pero Ivan tengo una duda, en que parte de la plantilla pones el captcha, y que he estado probando en diferentes posiciones y no consiguo que se muestre.
Gracias.
Para que te lo muestre tienes que coger la plantilla authentication.tpl de tu tema (/themes/TU-TEMA/authentication.tpl)
yo lo tengo en la línea 645, pero tengo varias modificaciones, no sé si caerá en la misma línea en tu archivo. Lo pongo dentro del form justo antes del {$HOOK_CREATE_ACCOUNT_FORM}. Añadimos tanto el script de recaptcha como el div que te facilita Google.
— línea 544 (authentication.tpl) —
—
En este caso te lo muestra después de poner tu correo y validarlo, cuando rellenas los datos de usuario.
Un saludo.
Gracias tocayo, ahora si que me funciona me faltaba poner el script del recaptcha. Voy a intentar hacer lo mismo con el login y tenia la curiosidad de saber si lo has intentado.
No lo he intentado porque, aunque sea útil, pagan justos por pecadores. Es de lo más pesado y feo para el cliente que cada vez que quiera loguearse tenga que poner el capcha, y en mi caso no puedo permitirme que el cliente vea la página complicada y pesada, puesto que es un cliente que es posible perder.
Pero imagino que irá por el mismo camino. Si tienes problemas o dudas me vas diciendo e intento ayudar.
Aunque todo esto me ha dado una idea que voy a querer desarrollar, poner el captcha pero una vez haya fallado 3 veces el logueo. A ver qué sale de ahí…
La verdad es que me lo estaba replanteando por eso mismo que plantes y tambien por pereza jeje. Pero lo que propones del fallo de login me parece interesante, aunque creo que de momento no lo voy a hacer es algo que meditare para un futuro.
Gracias! Hoy leí este otro https://zarza.com/captcha-para-verificacion-humana/ y viene super bien explicado, espero les sea de utilidad.
Estimado gracias por el aporte hice todo lo que indicas sin embargo no se muestra el captcha en el formulario de contacto estoy en prestashop 1.6.1 . Gracias por el apoyo
Fallo mío, puse header.php, sin embargo, este cambio hay que hacerlo en el header.tpl. Recomiendo ponerlo justo encima de la etiqueta de cierre
head
Un saludo! y perdonad la errata
Buenas ivan estuve haciendo pruebas y con el de contacto me funciona perfecto, pero por mas que modifico el autentication.tpl no me sale, no aparece el captcha, no se si me podrias ayudar
Hola Ivan, he leído varias veces el post y respuestas, intento colocar varias veces el capcha en el formulario de contacto pero no se muestra, sin embargo al intentar enviarlo me da el error «Error 1 Captcha no verificado», he seguído todos los pasos pero no muestra el capcha, a que puede ser debido?, sera del header.tpl ?
Cambios
themes/default-bootstrap/header.tpl linea 59
themes/default-bootstrap/contact-form.tpl linea 144
controllers/front/ContactController.php linea 55 else if (!($gcaptcha = (int)(Tools::getValue(‘g-recaptcha-response’))))
$this->errors[] = Tools::displayError(‘Captcha no verificado’);
Buenas tardes Juan, perdona que no responda antes. Tengo poco tiempo para mi web. Puede ser que no estés recogiendo bien el captcha de Google o puede que no hayas creado los permisos necesarios para tu web para que se muestre. Como el reconocimiento del reCaptcha va por separado de si se muestra o no, siempre te da el error. Revisa bien que en Google esté todo correcto. Y prueba a darle a F12 en el navegador y comprueba que no haya fallos.
Un saludo
Buenas tardes Ivan
He seguido los 3 pasos que indicas,pero no me sale el captcha en mi web, sino que me sale «error del servidor» y no me muesta nada.
Siguiendo las instrucciones de «google recaptcha» me falta hacer este paso, y no se como hacerlo….ni donde tengo que ir…
When your users submit the form where you integrated reCAPTCHA, you’ll get as part of the payload a string with the name «g-recaptcha-response». In order to check whether Google has verified that user, send a POST request with these parameters:
URL: https://www.google.com/recaptcha/api/siteverify
secret (required) xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
response (required) El valor de «g-recaptcha-response».
remoteip The end user’s ip address.
Me podrías indicar como hacer este paso? Quizás es lo que me falta para que me muestre el recaptcha en mi web.
Gracias
Lo que mencionas es el paso 3. El trato de los datos por parte del servidor. La comprobación de que está bien o no. Como le digo a Juan, comprueba que la API tenga permiso para tu URL, comprueba con F12 en tu navegador si no está dando ningún fallo al cargar reCaptcha y que existe en HTML, no vaya a ser que no haya cargado la modificación en tu web.
Un saludo
Llevo meses muy locos. A ver si os puedo dar una solución en breve 😉
Todo funcionó perfecto y a la primera. ¡gracias por el aporte!
Hola, me funcionó a la perfección pero quiero ponerlo en el formulario de registro y ya lo he podido colocar pero no puedo hacer que sea obligatorio verificarlo porque aunque no lo verifiquen sigue con el registro, he estado probando en el Authentication.tpl y el AuthController.php pero no logro conseguir hacerlo, si pudieras ayudarme. Gracias por la ayuda con el Captcha para el formulario.
Para que el captcha sea requisito tendrás que cambiar el AuthController.php tal y como yo lo hice en el ContactController.php. En este caso iremos a la función: protected function processSubmitAccount() y al acabar todos los checkeos, justo antes de «// Preparing customer» línea 381 pones esto:
No obstante lo óptimo es hacer un override como hicimos al final con ContactController.php con el siguiente código:
Ya me dices si te sirve.
Un saludo
Hola IvanR, antes de nada muchas gracias por publicar la integración. Me funciona perfectamente en el formulario de contacto.
Quiero poner el Captcha en el formulario para crear un nuevo usuario. ¿Cuales son los pasos y que códigos y archivos debo crear?
Gracias de antemano.
Buenas! Gracias por tu aporte Iván, me aparece el ReCaptcha, el problema es que aunque no lo marques, el mensaje se envía con éxito… ¿Sabes que puede ser?
Saludos
GRACIAS!! me funcionó. Pero no veo forma de agregarlo al formulario de registro 🙁
Hola,
gracias por la aportación para introducir el captcha. Lo he seguido paso a paso en un par de webs que tengo, y en una me funciona perfectamente y en la otra no.
Es el formulario de contacto lo que no me funciona, me sale el captcha, si no lo hago no me deja enviar, completo el captcha y una vez completado le doy a enviar y se vuelve a cargar la página con el formulario y los valores que tenía. No recibo mail alguno ni mensaje de formulario enviado con éxito.
He creado ContactController.php dentro de /override/controllers/front/
No sé que hacer, porque si quito el código del capcha el formualario funciona bien.
¿Alguna idea?
Muchas gracias!
Santi, ¿Solucionaste? Me pasa igual… ?
Hola, saben si anda en prestashop 1.7?
Hola,
En primer lugar, gracias por el tutorial. Lamentablemente llevo todo el día con ello y no hay forma. He estado leyendo también los comentarios, pero nada. He probado tanto con el formulario de contacto como con el de creación de usuario, que es el principal objetivo.
Centrándonos en el formulario de creación de usuario, el código de la parte final del authentication.tlp es el siguiente (viendo que en un comentario dices de poner todo junto, tanto el script como el div):
{$HOOK_CREATE_ACCOUNT_FORM}
{if isset($back)}{/if}
{l s=’Register’}
*{l s=’Required field’}
No obstante no se muestra nada 🙁
Una pregunta…. ahí estás cogiendo la respuesta del módulo recaptcha del formulario, y mostrando un error si no existe respuesta. Pero… ¿cómo te aseguras de que la respuesta es válida? Quiero decir, que un bot perfectamente puede colocarte un campo g-recaptcha-response con contenido, y te lo tragarías porque no es comprobado. Creo que a tu solución le falta la verificación de la respuesta recibida, dentro del ContactController.php,
Buenos días!
Tengo todavía pendiente responderos a unos cuantos. Voy a ir a los sencillo que es responder esta última cuestión. Google reCaptcha se encarga de que su botón lo suficientemente seguro como para que un bot no sea capaz de enviar el dato que espera recibir. Si reCaptcha cree que aun así tiene dudas de tu “humanidad” te solicita que introduzcas el indeseado Captcha, ya sea de forma de escritura o con las imágenes, etc… Por lo tanto, al enviar el formulario reCaptcha te da la respuesta si lo ha verificado, pero si no lo ha verificado no te da respuesta. Solo responde si está verificado por Google reCaptcha. Es lo sencillo del asunto, no tienes que comprobar en tu página si es un dato válido o no, solo si recibes, dado que realiza la verificación en el cliente, no en el servidor.
No tengo los conocimientos para darte muchos detalles sobre cómo realiza su verificación y demás, pero esa es la esencia del asunto y lo útil de Google reCaptcha.
Un saludo.
Iván Ros
Si, yo no dudo de la seguridad del reCaptcha de Google. Lo que me refiero es que tú, en el código que propones, simplemente se comprueba que exista «algo» dentro del campo «g-recaptcha-response» (que es un texarea que crea el reCaptcha) al recibir los datos. Pero… ¿qué te asegura que un bot, igual que te rellena el resto de campos del formulario (nombre, e-mail, etc) no te pueda introducir también algo dentro de ese campo?. Simplemente con Jquery se puede hacer, no es nada complicado.
A lo que me refiero es que yo abro ahora mismo una página con la protección recaptcha que planteas, accedo a la consola de desarrollador, introduzco con código JQuery:
[code]
$(«#g-recaptcha-response»).val(«1234»);
[/code]
… y ya estoy verificando tu comprobación, sin necesidad de haber resuelto el reChaptcha. Porque al revisar desde el ContactController.php si hay datos en ese campo me va a salir que sí los hay, ya que no se comprueba la validez de esos datos. De hecho, he probado a hacerlo así, y «cuela» sin ningún problema.
Bajo mi punto de vista, ahí falta una comprobación de que los datos que se han recibido realmente se corresponden con una verificación válida, lo cual no sé muy bien cómo se hace, pero creo que necesita de alguna librería PHP de Google e implica utilizar las clases y objetos de esa librería.
Yo me he basado en la información facilitada por Google. No he inventado nada nuevo. Google utiliza tokens, con lo que si hicieras lo que mencionas, reCaptcha ya se asegura de que si no recibe el token, no dé por válido lo que introduce y por lo tanto no devuelva nada.
No obstante, puede que me equivoque, ¿has probado lo que mencionas? ¿Funciona?
Lo he probado y funciona. Creo que no estamos hablando de lo mismo. Yo hablo de «saltarnos» la verificación del reCaptcha, no de engañarla.
Te digo cómo lo puedes probar tú mismo: Vas al formulario donde tengas instalado el reChaptcha en la forma que has comentado. Ahí rellenas todos los datos EXCEPTO el reCaptcha. Luego abres la consola del navegador (CTRL+F12 en Windows), y ahí tecleas simplemente esto:
$(“#g-recaptcha-response”).val(“1234”);
Ahí estamos introduciendo un valor dentro del campo de respuesta del rechaptcha de nuestro formulario, obviando la respuesta de éste. Le das al botón de enviar formulario, y verás cómo «cuela» y se lo traga.
Y es normal, porque en la verificación desde el PHP sólo se comprueba que haya «algo» en el campo de respuesta de Recaptcha. Pero ese algo puede ser cualquier número, es necesario comprobar que ese número coincida con lo que Google acaba de verificar, y eso creo que es necesario hacerlo a través de librerias de clases de Google para PHP.
Perdona por responder de nuevo, no sé si queda claro mi planteamiento:
Un formulario web consiste en una serie de campos «input», dentro de los cuales se introduce la información. Esa información es luego enviada al destino especificado en el formulario, donde se procesa (en este caso, al ContactController.php). El problema con los «bots», y de ahí la necesidad de utilizar un reCaptcha, es que te pueden acceder a tu formulario, rellenar automáticamente el contenido de tus campos input y enviarlo para su verificación. Y si están todos los campos rellenos, colará.
Si introduces un reCaptcha, en la práctica lo que haces es introducir un campo input nuevo en tu formulario (en este caso es un textarea, pero a efectos prácticos da lo mismo). Y ese campo será enviado junto al resto de inputs del formulario para su verificación.
El reCaptcha de Google crea ese textarea en principio vacío, y no le dota de contenido hasta que no ser resuelve la verificación. Pero si tú manualmente (o el bot de forma automática), introduce contenido dentro de ese campo, la verificación que planteas en el controlador lo dará por bueno, porque simplemente estás comprobando que ese campo tenga contenido y que sea un número. Nada más.
Yo planteo que esa verificación es incompleta, que falta una parte, que es comprobar que el número que se recibe desde ese textarea (g-recaptcha-response), realmente procede de una verificación exitosa de Google, y que no se lo ha inventado cualquiera y rellenado de forma automática.
Vale, ya comprendo lo que dices. Efectivamente yo me refería a otra cosa. Pues tengo que revisar bien lo que dice Google sobre el tema y qué herramientas se pueden utilizar para esperar un determinado parámetro. Si alguien encuentra algo antes que yo, por favor, compartidlo con la Comunidad.
Gracias!
Creo que los tiros van por aquí (no he comprobado aún si funciona):
https://gist.github.com/jonathanstark/dfb30bdfb522318fc819
Saludos, como puedo implementarlo en el formulario de registro???? Grcias
Genial Ivan! Enhorabuena, lo he puesto sin problema en naturaonline.es
¡Perfecto! En ese caso enhorabuena también a ti. Un placer haber podido ayudar.
Hola, gracias por el aporte, pero no me aparece el botón de recaptcha en contacto. He seguido todo, pero es como si esa div no se mostrase. Con el inspector de elemento tampoco la veo. Alguna solución? Gracias
Buenos días MarcosPG. ¿Has borrado la caché de la plantilla? Independientemente de que funcione o no, si no se ve en el código fuente ni el div en el contact-form.tpl ni el script en el header.tpl, el problema radica ahí, en que no está ejecutando la última versión de la plantilla. Tienes varias formas de hacerlo (recomiendo la forma 1):
1- Si no lo tienes instalado, instala el módulo Flush Caches & Compile y una vez instalado arriba en Limpiar haz click en «Limpia todo».
2- Parámetros avanzados > Rendimiento. En la sección Smarty, seleccióna forzar compilación y Caché > No
3- Accede mediante FTP al directorio donde tengas instalado Prestashop y borra el contenido de las siguientes carpetas:
Ya me dices el resultado que te da.
Hola!
Gracias por tu aportación, es muy fácil de integrar , no obstante lo he insertado en dos sitios y en ambos tengo el mismo problema, aparece el recaptcha correctamente pero no valida si lo introduces o verificas, en ambos casos solamente con e mail es suficiente para poder enviar correctamente el correo. Es como si el override no hiciera la función que tiene encomendada.
¿Sabes o sabéis que puede estar pasando?
Muchas gracias!
Buenos días Iván,
En primer lugar gracias por el aporte.
Lo he puesto siguiendo escrupulosamente tus pasos en el formulario de contacto de nuestra tienda http://www.muñecasatodotrapo.com y me pasa lo mismo que ha los compañeros Santi y Lluvia. Funciona bien, pero aún poniendo el reCaptcha correcto cuando doy a enviar el formulario, en lugar de hacerlo, se recarga el mismo formulario con todos los datos que he rellenado, no me da el mensaje de formulario enviado, no envía nada y no recibo correo alguno. Me gustaría me ayudases antes de implementarlo en otros formularios de la tienda.
Gracias de nuevo por adelantado, un saludo
Hola.
No consigo hacer que se vea el recaptcha en el contact-form.tpl y lo he puesto en distintos sitios.
He seguido todos los pasos al pie de la letra pero no consigo que se vea, alguna ayuda
Hola,
Gracias por tu aportacion… lo he probado en el formulario de contacto de un prestashop 1.6.0.9 y ha funcionado perfectamente.
Sin embargo lo he vuelto a probar en un prestashop 1.6.1.11 y no funciona. El problema está en el archivo ContactController.php ya que al subirlo al directorio /override/Controllers/front/ entonces no carga la página correctamente (error500).
Sospecho que para prestashop 1.6.1.11 las lineas de codigo a añadir no son las indicadas en el blog pero no veo cual puede ser el error.
Las lineas a añadir al fichero ContactController.php son estas:
else if (!($gcaptcha = (int)(Tools::getValue(‘g-recaptcha-response’))))
$this->errors[] = Tools::displayError(‘Captcha no verificado’);
Este es el codigo original de ContactController.php + las lineas añadidas:
public function postProcess()
{
if (Tools::isSubmit(‘submitMessage’)) {
$extension = array(‘.txt’, ‘.rtf’, ‘.doc’, ‘.docx’, ‘.pdf’, ‘.zip’, ‘.png’, ‘.jpeg’, ‘.gif’, ‘.jpg’);
$file_attachment = Tools::fileAttachment(‘fileUpload’);
$message = Tools::getValue(‘message’); // Html entities is not usefull, iscleanHtml check there is no bad html tags.
if (!($from = trim(Tools::getValue(‘from’))) || !Validate::isEmail($from)) {
$this->errors[] = Tools::displayError(‘Invalid email address.’);
} elseif (!$message) {
$this->errors[] = Tools::displayError(‘The message cannot be blank.’);
} elseif (!Validate::isCleanHtml($message)) {
$this->errors[] = Tools::displayError(‘Invalid message’);
} elseif (!($id_contact = (int)Tools::getValue(‘id_contact’)) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) {
$this->errors[] = Tools::displayError(‘Please select a subject from the list provided. ‘);
} elseif (!empty($file_attachment[‘name’]) && $file_attachment[‘error’] != 0) {
$this->errors[] = Tools::displayError(‘An error occurred during the file-upload process.’);
} elseif (!empty($file_attachment[‘name’]) && !in_array(Tools::strtolower(substr($file_attachment[‘name’], -4)), $extension) && !in_array(Tools::strtolower(substr($file_attachment[‘name’], -5)), $extension)) {
$this->errors[] = Tools::displayError(‘Bad file extension’);
else if (!($gcaptcha = (int)(Tools::getValue(‘g-recaptcha-response’)))) errors[] = Tools::displayError(‘Captcha no verificado’); context->customer;
if (!$customer->id) {
$customer->getByEmail($from);
}
$id_order = (int)$this->getOrder();
…Alguien sabe porqué sucede este error?
Gracias
El código sirve para las versiones 1.6.0.X, tengo que comprobar las variaciones de este archivo en versiones posteriores.
Respecto a tu código veo bastantes errores. Cambia esto:
else if (!($gcaptcha = (int)(Tools::getValue(‘g-recaptcha-response’)))) errors[] = Tools::displayError(‘Captcha no verificado’); context->customer;
Por esto otro
elseif (!($gcaptcha = (int)(Tools::getValue('g-recaptcha-response'))))
$this->errors[] = Tools::displayError('Captcha no verificado'); context->customer; }
A tener en cuenta:
– Une ese elseif como el resto
– Te faltó poner $this-> antes de errors[]
– Te faltó cerrar la llave } antes del siguiente if
– Comprueba que las comillas son comillas simples ‘ y no ‘ o ’. Al copiar y pegar a veces se transforma
Mi consejo es que no lo pongas todo en una línea porque no se ve bien y se te pueden colar muchos errores.
Prueba como te digo y nos dices.
Genial solución. Mil gracias, util y eficaz!!
Soys unos cracks!!! Solucionado!
Muchísimas gracias! 🙂
Recordad limpiar la caché…
Muchas gracias.
Me costo pero al final pude.
Consejos:
1. cuando cree el formulario en google para generar el captcha, solo me funciono seleccionando ReCaptcha V2, para que me saliera la opcion de «im not a robot» Las demas nunca me funcionaron.
2. Lo del ContactController.php no me funciono, me quedo mas facil agregar el IF. en principio me salia error pero era porque me faltaba agregar el «{» Entonces tengan presente eso.
3. Si no les aparece el captcha, verifiquen que la linea la estan agregando antes del /form o del /head.
En mi caso esta linea:
La agregue antes del /form y me funciono.
4. El contactcontroller.php o la opcionn del else if, solo sirve para validar, por lo cual pueden probar primero que les aparezca el captcha y si funciona luego siguen con la opcion de la validar.
5. No sobra decirlo pero desde prestashop deben forzar compilacion.
Un genio al autor gracias!
Muchas gracias por tu aporte. Llevo un tiempo fuera de juego y me alegra ver que otros usuarios aportan sus soluciones.
Para tomar nota, ¿qué versión de Prestashop tienes?
Gracias por compartir tu sabiduría. Namaste!
Buenas tardes a todos desde Venezuela,
Alguien podrá ayudarme, yo hice todos los pasos, y me aparece el capcha solo que si marco el captcha o lo dejo sin marcar igual se envian los datos. Yo copie el contactcontroller en override con el codigo sugerido de IVAN, pero me ocurre no valida si marco o no el captcha.
Agradeciendo el apoyo de todos ustedes,
Muy cordialmente,
JOSE G