Integrating Google's reCaptcha v3 with Recurly's JavaSript API - javascript

I am using Recurly's JavaScript API to process subscriptions payments.
I want to implement Google's reCaptcha V3 API to the Recurly's self-hosted page.
<script src="https://js.recurly.com/v4/recurly.js"></script>
recurly.configure({
publicKey : 'xxx-xxx',
required : ['cvv', 'address1', 'city', 'state', 'country', 'postal_code'],
});
// When a customer hits their 'enter' key while in a field
recurly.on('field:submit', function (event) {
$('form').submit();
});
// On form submit, we stop submission to go get the token
$('form').on('submit', function (event) {
// Prevent the form from submitting while we retrieve the token from Recurly
event.preventDefault();
// Reset the errors display
$('#errors').text('');
$('input').removeClass('error');
// Disable the submit button
$('button').prop('disabled', true);
var form = this;
// Now we call recurly.token with the form. It goes to Recurly servers
// to tokenize the credit card information, then injects the token into the
// data-recurly="token" field above
recurly.token(form, function (err, token) {
// send any errors to the error function below
if (err) error(err);
// Otherwise we continue with the form submission
else form.submit();
});
});
Things is, Google's API implementation is something like this :
<input type="hidden" name="recaptcha_response" id="recaptchaResponse">
<button type="submit" id="btn-submit" class="g-recaptcha" data-sitekey="xxxxxxxxx" data-callback='onSubmit' data-action='submit'>Submit</button>
<script>
function onSubmit(token)
{
document.getElementById("recaptchaResponse").value = token;
document.getElementById("frm-subscribe").submit();
}
</script>
Both have their own version of onSubmit. How do I include Google's one into Recurly's ?

<input type="hidden" name="recaptcha_response" id="recaptchaResponse">
<button type="submit" id="btn-submit">Submit</button>
recurly.token(form, function (err, token) {
// send any errors to the error function below
if (err) error(err);
// Otherwise we continue with the form submission
else
{
grecaptcha.ready(function()
{
grecaptcha.execute('xxx-xxx-site-key', {action: 'submit'}).then(function(token)
{
document.getElementById("recaptchaResponse").value = token;
form.submit();
});
});
}
});

Related

check if email exists in mongodb while typing

this project uses js , mongoose , node.js
if use an email that already exists during registration to create an account, it will refresh the page clear all fields and shows a pop up message using ajax that says email exists. i dont want the fields to be cleared
im trying to fix this. the idea that i thought would be perfect is if i can use an event listener that will check the email against the database every time the user types something in the email input field. i already did this with js to make sure the passwords are identical before posting, all help and tips and remarks are welcome
here is the part of the code that checks if email exists
module.exports.signUp = async (req, res) => {
const { site_web, username, fonction, direction, email} = req.body
try {
if(email){
var check = await InscritModel.findOne({ email: email });
if(check){
res.render('inscription', { layout: 'inscription', email: true});
}
else{
// create user
}
}
}
}
UPDATE
im still stuck with this, i trying to use ajax to constantly check the email input against the database in real time, but i know im messing up a lot of things,
i created a post route in user-routes called router.post("/emailCheck", emailCheck); and in function-controller file i created this function
module.exports.emailCheck = async (email) => {
var check = await InscritModel.findOne({ email: email });
if(check){
return 1;
}
else{
return 0;}
}
this is the html input call
<input type="email" id="txtUserEmail" class="form-control" name="email" placeholder="Email.." required>
and this is the crazy ajax code
$(document).ready(function () {
$('#txtUserEmail').keyup(function () {
var email = $(this).val();
if (email.length >= 3) {
$.ajax({
url: '/emailCheck',
method: 'post',
data: { email: email },
success: function (data) {
var divElement = $('#divOutput');
if (data) {
divElement.text(' already in use');
divElement.css('color', 'red');
}
else {
divElement.text( ' available')
divElement.css('color', 'green');
}
},
error: function (err) {
alert(err);
}
});
}
});
});
its shows a one very long error message with so many things, it ends with this
Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 8)
hopefuly ill get there, any help is appreciated, the idea i have in mind is to make ajax call a function that takes an email in its parameters and checks it against the database and returns true or false.
well, i ended up finding the solution, ill share for future people.
the goal: stop the other fields from getting cleared when the email already exists in database
the problem: verifying the email happens after the form is submit, which means the page gets refreshed
solution idea: disable the submit button, use js to listen on the email input, and verify the input against the database while the user is typing.
app.js or routes.js whatever u named it
const InscritModel = require('../models/inscrit-model');
router.get('/usercheck', function(req, res) {
console.log(req.query);
// dont forget to import the user model and change InscritModel by whatever you used
InscritModel.findOne({email: req.query.email} , function(err, InscritModel){
if(err) {
console.log(err);
}
var message;
if(InscritModel) {
console.log(InscritModel)
message = "user exists";
console.log(message)
} else {
message= "user doesn't exist";
console.log(message)
}
res.json({message: message});
});
});
in html
<div id="divOutput"></div>
<input type="email" id="usercheck" required>
<input type="submit" id="btsubmit" disabled />
in JS
$('#usercheck').on('keyup', function () {
console.log("ok");
console.log($(this).val().toLowerCase());
$.get('/usercheck?email=' + $(this).val().toLowerCase(), function (response) {
$('#divOutput').text(response.message);
var bouton = document.getElementById('btsubmit');
bouton.disabled = true;
if ($('#divOutput').html() === "user exists") {
$('#divOutput').text('Email not available').css('color', 'red');
}
else {
$('#divOutput').text('Email available').css('color', 'green');
bouton.disabled = false;
}
})
});

