0
votes

It's the First time that I use SP Page Builder component with Joomla. I want to use their contact form, but it doesn't support Google ReCaptcha. I'm good enough with coding to thought that I could manually add it into : /com_sppagebuilder/addons/ajax_contact/site.php and get it to work. I did add : <div class="g-recaptcha" data-sitekey="My_Key"></div>; And the Joomla ReCaptcha plugin is activated. I didn't know if I had to, but I added <script src='https://www.google.com/recaptcha/api.js'></script> into the head tag. With this the ReCaptcha is showing fine.

My problem is with the validation. I did try to add some validation code in the site.php but I believe SP Page Builder uses JFactory::getMailer(); to get the email ready and send it, and I don't know anything about that.

Thus, I do not know where I can add my ReCaptcha validation code, and as I did find few versions of that code online, I really don't know which one to use. I've been searching everywhere for some answers to how to do this verification... and I tried many things, but it's still not working.

Can anyone help me through this one ?

Thank you very much !

EDIT

I think my question is not clear enough :

I want to add Recaptcha, that is already working fine in other forms on my website (so it's not a configuration with Joomla problem). I want to use the following SP Page Builder contact form and not a RSFormPro as on the rest of the Website. The validation process should be done around this section, but I tried to add the Google validation code, and I tried a few versions of it I found around the Internet, and it's not working at all :

public static function getAjax() {
    $input = JFactory::getApplication()->input;
    $mail = JFactory::getMailer();

    //inputs
    $inputs             = $input->get('data', array(), 'ARRAY');

    foreach ($inputs as $input) {

        if( $input['name'] == 'recipient' ) {
            $recipient          = base64_decode($input['value']);
        }

        if( $input['name'] == 'email' ) {
            $email          = $input['value'];
        }

        if( $input['name'] == 'name' ) {
            $name           = $input['value'];
        }

        if( $input['name'] == 'subject' ) {
            $subject            = $input['value'];
        }

        if( $input['name'] == 'message' ) {
            $message            = nl2br( $input['value'] );
        }
    }

    /*Try at the validation*/
    $captcha_plugin = JFactory::getConfig()->get('captcha');
    if ($captcha_plugin != '0') {
    $captcha = JCaptcha::getInstance($captcha_plugin);
    $field_id = 'google-recaptcha';
     print $captcha->display($field_id, $field_id, 'g-recaptcha');
    }


    $sender = array($email, $name);
    $mail->setSender($sender);
    $mail->addRecipient($recipient);
    $mail->setSubject($subject);
    $mail->isHTML(true);
    $mail->Encoding = 'base64';
    $mail->setBody($message);

    if ($mail->Send()) {
        return '<span class="sppb-text-success">'. JText::_('COM_SPPAGEBUILDER_ADDON_AJAX_CONTACT_SUCCESS') .'</span>';
    } else {
        return '<span class="sppb-text-danger">'. JText::_('COM_SPPAGEBUILDER_ADDON_AJAX_CONTACT_FAILED') .'</span>';
    }
}

Any suggestions ?

Thank you !

3

3 Answers

0
votes

I have successfully added captcha to the Ajax contact form. Although the code still needs some improvements, Here is what I did:

See that I am using the n3tseznamcaptcha captcha plugin, I still need to implement the changes for other captchas to work (recaptcha,etc) but you can adapt it to your needs.

An SP Pagebuilder addon consists of two files, admin, and site. In the admin site I removed the default captcha, which lacks many security measures. Then in the site part I added the following:

function ajax_contact_addon($atts)
{
    global $formcaptcha;
    (...)
    if($formcaptcha) 
    {
            // TODO: Add Joomla's captcha:
            JPluginHelper::importPlugin('captcha');
            $dispatcher = JDispatcher::getInstance();

            // This will put the code to load CAPTCHA's JavaScript file into your <head>
            $dispatcher->trigger('onInit', 'dynamic_captcha_1');

            // This will return the array of HTML code.
            $captcha = $dispatcher->trigger('onDisplay', array(null, 'dynamic_captcha_1', 'class=""'));
            // I have only 1 recaptcha plugin enabled so the HTML is at 0 index, this will be improved in next version, following the contact component
            $output .= (isset($captcha[0])) ? $captcha[0] : '';
            $output .= '<div class="clearfix"></div><p></p>';
    }
    (...)
}

function ajax_contact_get_ajax() 
{
    global $formcaptcha;

    $jinput         = JFactory::getApplication()->input;
    $mail           = JFactory::getMailer();
    $config         = JFactory::getConfig();

    // TODO: CHECK CAPTCHA and add a Helper Class to get the captchas fields
    $captchaset = 'n3tseznamcaptcha';
    if ($captchaset === 'n3tseznamcaptcha')
    {   
        $captcha_field_hash = 'n3t_seznam_captcha_hash';
        $captcha_field_answer = 'n3t_seznam_captcha';
    }

    //inputs
    $inputs             = $jinput->get('data', array(), 'ARRAY');
    foreach ($inputs as $input) 
    {
            if( $input['name'] == 'title' ) 
            {
                $title                  = $input['value'];
            }
            if( $input['name'] == 'recipient' ) 
            {
                    $recipient      = base64_decode($input['value']);
            }

            if( $input['name'] == 'email' ) 
            {
                    $email          = $input['value'];
            }

            (...)

            if( $input['name'] == $captcha_field_hash ) 
            {
                    $captcha_hash   = $input['value'];
            }

            if( $input['name'] == $captcha_field_answer ) 
            {
                    $captcha_answer     = $input['value'];
            }
    }

    if($formcaptcha)
    {
            // get the plugin
            JPluginHelper::importPlugin('captcha');
            $dispatcher = JEventDispatcher::getInstance();

            // In order the plugin can check the code, we have to insert it into the request data:
            $jinput->set('n3t_seznam_captcha_hash', $captcha_hash);
            $jinput->set('n3t_seznam_captcha', $captcha_answer);

            // Here we check for the code:
            $res = $dispatcher->trigger('onCheckAnswer', $captcha_answer);

            if(!$res[0])
            {
                    // There is a problem with pagebuilder cache and captchas, so we need to clean the cache, to renew the captcha code:
                    $cache = JFactory::getCache('page');
                    $cache->clean();
                    return '<span class="pb-text-danger">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_FORM_WRONG_CAPTCHA') .'</span>';
            }
}

}

