Possible to create Token with Stripe JS with no payment information - javascript

I have a client that wants to have a Stripe subscription that does not cost anything. Currently, their application is set up to take CC info because their older plan did require a monthly fee.
I want to know if it is possible to create a Stripe customer token via Stripe JS without taking any kind of CC info/bank account etc from the user?
I tried removing the CC fields with jQuery, but I keep getting a Stripe Invalid Request error because it cannot find the payment information.
So to summarize, when a user selects the 'free' plan from the dropdown, they should not see the CC fields and they should be able to progress through the sign up page without any Stripe validations while also creating their customer token.
Is this possible?
Relevant files
Hosts Controller #create
def create
#host = User.new(host_params)
if #host.valid?
customer = Stripe::Customer.create(
stripe_params.merge(email: host_params[:email], coupon: coupon)
)
#host.update(
stripe_customer_id: customer[:id],
subscription_plan: stripe_params[:plan]
)
sign_in(:user, #host)
redirect_to dashboard_path, notice: t('notices.hosts.created')
else
render :new
end
rescue Stripe::CardError, Stripe::InvalidRequestError => error
render :new, alert: error.message
end
Stripe JS code
$(document).on 'ready page:load', ->
$cardFields = $('#credit-card-fields')
$parentForm = $cardFields.parents('form')
$parentBtn = $('.js-payment-btn', $parentForm)
return unless $parentForm.length
$parentBtn.on 'click', (event) ->
event.preventDefault()
pub_key = $('meta[name=stripe-publishable-key]').attr('content')
$parentBtn.prop('disabled', true)
Stripe.setPublishableKey(pub_key)
Stripe.card.createToken $parentForm, (status, response) ->
if response.error
$parentForm.find('.payment-errors').text(response.error.message)
$parentBtn.prop('disabled', false)
else
token = response.id
S> $parentForm.append($('<input type="hidden" name="stripe[source]" />').val(token))
$parentForm.get(0).submit()
Stripe JS Form
<script type="text/javascript" src="https://js.stripe.com/v2/" data-turbolinks-track="true"></script>
<div class="clearfix" id="credit-card-fields">
<span class="payment-errors"></span>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon icon icon-credit-card"></span>
<input id="card-number" class="form-control input-cc" required placeholder="Card Number" type="text" size="16" maxlength=16 data-stripe="number" />
</div>
</div>
<div class="form-group side-by-side">
<div class="input-group">
<span class="input-group-addon icon icon-calendar"></span>
<input id="card-month" class="form-control input-exp" required placeholder="MM" type="text" size="2" maxlength="2" data-stripe="exp-month" />
<input id="card-year" class="form-control input-exp" required placeholder="YY" type="text" size="2" maxlength="2" data-stripe="exp-year" />
</div>
</div>
<div class="form-group side-by-side">
<div class="input-group">
<span class="input-group-addon icon icon-lock"></span>
<input id="card-cvc" class="form-control input-cvv" required placeholder="CVC" type="text" size="4" maxlength="4" data-stripe="cvc" />
</div>
</div>
</div>

It would not make sense to create a card token without any card details so this is not possible. As you mentioned, if you try to create a token without the required parameters such as the card number or the expiration date you get an invalid_request_error back.
If you don't want to require card details then you should just not create a token. When someone attempts to subscribe to a free plan, you would bypass the need to create a token and simply collect the rest of the information you want such as the customer's email address or name. Then server-side, you'd call the Create Customer API and pass the plan id in the plan parameter to subscribe them.
If the plan is free then there's no need to pass a token and you can simply ignore the source parameter completely.

Related

I have issues when I click button for contact form of html and JavaScript which API of Django rest in heroku it gives this errors: HTTP ERROR 405

method: is POST in HTML and in django is post:
error : This page isn’t working If the problem continues, contact the site owner. HTTP ERROR 405
HTML contact form code
<div class="col-lg-6">
<form action="" method="post" role="form" class="form-example">
<div class="form-row">
<div class="col-md-6 form-group">
<input type="text" name="name" class="form-control" id="names" placeholder="Your Name" data-rule="minlen:4" data-msg="Please enter at least 4 chars" required />
<div class="validate"></div>
</div>
<div class="col-md-6 form-group">
<input type="email" class="form-control" name="email" id="emails" placeholder="Your Email" data-rule="email" data-msg="Please enter a valid email" required />
<div class="validate"></div>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control" name="subject" id="subjects" placeholder="Subject" data-rule="minlen:4" data-msg="Please enter at least 8 chars of subject" required />
<div class="validate"></div>
</div>
<div class="form-group">
<textarea class="form-control" name="message" id= "messages" rows="5" data-rule="required" data-msg="Please write something for us" placeholder="Message" required ></textarea>
<div class="validate"></div>
</div>
Django view:
class ContactView(APIView):
def post(self, request):
serailizer_class = ContactSerializer(data=request.data)
if serailizer_class.is_valid():
contact = Contact(
name=serailizer_class.data.get('name'),
email=serailizer_class.data.get('email'),
subject=serailizer_class.data.get('subject'),
message=serailizer_class.data.get('message')
)
contact.save()
email_from = contact.email
names = contact.name
send_mail("new contact form submitted", names, email_from, ['reciever#gmail.com'], )
return Response({"success": "contact Sent"})
return Response({'success': "Failed"}, status=status.HTTP_400_BAD_REQUEST)
javascript file:
const add_contact =async()=>{
const names = document.getElementById('names').value
const emails = document.getElementById('emails').value
const subjects = document.getElementById('subjects').value
const messages = document.getElementById('messages').value
const response = await fetch('https://herokuapp_name.herokuapp.com/contact/',{
method:"POST",
body:JSON.stringify({
name:names,
email:emails,
subject:subjects,
message:messages
}),
headers:{
"Content-Type": "application/json"
}
})
const responseData = await response.json()
console.log(responseData)
if(response.ok){
location.href="../../index.html"
}else{
alert(responseData.error)
}
}
document.getElementById('submit').addEventListener('click',add_contact)
remember: if I test using postman it work well but if I am using front-end web it doesn't work
I think you're facing a CORS issue. You can make sure that this is a CORS-thing by checking you browser console and looking for CORS.
Solution is to disable CORS in your browser for chrome you can find useful stuff here:
Disable same origin policy in Chrome
Also there's a ton of plugins for this purpose, just google something like Firefox CORS extension.
But what is CORS?
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

JavaScript set a form fields initial value, to the same value of another field?

I am trying to handle some JavaScript work, which I don't have much experience with. I have a 2 part form where a user enters their personal info, and then company info. I am trying to set some of the company fields to what they already entered in their personal info.
I don't want the user to have to retype address, email, etc.
for example, I have...
<div class="form-group">
<label for="email">Email<span>*</span></label>
<input name="email" type="text" class="form-control required" id="email"placeholder="Email" value=".
{{email}}">
<span id="span_email" class="error-msg"></span>
And...
<div class="form-group">
<label for="comp_email">Company Email<span>*</span></label>
<input name="comp_email" type="text" class="form-control required" id="comp_email"placeholder="Email"
value="{{comp_email}}">
<span id="span_email" class="error-msg"></span>
How would I be able to set that second comp_email field to initially have the email info, so the user doesn't have to retype, unless they actually wanted to change the comp_email to another email address?
EDIT
It is all in one form, just separated by divs. Initially, when the page is loaded, the account section div is displayed, when the user hits next, it triggers the display of the business info.
<input type="button" onclick="nextFormPage(); window.scrollTo(0, 100)"
class="btn btn-danger btn-block" value="Next">
The nextFormPage() function just hides the first div and displays the second div.
You have tagged both javascript and jQuery so I'm not sure which you are using. But you can do this with a single line either way:
Javascript::
document.getElementById("comp_email").value = document.getElementById("email").value;
document.getElementById("email").value gets the value from the email input and we set the value of the document.getElementById("comp_email") by setting its value attribute:
jQuery:
$("#comp_email").val( $("#email").val() );
$("#email").val() get the value from the email input and $("#comp_email").val( ... ); sets the text passed in as the input value.
Javascript Working Example
function nextFormPage(){
document.getElementById("comp_email").value = document.getElementById("email").value;
}
<div class="form-group">
<label for="email">Email<span>*</span></label>
<input name="email" type="text" class="form-control required" id="email" placeholder="Email" value="">
<span id="span_email" class="error-msg"></span>
<div class="form-group">
<label for="comp_email">Company Email<span>*</span></label>
<input name="comp_email" type="text" class="form-control required" id="comp_email" placeholder="Email"
value="">
<span id="span_email" class="error-msg"></span>
<input type="button" onclick="nextFormPage(); window.scrollTo(0, 100)"
class="btn btn-danger btn-block" value="Next">
If your user is logged in, you should pass all of their information to the form, including their email. For example:
const logIn = () => {
... some code to get the user ...
... pass the user to the form, probably through an event listener...
let button = document.createElement("button")
button.textContent = "Edit"
button.addEventListener('click', () => {editYourStuff(user)}
}
const editYourStuff = user => {
... grab whatever your form is called ...
editForm.email.value = user.email
}
This should pre populate your form with the email

Cannot Modify The Value of HTML Elements From Node.js

I have an HTML form, which should be completed by the user. After completing the form, the introduced data is checked, in order to see whether the introduced username was introduced before or not. If the username is unique, then the input data is valid. If the username has already been used by someone else, I want to reload the sign up page, which is called signUp.html, but I also want to modify the values and placeholders of those fields contained by that HTML form. Excepting the Username and Password fields, I want every other field to contain the data, which was introduced by the user before. For sample, if the First Name field contained the value Toma, then I want, after reloading the page, the First Name field to have the value of Toma. On the other hand, I want to change the message of the placeholder of the Username field, which would be something like: Sorry, this username is invalid.... I tried to use the jsdom package, in order to acces the HTML file: signUp.html, which is to be found in public/views. The code of the HTML form is:
<form method="POST" action="signUp" style="margin-left: 5%; margin-right: 5%; margin-top: 5%" class="was-validated">
<div class="form-group">
<label style="color: #ffffff"> First Name </label>
<input type="text" name="firstName" class="form-control" placeholder="e.g.: Toma" required>
</div>
<div class="form-group">
<label style="color: #ffffff"> Second Name </label>
<input type="text" name="secondName" class="form-control" placeholder="e.g.: Alex" required>
</div>
<div class="form-group">
<label style="color: #ffffff"> Email </label>
<input type="email" name="email" class="form-control" placeholder="e.g.: somename#somedomain.com" required>
</div>
<div class="form-group">
<label style="color: #ffffff"> Username </label>
<input type="text" name="username" class="form-control" placeholder="e.g.: miauMiau23 (this is the name your friends will identify you with)" required>
</div>
<div class="form-group">
<label style="color: #ffffff"> Password </label>
<input type="password" name="password" class="form-control" placeholder="please, use a solid password, having a minimum of 6 characters, small and capital letters, as well as numbers and symbols!" required>
</div>
<button type="submit" class="btn btn-primary" style="width: 100%"> Submit </button>
</form>
The code found in server.js, which tried to achieve what I've described before:
app.post('/signUp', urlencodedParser, function(req, res){
console.log("sorry... this username is invalid!");
res.render('signUp');
var { document } = (new JSDOM('public/views/signUp.html')).window;
var firstNameField = document.getElementsByName('firstName');
var secondNameField = document.getElementsByName('secondName');
var emailField = document.getElementsByName('email');
var usernameField = document.getElementsByName('username');
var passwordField = document.getElementsByName('password');
console.log(firstNameField.placeholder);
firstNameField.value = req.body.firstName;
secondNameField.value = req.body.secondName;
emailField.value = req.body.email;
usernameField.value = "";
usernameField.placeholder = "'" + req.body.username + "' is an invalid username...";
passwordField.value = "";
}
After reloading, the page loses all of the introduced data.
The reason is not working is because res.render will render the page on the server and then send it to the client. What you're doing after that is simply loading the HTML again into the server's memory with JSDOM and modifying it, at the end of the request that is just thrown away and doesn't effect what has already been sent to the client by res.render.
The correct way to do this would be to use a templating language (there are many to choose from) with your express.js server to dynamically render the page and inject the values you want in the right place. You can then simply pass the variables to the res.render to be available when rendering your template:
app.post('/signUp', urlencodedParser, function(req, res) {
console.log("sorry... this username is invalid!");
res.render('signUp', {
firstName: req.body.firstName,
secondName: req.body.secondName,
email: req.body.email,
error: "'" + req.body.username + "' is an invalid username...",
});
});
For example, if you went with Pug.js as a templating engine your sign-up page could look something like this (I've not included all formatting which should go into CSS):
form(method='POST' action='/signUp')
div.form-group
label(for='firstName') First Name
input#firstName.form-control(type='text', name='firstName', value=firstName, required)
div.form-group
label(for='secondName') Second Name
input#secondName.form-control(type='text', name='secondName', value=secondName, required)
div.form-group
label(for='email') Email:
input#email.form-control(type='email', name='email', value=email, required)
div.form-group
label(for='username') Username
if error:
input#username.form-control(type='text', name='username', placeholder=error)
else:
input#username.form-control(type='text', name='username', placeholder='e.g.: miauMiau23 (this is the name your friends will identify you with')
div.form-group
label(for='password') Password:
input#passwordw.form-control(type='password' name='password')
button.btn.btn-primary(type='submit') Submit

how to use autocomplete in angularjs

I have an application with add friend feature, in that feature, user must fill their friend's username in the textbox. this is the html code:
<div content-for="title">
<span>Add Friend</span>
</div>
<form class="form-inline" role="form">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail2">User ID</label>
<input type="text" class="form-control" data-ng-model="add.email" id="exampleInputEmail2" placeholder="User ID">
</div>
<button type="submit" class="btn btn-default" data-ng-click="addfriends()">Add</button>
the interface will be like this
and this is the js code:
// addfriend
$scope.add = {};
$scope.addfriends = function(){
$scope.messages = {
email : $scope.add.email,
userid : $scope.datauser['data']['_id']
};
//event add friend
socket.emit('addfriend',$scope.messages,function(callback){
if(!callback['error']){
$scope.datauser['data']['penddingrequest'].push(callback['data']);
//push pendding request to localstorage user
localStorageService.remove('user');
localStorageService.add('user', $scope.datauser);
$scope.add['email'] = '';
alert('Successfully added friend');
}else{
var msg = callback['error'];
navigator.notification.alert(msg,'','Error Report','Ok');
}
});
};
I want to change this feature little bit, I want to make this textbox showing some suggestion based on the input, like if user input 'a', the textbox will show all user id that start with 'a'. something like twitter's searchbox or instagram searchbox. these user ids is from database.
example searchbox of web instagram
my question is how to change this textbox to be autocomplete but still work like before? thanks very much
There are many ways to do this.
First is this one: You basically create Angular directive for your input.
http://jsfiddle.net/sebmade/swfjT/
Another way to do is to attach onKeyUp event to your input:
<div class="form-group">
<label class="sr-only" for="exampleInputEmail2">User ID</label>
<input type="text" class="form-control" data-ng-model="add.email" id="exampleInputEmail2" placeholder="User ID" ng-keyup="searchFriends()">
<div ng-model="searchFriendsResult" />
</div>
And then, in your controller, you create a searchFriends function that will:
Search your database
Display the result in the view.
Something like this (not a complete code):
$scope.searchFriends = function(value){
// Make Ajax call
var userRes = $resource('/user/:username', {username: '#username'});
userRes.get({username:value})
.$promise.then(function(users) {
$scope.searchFriendsResult = users;
});
};
Use Bootstrap Typeahead
<input type="text" ng-model="asyncSelected"
placeholder="Locations loaded via $http"
uib-typeahead="address for address in getLocation($viewValue)"
typeahead-loading="loadingLocations"
typeahead-no-results="noResults"
class="form-control"/>

Meteor - Form not being inserted into collection when submitted

I am attempting to store information that is put into this form with meteor:
<form class="form-group" id="lost_form">
<label for="item_name">Type</label>
<input id="item_name" class="form-control" type="text" placeholder="What is the item? Ex: Water bottle" required/>
<label for="item_brand">Brand</label>
<input id="item_brand" class="form-control" type="text" placeholder="What brand is the item? Ex: Nalgene" required/>
<label for="item_desc">Description</label>
<input id="item_desc" class="form-control" type="text" placeholder="Describe the item. Ex: Green, name on bottom" required/>
<label for="item_loc">Location</label>
<input id="item_loc" class="form-control" type="text" placeholder="Where did you have it last? Ex: Main common room"/>
<label for="item_date">Date Missing</label>
<input id="item_date" class="form-control" type="date"/>
<br>
<input id="submit_lost_form" class="btn btn-primary btn-block" type="submit" value="Submit" />
</form>
The JS I am using to put it into a collection is below:
LostItems = new Meteor.Collection('lostitems');
Meteor.methods({
'insertItem': function(iname, ibrand, idesc, iloc, idate){
LostItems.insert({
user: Meteor.user(),
name: iname,
brand: ibrand,
description: idesc,
location: iloc,
date: idate
})
}
});
if (Meteor.isClient) {
Template.lost_form.events({
'submit form': function (event) {
event.preventDefault();
var itemName = event.target.item_name.value;
var itemBrand = event.target.item_brand.value;
var itemDesc = event.target.item_desc.value;
var itemLoc = event.target.item_loc.value;
var itemDate = event.target.item_date.value;
Meteor.call('insertItem', itemName, itemBrand, itemDesc, itemLoc, itemDate);
}
});
}
But whenever I submit the form, nothing happens. There are no errors in the developer console, or on the meteor console, and when I do LostItems.find().fetch() there is nothing there.
I am new to meteor so this is probably a really dumb question, but I appreciate any help!
You might need to use Meteor.userId() instead of Meteor.user() in your call to insert(). Without the autopublish package, the doc returned by Meteor.user() can be different on the client than it is on the server (for security reasons). That would mean that the client-side insert into your mini-mongodb and the server-side insert into the real mongodb could conflict with each other. I would expect the client-side insert to be ignored after the result of the server-side insert propagates back to the client. I'm not sure why it isn't being replaced by the server-side insert though. What does LostItems.find().fetch() return when you run it on the server (e.g. in meteor shell)?
I fixed the issue by adding insecure, yogiben:autoform-tags and autopublish to my package list. I think autopublish is the one that made the difference. I am sure there is a better way to do this and that this probably has some security flaws to it, but this is not a big project and it isn't storing sensitive data, so this will work for now.

Categories

Resources