Submitting Braintree form after getting payment nonce using hosted fields - javascript

I am trying to customize the layout of my Braintree payment form using hosted fields.
I had been using the JS v2 SDK but was having other issues: Braintree - Hosted Fields - Uncaught TypeError: FormNapper requires an HTMLFormElement element or the id string of one
I've tried changing to the v3 SDK.
Here is the stripped down version of my payment form and the braintree.js file that I am using with it:
$.ajax({
url:'web/token.php',
type:'get',
dataType:'json',
success:function(token){
var payment_form = document.querySelector('#payment_form');
var submit_button = document.querySelector('#payment_button');
braintree.client.create({
authorization: token
}, function(err, clientInstance) {
if (err) {
console.error(err);
return;
}
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {'font-size': '14px'},
'input.invalid': {'color': 'red'},
'input.valid': {'color': 'green'}
},
fields: {
number: {selector: '#card-number',placeholder: '4111 1111 1111 1111'},
cvv: {selector: '#cvv',placeholder: '123'},
expirationDate: {selector: '#expiration-date',placeholder: 'MM/YY'}
}
}, function(err, hostedFieldsInstance) {
if (err) {
console.error(err);
return;
}
submit_button.removeAttribute('disabled');
payment_form.addEventListener('submit', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (tokenizeErr, payload) {
if (tokenizeErr) {
console.error(tokenizeErr);
return;
}
console.log('Got a nonce: ' + payload.nonce);
$('#payment-method-nonce').val(payload.nonce);
// payment_form.submit();
// $('#payment_form').submit();
document.getElementById('payment_form').submit();
});
});
});
});
}
});
<form action="process_order.php" method="POST" class="form" id="payment_form">
<div id="payment_container">
<div class="form-group">
<label for="card-number">Card Number</label>
<div id="card-number" name="card-number"></div>
</div>
<div class="form-group">
<label for="cvv">CVV</label>
<div id="cvv" name="cvv"></div>
</div>
<div class="form-group">
<label for="expiration-date">Expiration Date</label>
<div id="expiration-date" name="expiration-date"></div>
</div>
<input type="hidden" id="payment-method-nonce" name="payment-method-nonce">
<input type="submit" class="btn btn-default mx-auto" value="Complete Order ยป" id="payment_button">
</div>
</form>
<script src="https://js.braintreegateway.com/web/3.50.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.50.0/js/hosted-fields.min.js"></script>
<script src="web/braintree.js"></script>
At this point I can get the nonce and it is added to the value of the hidden input but the form won't submit.
When I use the variable name or use document.getElementById() I get TypeError: document.getElementById(...).submit is not a function but when I do it the jQuery way ($) nothing happens.

Related

Unable to use variable containing string in place of hardcoded string

I am setting up Stripe on my web app. Stripe seems to work fine when I hardcode a string such as 'test#test.com' into the email parameter. When I try to use the value from the input box however, the code does not execute properly. I do not get an error, the code just simply does not execute further. Here is my code:
form.addEventListener('submit', function (event) {
var user_email = document.getElementById('example1-email').value;
document.getElementById('output').innerHTML = user_email;
event.preventDefault();
stripe.createPaymentMethod({
type: 'card',
card: cardElement,
billing_details: {
email: user_email
},
}).then(stripePaymentMethodHandler);
});
function stripePaymentMethodHandler(result, email) {
if (result.error) {
} else {
// Otherwise send paymentMethod.id to your server
fetch('/checkout_stripe', {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: user_email,
payment_method: result.paymentMethod.id
}),
}).then(function (result) {
return result.json();
}).then(function (customer) {
// The customer has been created
}).then(redirectfunc);
}
HTML:
<form id="subscription-form">
<div class="cell example example1" id="example-1" style="padding-left: 25%;padding-right: 25%;padding-top: 5%">
<br>
<fieldset>
<div class="row">
<label for="example1-name" data-tid="elements_examples.form.name_label">Name</label>
<input id="example1-name" data-tid="elements_examples.form.name_placeholder" type="text" placeholder="Jane Doe" required
autocomplete="name">
</div>
<div class="row">
<label for="example1-email" data-tid="elements_examples.form.email_label">Email</label>
<input id="example1-email" data-tid="elements_examples.form.email_placeholder" type="email" placeholder="janedoe#gmail.com"
required autocomplete="email">
</div>
<div class="row">
<label for="example1-phone" data-tid="elements_examples.form.phone_label">Phone</label>
<input id="example1-phone" data-tid="elements_examples.form.phone_placeholder" type="tel" placeholder="(941) 555-0123" required
autocomplete="tel">
</div>
</fieldset>
<fieldset>
<div class="row">
<div id="example1-card"></div>
</div>
<form id="subscription-form">
<div id="card-element" class="MyCardElement">
<!-- Elements will create input elements here -->
</div>
<!-- We'll put the error messages in this element -->
<div id="card-errors" role="alert"></div>
</fieldset>
<button type="submit" style="background-color: #27eb15">Subscribe</button>
</form>
This is just the stock code from Stripe, with me pulling in the string from the input box and trying to put it into the email param. Bizarrely, only a hardcoded string such as test#test.com allows the process to complete, but not just using the var user_email - despite that just being a string that contains the same string as the hardcoded.
I have tested whether or not I am actually pulling anything in when I use the .value, and I am. I have also tested the datatype of user_email, and it is indeed a string.
How can I get this to execute properly using the data pulled in from the user input boxes?