I think that's all. Hope it helps you to find out.

0
votes

So here you have the complete solution. Note that I changed a few things in the admin side too. This version will display and validate the default captcha selected in Joomla config, but it will only work for recaptcha and n3tsezam.. other should be added manually. The reason is that this addon does not add the challenge and response fields in the request, which the captcha plugins use for validation, therefor we need to retrieve it and write to the jinput within our ajax function (ajax_contact_get_ajax), and what complicates the whole thing is that every captcha plugin use different fields. Anyway.. if you need any other captcha plugin just can add it to the switch and you should be done.

function ajax_contact_addon($atts) {

        extract(AddonAtts(array(
                "title"             => '',
                "show_title"                    => '',
                "heading_selector"      => 'h3',
                "title_fontsize"        => '',
                "title_fontweight"      => '',
                "title_text_color"      => '',
                "title_margin_top"      => '',
                "title_margin_bottom"           => '',  
                "recipient_email"       => '',
                "formcaptcha"           => '',
                "class"             => '',
                ), $atts));

        JHtml::script('media/com_pagebuilder/js/ajax-contact.js');        

//      There is a problem with pagebuilder cache and captchas
        $cache = JFactory::getCache('page');
        $cache->clean();

        $output  = '<div class="pb-addon pb-addon-ajax-contact ' . $class . '">';

        if(boolval($show_title) && $title) 
        {

                $title_style = '';
                if($title_margin_top !='') $title_style .= 'margin-top:' . (int) $title_margin_top . 'px;';
                if($title_margin_bottom !='') $title_style .= 'margin-bottom:' . (int) $title_margin_bottom . 'px;';
                if($title_text_color) $title_style .= 'color:' . $title_text_color  . ';';
                if($title_fontsize) $title_style .= 'font-size:'.$title_fontsize.'px;line-height:'.$title_fontsize.'px;';
                if($title_fontweight) $title_style .= 'font-weight:'.$title_fontweight.';';

                $output .= '<'.$heading_selector.' class="pb-addon-title" style="' . $title_style . '">' . $title . '</'.$heading_selector.'>';
        }

        $output .= '<div class="pb-addon-content">';
        $output .= '<form class="pb-ajax-contact-form">';

        $output .= '<div class="pb-form-group">';
        $output .= '<input type="text" name="name" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_NAME') .'" required="required">';
        $output .= '</div>';

        $output .= '<div class="pb-form-group">';
        $output .= '<input type="email" name="email" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_EMAIL') .'" required="required">';
        $output .= '</div>';

        $output .= '<div class="pb-form-group">';
        $output .= '<input type="text" name="subject" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_SUBJECT') .'" required="required">';
        $output .= '</div>';

        $output .= '<div class="pb-form-group">';
        $output .= '<textarea type="text" name="message" rows="5" class="pb-form-control" placeholder="'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_MESSAGE') .'" required="required"></textarea>';
        $output .= '</div>';

        if($formcaptcha) 
        {
                JPluginHelper::importPlugin('captcha');
                $dispatcher = JDispatcher::getInstance();
                $dispatcher->trigger('onInit', 'dynamic_captcha_1');

                $captchas = $dispatcher->trigger('onDisplay', array(null, 'dynamic_captcha_1', 'class=""'));
                $index = 0;

                foreach (JPluginHelper::getPlugin('captcha') as $plugin)
                {
                        if (JFactory::getApplication()->get('captcha', '0') === $plugin->name)
                        {
                                $captcha = $captchas[$index];
                                break;
                        }
                        $index++;
                }
                $output .= (isset($captcha)) ? $captcha : '';
                $output .= '<div class="clearfix"></div><p></p>';
        }

        $output .= '<input type="hidden" name="recipient" value="'. base64_encode($recipient_email) .'">';
        $output .= '<input type="hidden" name="title" value="'. $title .'">';

        $output .= '<button type="submit" class="btn btn-default"><i class="fa"></i> '. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_SEND') .'</button>';

        $output .= '</form>';

        $output .= '<div style="display:none;margin-top:10px;" class="pb-ajax-contact-status"></div>';

        $output .= '</div>';

        $output .= '</div>';

        return $output;

}

