<p>Upgrading to the latest versions will likely resolve any issues with the default implementation. There was a bug in the timing of our javascript that was resolved in <a href="https://github.com/barrelstrength/sprout-forms/blob/v3/CHANGELOG.md#31320---2023-03-17" rel="nofollow noreferrer">3.13.20</a>.</p>

CC BY-SA 4.0
2023-11-05T12:31:14.953Z
2023-11-05T12:31:14.953Z
Ben Parizek
<p>I'm using Sprout Forms V3 on Craft 3. I'm trying to handle the submit within a controller.
This choice is made to add a custom logic, to implement a Google reCAPTCHA (as the official Sprout's plugin isn't working).</p>
<p>This is the JS part:</p>
<pre><code>grecaptcha.ready(function() {
    // Verify reCAPTCHA
    grecaptcha.execute(recaptchaSiteKey, { action: 'contactForm' }).then(function(token) {
        // Send the token to the server for verification
        var data = {
            token: token,
            action: 'contactForm',
            formData: $form.serialize()
        };
        data[csrfTokenName] = csrfTokenValue;
        fetch('/actions/utilities-module/captcha', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(data),
        })
        .then(data =&gt; {
            console.log(data);
            if (data === true) {
                console.log('success');
            } else {
                console.log('error');
            }
        });
    });
});
</code></pre>
<p>and the controller part:</p>
<pre><code>public function actionIndex()
{
    // Check CSRF
    $this-&gt;requirePostRequest();

    // Call cURL to POST request
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,&quot;https://www.google.com/recaptcha/api/siteverify&quot;);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
        'secret' =&gt; getenv('GOOGLE_RECAPTCHA_SECRET_KEY'),
        'response' =&gt; Craft::$app-&gt;getRequest()-&gt;getParam('token')
    )));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($response, true);

    // Verify the response 
    if ($response[&quot;success&quot;] &amp;&amp; $response[&quot;action&quot;] == 'contactForm' &amp;&amp; $response[&quot;score&quot;] &gt;= 0.9) {

        // Process the form
        $formData = Craft::$app-&gt;getRequest()-&gt;getParam('formData');
        $response = Craft::$app-&gt;runAction('sprout-forms/entries/save-entry', [
            'handle' =&gt; 'contact',
            'submission' =&gt; $formData
        ]);

        if (!$response['success']) {
            return $this-&gt;asJson(false);
        }

        return $this-&gt;asJson(true);

    } else {
        return $this-&gt;asJson(false);
    }
}
</code></pre>
<p>The issue here is that it's always failing. Looks like the <code>Craft::$app-&gt;runAction()</code> is missing something to process.</p>
<p>Any idea what's wrong?</p>

<plugin-sproutforms><controller><plugin-recaptcha><sprout>
How to run Sprout Forms action from a controller to implement Google reCAPTCHA?
# How to run Sprout Forms action from a controller to implement Google reCAPTCHA?

(Asked by: username_0 on 2023-08-18)

I'm using Sprout Forms V3 on Craft 3. I'm trying to handle the submit within a controller.
This choice is made to add a custom logic, to implement a Google reCAPTCHA (as the official Sprout's plugin isn't working).
This is the JS part:
grecaptcha.ready(function() {
    // Verify reCAPTCHA
    grecaptcha.execute(recaptchaSiteKey, { action: 'contactForm' }).then(function(token) {
        // Send the token to the server for verification
        var data = {
            token: token,
            action: 'contactForm',
            formData: $form.serialize()
        };
        data[csrfTokenName] = csrfTokenValue;
        fetch('/actions/utilities-module/captcha', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(data),
        })
        .then(data => {
            console.log(data);
            if (data === true) {
                console.log('success');
            } else {
                console.log('error');
            }
        });
    });
});

and the controller part:
public function actionIndex()
{
    // Check CSRF
    $this->requirePostRequest();

    // Call cURL to POST request
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
        'secret' => getenv('GOOGLE_RECAPTCHA_SECRET_KEY'),
        'response' => Craft::$app->getRequest()->getParam('token')
    )));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($response, true);

    // Verify the response 
    if ($response["success"] && $response["action"] == 'contactForm' && $response["score"] >= 0.9) {

        // Process the form
        $formData = Craft::$app->getRequest()->getParam('formData');
        $response = Craft::$app->runAction('sprout-forms/entries/save-entry', [
            'handle' => 'contact',
            'submission' => $formData
        ]);

        if (!$response['success']) {
            return $this->asJson(false);
        }

        return $this->asJson(true);

    } else {
        return $this->asJson(false);
    }
}

The issue here is that it's always failing. Looks like the Craft::$app->runAction() is missing something to process.
Any idea what's wrong?

**Tags:** plugin-sproutforms, controller, plugin-recaptcha, sprout


---

## 1 answers

### Answer by username_1 on 2023-11-05. Score: 2

Upgrading to the latest versions will likely resolve any issues with the default implementation. There was a bug in the timing of our javascript that was resolved in [3.13.20](https://github.com/barrelstrength/sprout-forms/blob/v3/CHANGELOG.md#31320---2023-03-17).


---