Node.js password reset

I have been working on password reset in Node.js and Express.js
So far, my code is working for emailing to the user for changing their password. Also, user can change their password and receives an email after changing the password.
Now, the problem is, I cannot show success message after submitting the password. After pressing the submit button, it redirect to reset.ejs page.
Below is my code,
reset.ejs
<html>
<body style="margin-left:0px;">
<div class="custom-header">
<div class="custom-header-left">
</div>
<div class="custom-header-button">
</div>
<div class="custom-header-right">
<a class="navbar-brand">
<img alt="AGD" src="agdlogo.png" style="width:70%; margin-top:-22%;">
</a>
<a class="navbar-brand" href="/"> XXX </a>
<a class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
</div>
</div>
<!-- Top Bar-->
<div id="fullpage">
<div class="">
<div class="col-md-12 custom-margin-top">
<div class="panel panel-primary text-left">
<div class="panel-heading">Reset your Password</div>
<div class="panel-body">
<div class="col-md-10 ">
<form id="resetpass" role="form" class="form">
<div>
<div class="form-group">
<label for="InputEmail">New Password</label>
<input type="password" class="form-control" id="password" class="password" name="password" placeholder="Enter Email" required>
<label for="InputEmail">Confirm Password</label>
<input type="password" class="form-control" id="repass" class="repass" name="repass" placeholder="Enter Email" required>
<!-- <input type="hidden" name="token" id="token">-->
<button type="submit">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
var params = location.href;
var paramsplit = params.split('/');
//console.log(paramsplit);
$("#resetpass").submit(function (e) {
var resetData = {
password: $("#password").val(),
repass: $("#repass").val(),
token: paramsplit[4]
}
console.log(resetData);
// console.log(resetData);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: '/reset/:token',
data: JSON.stringify(resetData),
success: function (data) {
//console.log(data); // show response from the php script.
}
});
// e.preventDefault(); // avoid to execute the actual submit of the form.
});
</script>
<style CSS>
#import url("https://bootswatch.com/flatly/bootstrap.min.css");
</style>
</html>
I have a mail.controller.js file for controlling the view and model
exports.resetpassword = function(req, res) {
var data = req.body;
async.waterfall([
function(done) {
User.findOne({
resetPasswordToken: req.body.token,
resetPasswordExpires: {
$gt: Date.now()
}
}, function(err, user) {
if (!user) {
res.render('tinypage/regnotify', {
title: "Something is wrong",
alerttype: "alert-danger",
message: "Something wrong with your password change."
});
} else {
user.password = req.body.password;
user.resetPasswordToken = '';
user.resetPasswordExpires = '';
user.save(function(err, user) {
done(err, user);
});
}
});
},
function(user, done) {
var smtpTransport = nodemailer.createTransport('SMTP', {
service: 'Mailgun',
auth: {
user: 'sdfa',
pass: 'afdafsa'
}
});
var mailOptions = {
to: user.email,
from: 'agdtrack#s.com',
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
'This is a confirmation that the password for your account ' + req.body.token + ' has just been changed.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
if (err) {
res.render('tinypage/regnotify', {
title: "Wrong",
alerttype: "alert-danger",
message: "Something wrong"
});
} else {
return res.render('tinypage/regnotify', {
title: "Success",
alerttype: "alert-success",
message: "Success! Your password has been changed."
});
done(err);
}
});
}
], function(err) {
res.redirect('/');
});
};
exports.renderresetpage = function(req, res) {
res.render('reset');
};
And my mail.route.js is :
app.route('/reset/:token').get(mail.renderresetpage);
app.route('/reset/:token').post(mail.resetpassword);
All are working fine. Only does not show the success message after pressing submit button.
Your contribution would be a great help.
Submitting a from will navigate to the form's action. You can add an 'onclick' to the button instead to keep you in the same page, and send the ajax request from it. So you can be able to handle the ajax success.

