Nonprofits love when volunteers sign up and engage with the organization. When using Volunteers for Salesforce this is accomplished through the sign up form that allows sign ups to flow from the online form directly into Salesforce. It is therefore important to protect the quality of the incoming data and make sure it is humans signing up and not bots.

This article will show how to enhance the Volunteers for Salesforce Signup page with CAPTCHA using very little customization.

Please keep in mind that the Volunteers for Salesforce Sign Up page is part of the managed package Volunteers for Salesforce so in order to add the CAPTCHA some coding will be needed.

Step 1 : Configure the reCAPTCHA

You can learn more about reCAPTCHA by reading through the Google developer documentation located here: https://developers.google.com/recaptcha/

For this example we used reCAPTCHA v2 with the checkbox. You will need a Google account to perform this step. Register for reCAPTCHA service by visiting Google’s reCAPTCHA page and click “Get reCAPTCHA”. Once you sign in with your Google account you can register your site by providing a descriptive label, and the domain name for your site. For this particular example the domain will be something like this:

partial18-mysalesforceinstance.cs90.force.com

 

SettingUpGoogleCaptchaDomain

Once you have set up reCAPTCHA you will be given a data site key and a secret key that will be used later.

CaptchaKeys

Step 2: Add Google as a Remote Site in Salesforce

In order for your form to be able to connect to Google and verify the CAPTCHA you will need to add google as a remote site. From the Administration Setup menu create a new Remote Site.

Remote Site

Step 3 : Extend the VOL_CTRL_VolunteersSignupFS controller

VOL_CTRL_VolunteersSignupFS is the controller that acts behind the scenes when a volunteer signs up using the VolunteersSignupFS page from Volunteers For Salesforce. This controller is extensible, meaning we can create a class that extends its functionality without having to change or edit the code in the managed package. We will create a new class to extend the VOL_CTRL_VolunteersSignupFS functionality and support the reCAPTCHA verification functionality.

public class DZK_VOL_CTRL_VolunteersSignUpFS extends GW_Volunteers.VOL_CTRL_VolunteersSignupFS {

 

Inside this new class we will add some methods that verify that the user has clicked the reCAPTCHA and confirmed they are not a robot.

public Boolean verified { get; private set; }
public String res {get; set;}
public String response  { 
   get {
     return ApexPages.currentPage().getParameters().get('g-recaptcha-response');
   }
}
public PageReference verify() {                
   String privateKey = 'YOUR_SECRET_KEY-FROM_STEP_1';
   String baseUrl = 'https://www.google.com/recaptcha/api/siteverify';
   HttpResponse r = makeRequest(baseUrl,
            'secret=' + privateKey + 
            '&remoteip='  + remoteHost + 
            '&response='  + response);
                
   //in unit tests fake the response
   if (test.isRunningTest()) {
      res = '{ "success": true, "challenge_ts": "2018-11-14T05:47:06Z", "hostname": "partial18-myinstance.cs90.force.com" }';
   } else {
      res = r.getBody();
   }        
   if ( res != null ) {
      JSONParser parser = JSON.createParser(res);
      while (parser.nextToken() != null) {
          if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) && 
              (parser.getText() == 'success')) {
              // Get the value.
	      parser.nextToken();
              this.verified = parser.getBooleanValue();
              break;
          }
      }            
   }                       
   if (this.verified) {
      // If they pass verification, save
      return Save();
   } else {
      // stay on page to re-try reCAPTCHA
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Sorry, but it looks like you are a robot.'));
      return null; 
   }
}
    
/* Private helper methods */
    
private static HttpResponse makeRequest(string url, string body)  {
        HttpResponse response = null;
        HttpRequest req = new HttpRequest();   
        req.setEndpoint(url);
        req.setMethod('POST');
        req.setBody (body);
        try {
            Http http = new Http();
            response = http.send(req);
            System.debug('reCAPTCHA response: ' + response);
            System.debug('reCAPTCHA body: ' + response.getBody());
        } catch(System.Exception e) {
            System.debug('ERROR: ' + e);
        }
        return response;
}   
        
private String remoteHost { 
   get { 
            String ret = '127.0.0.1';
            // also could use x-original-remote-host 
            Map<String, String> hdrs = ApexPages.currentPage().getHeaders();
            if (hdrs.get('x-original-remote-addr')!= null)
                ret =  hdrs.get('x-original-remote-addr');
            else if (hdrs.get('X-Salesforce-SIP')!= null)
                ret =  hdrs.get('X-Salesforce-SIP');
            return ret;
        }
}

Step 4 : Create your new sign up form with the reCAPTCHA

Even though the VolunteersSignupFS page is part of the Volunteers for Salesforce managed package, you can clone this page by copying and pasting the code into a new Visualforce page. In the new page change the controller and use the new controller created in Step 3. (Please read and keep the copyright information in the header of the file.)

<apex:page controller="DZK_VOL_CTRL_VolunteersSignUpFS" language="{!strLanguage}" showheader="false" sidebar="false" standardStylesheets="false" cache="false">

 

In this new Visualforce page add the following section, which shows the reCAPTCHA in the form right before the Submit button.

ScriptForPage

Change the following line to call the verify method instead of the Save method.

<apex:actionFunction name="DoSave" action="{!verify}" />

Voila, here is the new page with the reCAPTCHA displayed!

V4SWithCaptcha

Step 5 : Unit tests for new controller

In order to deploy the new Visualforce page and controller you will need unit tests. Create a new Apex class for unit tests as shown below.

@isTest
private class DZK_VOL_CTRL_VolunteersSignUpFS_TEST {

@isTest
private static void testCaptcha() {
   //instantiate the controller 
   DZK_VOL_CTRL_VolunteersSignUpFS ctrl = new DZK_VOL_CTRL_VolunteersSignUpFS(); 
   PageReference verifyCaptcha = ctrl.verify();
   System.assertEquals(null, verifyCaptcha);
}
}

Want to learn more? Contact DaizyLogik to learn more about how we can support you with specialized consulting and custom development and help you get the most out of Salesforce.