diff --git a/README.md b/README.md index 8bdf84e..1afccaf 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,54 @@ Note: The keys of the `data` object should match with the fields that are set us Article: https://devapt.com/formspree-alternative-formeasy +## Captcha validation + +FormEasy supports multiple captcha providers to allow you to prevent unverified submissions by robots. Each provider is unique and requires a unique configuration. Please refer to the documentation below to enable a specific captcha provider. + +### Google reCAPTCHA V2 + +1. Register a site and get your secret key, and site key: [https://www.google.com/recaptcha/admin/create](https://www.google.com/recaptcha/admin/create) + +2. In your apps script file, inside function `doPost`, add the following configuration: + +```js +function doPost(req) { + // ... + FormEasy.setRecaptcha('YOUR_SECRET_KEY'); // To validate reCAPTCHA + // ... + return FormEasy.action(req); // Mandatory to return action method +} +``` + +3. On your website, add the reCAPTCHA library at the end of the `` tag: + +```html + + + + + +``` + +4. Add reCAPTCHA input into your form: + +```html +
+``` + +5. You should see `I am not a robot` box on your site. If you don't, please refer to [reCAPTCHA Docs](https://developers.google.com/recaptcha/docs/display) for debugging. + +6. Inside your `fetch()` method, add a reCAPTCHA response from the input: + +```js +const data = { + // ... + 'g-recaptcha-response': document.getElementById('g-recaptcha-response').value, +}; + +// ... +``` + ## Video instructions To see all the above instructions lively, check this demo video below. diff --git a/src/Code.js b/src/Code.js index 229285a..bd47332 100644 --- a/src/Code.js +++ b/src/Code.js @@ -3,6 +3,7 @@ let emailSubject = 'New submission using FormEasy'; let formHeading = 'Form submission - FormEasy'; let email = ''; let fields = []; +let captcha = null; /** * @param {String} name Name of the sheet to log the data @@ -69,6 +70,15 @@ function setFields(...fieldsArr) { } } +/** + * Google reCAPTCHA V2 implementation + * + * @param {String} secretKey Private key of reCAPTCHA site + */ +function setRecaptcha(secretKey) { + captcha = { type: 'recaptcha_v2', data: { secretKey } }; +} + /** * @param {Object} req POST request object * @return {Object} response to the POST request @@ -89,6 +99,44 @@ function action(req) { return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); } + if (captcha) { + switch (captcha.type) { + case 'recaptcha_v2': + const siteKey = jsonData['g-recaptcha-response']; + + if (!siteKey) { + response = { + status: 'error', + message: 'reCAPTCHA verification under key \'g-recaptcha-response\' is required.', + }; + return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); + } + + const captchaResponse = UrlFetchApp.fetch('https://www.google.com/recaptcha/api/siteverify', { + 'method': 'post', + 'payload': { + 'response': siteKey, + 'secret': captcha.data.secretKey + } + }); + + const captchaJson = JSON.parse(captchaResponse.getContentText()); + + if (!captchaJson.success) { + response = { + status: 'error', + message: 'Please tick the box to verify you are not a robot.', + }; + + return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); + } + + break; + default: + // Captcha not enabled + } + } + let logSheet; const allSheets = SpreadsheetApp.getActiveSpreadsheet() @@ -155,4 +203,4 @@ function action(req) { }; return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); -} +} \ No newline at end of file