Getting XMLHttpRequest erros on ajax Post

I have a modal in which there's a form that I want users to be able to submit an email with. I set up the ajax post like I usually would, however, the post keeps failing. When it does, I get the following two errors in the console.
Setting XMLHttpRequest.withCredentials for synchronous requests is deprecated
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
Interestingly, the email sometimes sends regardless of the errors, but sometimes it doesn't either.
Here is my Html:
<form class="cmxform" id="contactForm" >
<div class="row">
<div class="col-xs-6">
<label class="col-md-12 control-label" style="text-align: left;" >Name</label>
<div class="col-md-12">
<input required class="form-control" id="FromName" name="FromName" style="margin-bottom: 10px;" type="text" value=""/>
</div>
</div>
<div class="col-xs-6">
<label class="col-md-12 control-label" style="text-align: left;" >Email</label>
<div class="col-md-12">
<input required class="form-control" style="margin-bottom: 10px;" id="FromEmail" name="FromEmail" type="text" value=""/>
</div>
</div>
</div>
<label class="col-md-12 control-label" >Message</label>
<div class="col-md-12">
<textarea required class="form-control contact-message" cols="20" id="Message" name="Message" rows="2"></textarea>
</div>
<div class="col-md-12">
<input type="submit" class="btn btn-info" value="Submit" />
</div>
</form>
And my JS:
function sendMessage(messageData) {
$.ajax({
async: true,
url: '/api/SendMessageApi',
type: 'POST',
data: messageData,
success: function () {
},
error: function (ex) {
alert('there was an error');
}
});
}
$("#contactForm").submit(function () {
var name = $('#FromName').val();
var email = $('#FromEmail').val();
var message = $('#Message').val();
var messageData = { Name: name, Email: email, Message: message };
sendMessage(messageData);
});
Any help would be much appreciated!
To submit the form after ajax success, you can use:
function sendMessage(messageData) {
$.ajax({
context: this, // set context to the form
async: true,
url: '/api/SendMessageApi',
type: 'POST',
data: messageData,
success: function () {
this.submit(); // submit form on success
},
error: function (ex) {
alert('there was an error');
}
});
}
$("#contactForm").submit(function (e) {
e.preventDefault();
var name = $('#FromName').val();
var email = $('#FromEmail').val();
var message = $('#Message').val();
var messageData = { Name: name, Email: email, Message: message };
sendMessage.call(this, messageData); // set context to the form
});

angular payments returns invalid card with test data

