To add google recatcha v3 in a check out page
we need to create a extension and suite script and suite let file
NOTE: SITE KEY and SECRET KEY will differ with domain
java script:
mountToApp: function mountToApp (container)
{
_.extend(WizardView.prototype,{
//adding a new model for view//
initialize: _.wrap(WizardView.prototype.initialize, function initialize(fn) {
fn.apply(this, _.toArray(arguments).slice(1));
this.recaptchamodel = new JJRecaptchaV3RecaptchaV3Model();
}),
//extend a function to ad recaptcha verification feature//
submit: function(e) {
try {
let self = this;
e.preventDefault();
let promise = jQuery.Deferred();
let siteKey = SC.CONFIGURATION.ReCaptcha.SiteKey;
let recaptchaOptionEnable = SC.CONFIGURATION.ReCaptcha.EnableButton;
if (recaptchaOptionEnable == true && self.wizard.currentStep === "review") {
try {
grecaptcha.ready( function() {
grecaptcha.execute(siteKey, {action: 'submit'}).then( function(token) {
var response = jQuery('.g-recaptcha-response').val();
self.recaptchamodel.fetch({
data:{
token:token,
responses: response
}
})
.done(function (data) {
console.log('result',data.body);
data = JSON.parse(data.body)
if (data.score > 0.5) {
self.wizard.getCurrentStep().submit(e);
} else {
var global_view_message = new GlobalViewsMessageView({
message:'Recaptcha verification failed!!',
type: 'error',
closable: true,
});
jQuery(container).show();
var msgContainerParent = jQuery('.recaptcha-error-message');
msgContainerParent.html(global_view_message.render().$el.html());
return promise.resolve();
}
})
});
});
} catch (e) {
console.log('err@recaptchfunction', e)
}
} else {
self.wizard.getCurrentStep().submit(e);
}
} catch (e) {
console.log('err@submit', e)
}
},
})
//loading a script to header tag//
_.extend(OrderWizardStep.prototype,{
template:jj_recaptchav3_recaptchav3_tpl,
loadScript: function loadScript(url, callback ) {
try {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = function () {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
} catch (e) {
console.log('err@loadScript', e)
}
},
getContext: _.wrap(OrderWizardStep.prototype.getContext, function (fn) {
let originalRet = fn.apply(this, _.toArray(arguments).slice(1));
try {
let self = this;
let ReCaptchaSiteKey = SC.CONFIGURATION.ReCaptcha.SiteKey;
originalRet.ReCaptchaSiteKey = ReCaptchaSiteKey;
let recaptchaOptionEnable = SC.CONFIGURATION.ReCaptcha.EnableButton;
if (recaptchaOptionEnable == true && self.step_url === "review" ) {
loadScript("https://www.google.com/recaptcha/api.js?render="+ ReCaptchaSiteKey ),
function callback(e) {
console.log('RENDERED',e);
}
}
} catch (e) {
console.log('err@getContext', e)
}
return originalRet;
})
});
}
Model file:
return Backbone.Model.extend({
//@property {String} urlRoot
urlRoot: Utils.getAbsoluteUrl(
getExtensionAssetsPath(
"services/RecaptchaV3.Service.ss"
)
)
});
});
suite script files:
JS file:
'use strict';
return SCModel .extend({
name: 'JJ.RecaptchaV3.RecaptchaV3',
Recaptcha : function (data) {
try {
var url = nlapiResolveURL("SUITELET", "customscriptjj_captcha_validation_2",
"customdeploy3", true);
var response = nlapiRequestURL(url, data, null, "POST");
return response;
} catch (e) {
console.error('err@recaptchfunctionsuitescript', e)
}
}
})
});
service controler:
get: function get() {
try {
var token = this.request.getParameter('token');
var responce = this.request.getParameter('responses');
return JJ_RecaptchaV3_RecaptchaV3.Recaptcha({token:token, responce:responce})
} catch (e) {
console.error('err@getfunction', e)
}
},
post: function post() {
// not implemented
},
put: function put() {
// not implemented
},
delete: function() {
// not implemented
}
tpl file
<div class="order-wizard-step-button-container">
{{#if showContinueButton}}
<button id="placeorder" class="order-wizard-step-button-continue " data-sitekey= {{ReCaptchaSiteKey}} data-action="submit-step">
{{continueButtonLabel}}
</button>
{{/if}}
<button class="order-wizard-step-button-back" {{#unless showBackButton}}style="display:none;"{{/unless}} data-action="previous-step">
{{translate 'Back'}}
</button>
</div>
</div>
suite let file
/**
* @NApiVersion 2.0
* @NScriptType Suitelet
*/
define(['N/https'], function (https) {
function onRequest(context) {
log.debug('context', context);
var token = context.request.parameters.responce;
log.debug('token', token);
var secret = "6LcWTA0pAAAAAAkfwc9w1wfjKo7k7HDITY3aw0-N";
var url = 'https://www.google.com/recaptcha/api/siteverify';
var headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var body = 'secret=' + secret + '&response=' + token;
log.debug("body",body);
var captchaResponse = https.post({
url: url,
headers: headers,
body: body
});
log.debug("captchaResponse",captchaResponse)
var responseBody = captchaResponse.body;
log.debug('reCAPTCHA response', responseBody);
context.response.setHeader({
name: 'Content-Type',
value: 'application/json'
});
context.response.write(responseBody);
}
return {
onRequest: onRequest
};
});
configuration file
{
"type": "object",
"subtab":
{
"id": "ReCaptcha_subtab",
"title": "ReCaptcha Subtab",
"description": "ReCaptcha Subtab update",
"group": "extensions"
},
"properties": {
"ReCaptcha.SiteKey": {
"group": "extensions",
"subtab": "ReCaptcha_subtab",
"type": "string",
"title": "ReCaptcha SiteKey",
"description": "add ReCaptcha Site Key",
"default": ""
},
"ReCaptcha.EnableButton": {
"group": "extensions",
"subtab": "ReCaptcha_subtab",
"type": "boolean",
"title": "ReCaptcha EnableButton",
"description": "ReCaptcha Enable Button",
"default": ""
},
"ReCaptcha.BackendLink": {
"group": "extensions",
"subtab": "ReCaptcha_subtab",
"type": "string",
"title": "Backend Link",
"description": "Backend Link",
"default": ""
}
}
}