reCaptcha V3 fails validation on first form submission only

I am trying to set up reCaptcha v3 and it sort of works. For some reason the first time I submit the form it fails but from the second submit onwards it is fine. I can't figure out why this is happening?
<script src="https://www.google.com/recaptcha/api.js?render=MY_SITE_KEY"></script>
<script>
grecaptcha.ready(function () {
grecaptcha.execute('MY_SITE_KEY', { action: 'contact' }).then(function (token) {
var recaptchaResponse = document.getElementById('captcha-response');
recaptchaResponse.value = token;
});
});
</script>
<input type="hidden" name="captcha-response" id="captcha-response">
PHP
$verifyResponse = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret='.$secretKey.'&response='.$_POST['captcha-response']);
$responseData = json_decode($verifyResponse);
if(!$responseData->score < 0.5) {
$message .= "Verification failed " . $responseData->score;
}
When I submit the form the first time, I get the validation error but my score is 0.9.
Why you have added "!" with "$responseData->score"? you may need to replace your condition with the following:
Replace this:
if(!$responseData->score < 0.5) {
$message .= "Verification failed " . $responseData->score;
}
With this one:
if($responseData->score < 0.5) {
$message .= "Verification failed " . $responseData->score;
}
P.S: Following code takes few seconds to properly load and get a "captcha-reponse" code, so you may need to disable all submit button and wait till you got a "captcha-reponse" to enable the submit button in form or you needs to implementent another way to delay the submit to execute only once you got a "captcha-response" code otherwise you will keep getting "missing-input-response" error message
<script src="https://www.google.com/recaptcha/api.js?render=MY_SITE_KEY"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('MY_SITE_KEY', {
action: 'contact'
}).then(function(token) {
var recaptchaResponse = document.getElementById('captcha-response');
recaptchaResponse.value = token;
});
});
</script>
You should re-generate the reCaptcha token after error form validation occured.
The token reCaptcha only valid for ONE TIME.
So, you have two options to fixes this issue.
1. Reload the page when error occured
This is the easiest way. You only need to reload the page whenever form validation error occured.
Of course, this will trigger the reCaptcha to generate new token.
2. Handle with AJAX (Non-reload page)
This is the best approach, since this will helps the user not losing the form data and continue to fill the form.
So, here's what you should do.
<!-- Put this hidden input inside of your form tag -->
<input name="_recaptcha" type="hidden">
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITEKEY_HERE"></script>
<script>
// This will generate reCaptcha token and set to input hidden
const generateRecaptcha = function() {
grecaptcha.execute(
"YOUR_SITEKEY_HERE", {
action: "YOUR_ACTION_NAME"
}).then(function(token) {
if (token) {
document.querySelector("input[name='_recaptcha']").value = token;
}
});
}
// Call it when page successfully loaded
grecaptcha.ready(function() {
generateRecaptcha();
});
// Do your AJAX code here
$.ajax({
url: "https://example.com",
success: function(response) {
console.log(response);
},
error: function(error) {
// Call again the generator token reCaptcha whenever error occured
generateRecaptcha();
}
</script>
Don't forget to put your Site key and your action name. Make sure the action name matches with your Backend action name.
Medium Article

JS form can't get it to submit

After validating my form with javascript I can not get it to submit to the server
myForm.addEventListener("submit", validation);
function validation(e) {
let data = {};
e.preventDefault();
errors.forEach(function(item) {
item.classList.add("cart__hide");
});
at the end of the validation I have the following code
if (!error) {
myForm.submit();
}
I also tried
if (error = false) {
myForm.submit();
}
if ((error == false)) {
myForm.submit();
}
when I console log error I am getting all false so the form should submit.
I am getting the following console log error
TypeError: myForm.submit is not a function
I did this same validation on an html page and it worked fine. Now I am trying to get it to work on a PHP page and it will not submit.
I am not sure why the myForm.submit() is causing the error.
Thanks
Jon
Remove e.preventDefault(); from your code and put it in your validation function like this:
if (error) {
e.preventDefault();
}
What you need to do is to only call Event#preventDefault when there is an error.
myForm.addEventListener("submit", validation);
function validation(e) {
var error = !form.checkValidity(); // replace this with the actual validation
if (error) e.preventDefault();
}
<form>
<input type="text">
<input type="submit" value="submit">
</form>

Customize Stripe error messages with JavaScript

I am using Stripe and "custom forms" from the API. The following code is throwing errors if something is wrong, in English, but I want to translate some of the error messages into Norwegian to make it more user friendly for my customers. For example "invalid_expiry_year" and "invalid_expiry_month" which is currently in English.
Is it possible to achieve and if so, how?
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('pk_test_2iA9ERjj5lVuUgvOS9W5fNtV');
$(function() {
var $form = $('#payment-form');
$form.submit(function(event) {
// Disable the submit button to prevent repeated clicks:
$form.find('.submit').prop('disabled', true);
// Request a token from Stripe:
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from being submitted:
return false;
});
});
function stripeResponseHandler(status, response) {
function stripeHandler( status, response ){
if ( response.error && response.error.type == 'card_error' ){
$( '.errors' ).text( errorMessages[ response.error.code ] );
}
else {
// do other stuff (and handle api/request errors)
}
}
// Grab the form:
var $form = $('#payment-form');
if (response.error) { // Problem
// Show the errors on the form:
$form.find('.payment-errors').text(response.error.message);
$form.find('.submit').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token ID into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken">').val(token));
// Submit the form:
$form.get(0).submit();
}
};
</script>
There is an option for you to set up the stripe form in a different language than English, but only for a few other languages Stripe supports. For a custom integration, you will have to pass locale: 'auto' when calling StripeCheckout.configure() so the language will be detected automatically. There’s more info in the docs.
However, since Norwegian isn't supported yet, what I am suggesting is mapping the response codes and providing your own translations for the errors.
var errorMessages = {
incorrect_number: "The card number is incorrect.",
....
};
You can find a complete list with all error codes here

Trying to pass <%> HTML Variable to Javascript - Node, Passport, and Stripe

A bit of a newbie here. I've been looking for an answer that works and found some similarities in a Jade problem but I'm not using Jade. I have passed an "user" attribute into an HTML view as so:
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profilePage/profilePage.html', {
user : req.user // get the user out of session and pass to template
});
});
Then, in my profile HTML, I can access my user property like so:
<%=user.local.firstname%>'s Profile
However, I want to allow Stripe to send the user's credit card info via the Stripetoken. I have managed to include a variable amount from a text field the user inputs. However, I want to append the user property so I can use it in my callback. Here is the javascript/jquery that's included in the profile html:
<!-- New section -->
<script type="text/javascript">
<!-- Fill in your publishable key -->
Stripe.setPublishableKey('pkkey');
var stripeResponseHandler = function(status, response) {
var $form = $('#contactForm');
var $amount = $('#amount').val();
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// token contains id, last4, and card type
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
$form.append($('<input type="hidden" name="amount" />').val($amount));
// and re-submit
$form.get(0).submit();
}
};
jQuery(function($) {
$('#contactForm').submit(function(e) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
</script>
As you can see, I have managed to append the $amount variable so I can access it in the callback:
module.exports = function(app, passport) {
app.post('/stripe', function(req,res) {
// =====STRIPETOKEN======
var transaction = req.body;
var stripeToken = transaction.stripeToken;
var donationAmount = transaction.amount;
stripe.customers.create({
source : stripeToken,
account_balance : 0
},function(err, customer) {
if (err) {
console.log(err);
} else {
console.log("Success!");
}});
// ====CREATE CHARGE======
var charge =
{
amount : donationAmount,
currency : 'USD',
card : stripeToken
};
stripe.charges.create(charge, function(err, charge) {
if(err)
console.log(err);
else
{
res.json(charge);
console.log('Successful charge sent to Stripe!');
console.log(charge);
};
});
// ====PROFILE PAGE REDIRECT=====
res.render('profilePage/profilePage.html', {
});
});
So here's my problem. I want to pass the user's information, kind of like I did the amount, into the post method so when it redirects on success, I can pass it back in the res.render function, as well as send it to Stripe for description purposes. The only thing I can think of is to put the user info in a hidden field in HTML and access it like that, but that sounds messy and not proper.
This is my first time posting here so I apologize if it was too lengthy or not specific enough. Thanks!
The answer was in the way I was declaring passport and stripe in my application. Make sure you declare passport after everything to make the user variable available to stripe and all views.

Categories

Resources