I'm trying to congifure stripe in angular js using the angular-payments app found here
https://github.com/laurihy/angular-payments
the problem is that it seems to be returning invalid_card errors even with the test data.
Here is the error:
POST https://api.stripe.com/v1/tokens 402 (Payment Required)
Stripe.isDoubleLoaded.c(index):3 Stripe.isDoubleLoaded.e(index):3 Stripe.isDoubleLoaded.a(index):3 Stripe.isDoubleLoaded.Stripe.xhr(index):2 Stripe.a._rawRequest(index):2 Stripe.a.request(index):2 Stripe.token.a.create(index):2 Stripe.card.b.createToken(index):2 Stripe.a._channelListener(index):2 Stripe.isDoubleLoaded.H.Socket.t.concat.incoming(index):2
I'm setting my publishable key and including Stripe.js without a problem, and I know that the call is completed, as I'm picking up the error in the ResponsHandler
any thoughts what may be causing this?
here is the code:
form
<form name="myform" id="signup-form" stripe-handler="saveCustomer">
<div class="form-group">
<label for="card_number">Card Number</label>
<input type="text" class="form-control" size="20" ng-model="number" payments-validate="card" payments-format="card" payments-type-model="type" ng-class="myform.number.$card.type"/>
</div>
<div class="form-row">
<label for="CVC"> CVC</label>
<input type="text" class="form-control" size="4" ng-model="cvc" payments-validate="cvc" payments-format="cvc" payments-type-model="type"/>
</div>
<div class="form-row">
<label for="expiry"> Expiry</label>
<input type="text" class="form-control" size="2" ng-model="expiry" payments-validate="expiry" payments-format="expiry" />
</div>
<div class="text-center">
<span class="glyphicon glyphicon-heart"></span>
<h3>Thanks For Your Money!</h3>
<button type="submit" class="btn">Submit</button>
</div>
here is the contoller function:
// function to process the form
$scope.saveCustomer = function(status, response) {
if (response.error) {
// Show the errors on the form
console.log(response);
console.log(response.error);
} else {
// response contains id and card, which contains additional card details
var token = response.id;
console.log(token);
formData.token = token;
}
}
and my index.html header includes...
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
// This identifies your website in the createToken call below
Stripe.setPublishableKey('my-key-here');
// ...
</script>
The wierd thing is that it was working with stripe-angluar which is another repo for processing stripe - any ideas what am i doing wrong?
You might be creating the token incorrectly. I was having the same problem. What worked for me was setting the card like this:
Stripe.card.createToken({
"number": '4242424242424242',
"exp_month": 12,
"exp_year": 2016,
"cvc": '123'
}, function(status, response) {
stripeResponseHandler(status, response);
});
Instead of this (notice how the card object is created twice - thus the "Stripe.isDoubleLoaded" error, I believe ):
Stripe.card.createToken({
card: {
"number": '4242424242424242',
"exp_month": 12,
"exp_year": 2016,
"cvc": '123'
}
}, function(status, response) {
stripeResponseHandler
});

How do you edit and add new fields to the Current User in Meteor?

In Meteor the current user simply has a "name" field. I want to add a first_name and last_name under profile.
My user_edit.html form:
<template name="userEdit">
<div id="login-wrapper">
<form id="login-form" action="action" class="form login-form">
<div class="control-group">
<div class="controls">
<input name="first_name" type="text" value="" placeholder="First Name"/>
</div>
</div>
<div class="control-group">
<div class="controls">
<input name="last_name" type="text" value="" placeholder="Last Name"/>
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="submit" value="Submit" id="submit-website-button" class="btn btn-primary"/>
</div>
</div>
</form>
</div>
</template>
I have a form for editing the current user:
I'm not too sure how to update the current user in user_edit.js and add additional fields for first and last name. The code below doesn't work.
Template.userEdit.events({
'submit form': function(e) {
e.preventDefault();
var currentUserId = this._id;
var userProperties = {
first_name: $(e.target).find('[name=first_name]').val(),
last_name: $(e.target).find('[name=last_name]').val()
}
User.update(currentUserId, {$set: userProperties}, function(error) {
if (error) {
// display the error to the user
alert(error.reason);
} else {
Router.go('userPage', {_id: currentUserId});
}
});
}
});
EDIT
Here is the working version of my JS file after applying the answer:
Template.userEdit.events({
'submit form': function(e) {
e.preventDefault();
Meteor.users.update( Meteor.userId(),
{
$set: {
'profile.first_name': $(e.target).find('[name=first_name]').val(),
'profile.last_name': $(e.target).find('[name=last_name]').val(),
'profile.cell_phone': $(e.target).find('[name=cell_phone]').val(),
'profile.email': $(e.target).find('[name=email]').val(),
'profile.business_name': $(e.target).find('[name=business_name]').val(),
'profile.website': $(e.target).find('[name=website]').val()
}
},
function(error) {
if (error) {
// display the error to the user
alert(error.reason);
} else {
Router.go('userPage', {_id: Meteor.userId() });
}
}
);
}
});
A couple of things. I haven't used the past couple of updates of Meteor so maybe 'User' has been added as a cursor to update the current user but from my experience this is how you would update the current user:
Meteor.users.update( Meteor.userId(), { $set: { 'profile.first_name': "example" } } );
Also note how I had to specify 'profile.first_name', in your snippet you would be trying to set first_name and last_name in the base of the user object when users are only allowed to edit the profile section client side. Lastly I'm not sure what 'this' is in the context of your Template so I would set currentUserId = Meteor.userId(), a convenient way to get the current user's id.

Categories

Resources