function ajax_contact_get_ajax() 
{
        $config                         = JFactory::getConfig();
        $jinput             = JFactory::getApplication()->input;
        //inputs
        $inputs             = $jinput->get('data', array(), 'ARRAY');

        $mail               = JFactory::getMailer();

        // TODO: Find the way to check if captcha is enabled in the addon
        $formcaptcha = true;
        $message = "";

        // TODO: CHECK CAPTCHA and add a Helper Class to get the captchas
        switch (JFactory::getApplication()->get('captcha', '0'))
        {
            case 'recaptcha':
                // v.1:
                //$captcha_challenge_field = 'recaptcha_challenge_field';
                //$captcha_answer_field = 'recaptcha_response_field';
                // v.2:
                $captcha_challenge_field = '';
                $captcha_answer_field = 'g-recaptcha-response';
                break;
            case 'n3tseznamcaptcha':
                $captcha_challenge_field = 'n3t_seznam_captcha_hash';
                $captcha_answer_field = 'n3t_seznam_captcha';
                break;
            default:
                // disable captcha as we could not find the right fields
                $formcaptcha = false;
        }

        foreach ($inputs as $input) 
        {

                if( $input['name'] == 'title' ) 
                {
                        $title                  = $input['value'];
                }
                if( $input['name'] == 'recipient' ) 
                {
                        $recipient      = base64_decode($input['value']);
                }

                if( $input['name'] == 'email' ) 
                {
                        $email          = $input['value'];
                }

                if( $input['name'] == 'name' ) 
                {
                        $name           = $input['value'];
                }

                if( $input['name'] == 'subject' ) 
                {
                        $subject            = $input['value'];
                }

                if( $input['name'] == 'message' ) 
                {
                        $message            = nl2br( $input['value'] );
                }

                if( $input['name'] == $captcha_challenge_field ) 
                {
                        $captcha_challenge  = $input['value'];
                }

                if( $input['name'] == $captcha_answer_field ) 
                {
                        $captcha_answer     = $input['value'];
                }

        }

        $valid_captcha = true;
        if($formcaptcha)
        {
                // get the plugin
                JPluginHelper::importPlugin('captcha');
                $dispatcher = JEventDispatcher::getInstance();

                $jinput->set($captcha_challenge_field,  $captcha_challenge);
                $jinput->set($captcha_answer_field,     $captcha_answer);

                $res = $dispatcher->trigger('onCheckAnswer', $captcha_answer);

                $index = 0;
                foreach (JPluginHelper::getPlugin('captcha') as $plugin)
                {
                        if (JFactory::getApplication()->get('captcha', '0') === $plugin->name)
                        {
                                $valid_captcha = $res[$index];
                                break;
                        }
                        $index++;
                }
                if(!$valid_captcha)
                {
                    $msg = '<span class="pb-text-danger">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_FORM_WRONG_CAPTCHA') .'</span>';                        
                }
        }

        if ($valid_captcha)
        {
                // We do not want to send the email as a fake user, it may cause spam problems
                $sender = array( 
                        $config->get( 'mailfrom' ),
                        $config->get( 'fromname' ) 
                );

                $subject = (($title)? '['.$title.'] ' : '') . $subject;
                $message .= JText::sprintf('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_EMAIL_SIGNATURE', JUri::getInstance()->toString(),  JUri::getInstance());

                $mail->setSender($sender);
                $mail->addRecipient($recipient);
                $mail->setSubject($subject);
                $mail->AddReplyTo($email);
                $mail->isHTML(true);
                $mail->Encoding = 'base64'; 
                $mail->setBody($message);

                if ($mail->Send()) 
                {
                        $msg = '<span class="pb-text-success">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_SUCCESS') .'</span>';
                } else {
                        $msg = '<span class="pb-text-danger">'. JText::_('COM_PAGEBUILDER_ADDON_AJAX_CONTACT_FAILED') .'</span>';
                }
        }

//      There is a problem with pagebuilder cache and captchas
        $cache = JFactory::getCache('page');
        $cache->clean();

        return $msg;

}
0
votes

That functionality is now integrated into SP Page Builder Contact Form Addon.

1) Grab the reCaptcha API keys from the console: https://www.google.com/recaptcha/admin get recaptcha keys

2) Enable reCaptcha plugin in Joomla's backend: Joomla Control Panel and navigate to Extensions > Plugins > captcha - reCaptcha enable recaptcha plugin

3) Enable reCaptcha in your Joomla configuration: Go to System > Global Configuration > Site Settings > Default Captcha set joomla configutarion for recaptcha

4) Go to your Contact Form (or create a new one) and enable captcha. Then choose "CAPTCHA - reCAPTCHA" in Captcha type selector. set recaptcha on form

After completing the above steps, if you don't see a reCAPTCHA box on the contact form frontend, it means that your template uses the old contact addon code. In most cases, you can safely take a backup and then delete the (bold) folder: templates\YOUR-TEMPLATE-NAME\sppagebuilder\addons\ajax_contact

All the info you need is available in this article: https://www.joomshaper.com/blog/google-recaptcha-joomla-contact-forms-integration