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

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.

Related

Meteor change database at run time

I have three database i.e, main_db it is default load database. I want load database after login.
Database are:-
main_db
->user_collection
psm_2017_db
->abc_collection
->xyz_collection
psm_2018_db
->abc_collection
->xyz_collection
Here is my project structure
here is my login script.
client
|->login
|->login.js
Template.login.rendered = function(){
SessionStore.set("login_user",false);
};
Template.login.events({
'submit #formLogin': function (event, target){
event.preventDefault();
var email = target.find('#loginEmail').value;
var password = target.find('#loginPassword').value;
// console.log(email +" "+password);
Meteor.loginWithPassword(email, password, function(err){
if(err){
console.log(err);
alert("Invalid Login!");
}
else {
SessionStore.set("login_user",true);
console.log('successfully')
Router.go("/dashboard")
}
});
}
});
Template.layout.helpers({
"isLoggedin": function () {
return SessionStore.get("login_user");
}
});
here is my load collection file
lib
|->collection.js
abcCollection=new Mongo.Collection("abc_collection");
xyzCollection=new Mongo.Collection("xyz_collection");
You can connect to multiple dbs using the below approach.
var database = new MongoInternals.RemoteCollectionDriver("<<mongo url>>");
MyCollection = new Mongo.Collection("collection_name", { _driver: database });
<<mongo_url>> is your standard mongodb url.
Eg. mongodb://127.0.0.1:27017/database_name
Now, in your specific scenario, main_db contains the user collection (I'm under the assumption that this is pertaining to meteor user collection). You need to have this loaded at all times. You can't have it load after login since user information - which is required for logging in resides in that db!
Once you take care of the above, connecting to the remaining two dbs can be done on login as below:
/lib/dbconnection.js (this will be common to both server and clinet)
Meteor.methods({
loadDB: function(){
if(Meteor.userId()){ // if a user has logged in
var database = new MongoInternals.RemoteCollectionDriver("<<mongo url>>");
MyCollection = new Mongo.Collection("collection_name", { _driver: database });
}
}
})
Meteor.call("loadDB");
loadDB will get called each time a user logs in. But I fear that it will be run each time any user logs in. In order to avoid it being re-initialized for each user login, you might want to do a check on whether database or myCollection already exists.

NodeJS Update API - Internal Server Error

It's about time I call in the big guns for this as I can't seem to figure it out.
I have a simple CRUD API in Node. I'm using EJS on the front-end. Essentially, I've got a selectAllRecords view where I display a table of all the records. I have a button next to each record to edit the record. When the button is clicked, it redirects to an editrecord.ejs page, hits the API for a single record where each line is displayed as a value in an input box. From there, I have an onclick method with an XMLHttpRequest making a put request to update the database. However, I'm getting an error - 500 (Internal Server Error) - I'm sure it's something fairly simple I'm missing, but I can't seem to figure it out.
Any help is greatly appreciated! Code below:
First on my view:
<script type="text/javascript">
function someFunc() {
var id = <%= id %>;
var url = '/api/edit/' + candID;
console.log('url ' + url);
var name = document.getElementById("name").value;
var email = document.getElementById("email").value;
var data = {
name: name,
email: email,
}
var json = JSON.stringify(data);
console.log('json ' + json);
var xhr = new XMLHttpRequest();
xhr.open("PUT", url, true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(json);
};
and in my queries.js file:
function updateCandidate(req, res, next) {
var candID = parseInt(req.params.id);
console.log('hit update');
console.log('name ' + req.body.name);
db.none('update cands set name=$1, email=$2 where id=$3',
[req.body.name, req.body.email, candID])
.then(function () {
var candID = candID
var name = data.name;
var email = data.email;
res.render("edited", {"candID":candID, "name":name, "email":email});
})
.catch(function (err) {
return next(err);
});
}
A potentially important note, when I hit the update button and execute the someFunc() function, the dev tool logs show a PUT request to 'api/edit/50' (or whatever ID) and '500 (Internal Server Error)' -- If i hard reload the 'getAllRecords' view, the updates are reflected so it's an issue with the render or redirect (I've tried both)
EDIT
As suggested, I removed the render from the updateCandidate method, but I still get a 500 Internal Server Error. the devtools show me the PUT request is hitting the right URL so i'm really not sure why this isn't functioning correctly. Updated code below...
function updateCandidate(req, res, next) {
var candID = parseInt(req.params.id);
db.none('update cands set name=$1, email=$2, client=$3, jobtitle=$4, question1=$5, question2=$6, question3=$7 where id=$8',
[req.body.name, req.body.email, req.body.client,
req.body.jobtitle, req.body.question1, req.body.question2, req.body.question3, candID])
.then(function (data, err) {
res.status(200)
.json({
status: 'success',
message: `Edited Candidate`
});
})
.catch(function (err) {
return next(err);
});
}
You are sending an ajax request to update the record. So, you should not try to render a view or redirect user as the response of this request. Instead, you can send back a JSON object with some properties e.g. "status".
Then on client side, you check the returned JSON response and based on "status" parameter ( or any other you chose ), you can either update your data or reload the page using window.reload on client side.
Your db query says
db.none('update cands set name=$1, email=$2 where id=$8', [req.body.name, req.body.email]) ...
Shouldn't it be
db.none('update cands set name=$1, email=$2 where id=$8', [req.body.name, req.body.email, candID])

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

Redirect to home page on login with username appended in url

I want to know when a user logs in successfully onto Facebook he is redirected to home page with its first name and last name being part of the url.
How is that process being carried out and how to do the same using nodejs.
var checkSession=require('./../custom-modules/sessionManager');
var express=require('express');
var router = express.Router();
var builtLoginMaster=require('./../custom-modules/BuiltLoginMaster');
var scripts=require('./../cdnscripts.json');//cdn scripts
//handle login authentication
router.post('/logincheck',function(req,res,next){
console.log("got hit on authenticate url");
var session=req.session;
var email = req.body.email;
var pass = req.body.password;
builtLoginMaster.authenticateUser(email,pass,function(object){
if(object!==null)
{
console.log('Rendering chat page and result');
console.log("setting session");
// console.log(session);
session.user=object.toJSON();//set user object in session
//here home page
//here only home page rendered with same '/logincheck' whereas i want something "http://example.com/firstname.lastname"
res.render('home',{title:"Twiddle",
url:scripts,
user:object.toJSON()});
}
else{
session.err="Invalid credentials";
}
});
});
//=============================Root file===========================
router.get('/',checkSession,function(req,res,next){
console.log("after checked session");
console.log(req.session);
if(!req.isLoggedIn)
{
console.log('user not logged in');
res.render('login',{ title:'Login Page',
url:scripts,
session:req.session});
}
else
{
res.render('home',{title:"Twiddle",
url:scripts,
user:req.session}) ;
console.log("redirect to home");
}
});
router.get('/register',function(req,res,next){
res.render('register',{ title:'Registration',
url:scripts});
});
router.get('/test',function(req,res,next){
res.render('test',{ title:'test',
url:scripts});
});
module.exports = router;
Instead of
res.render('home...
what you wanna do instead is
res.redirect('/user/' + user.username);
Note, you should use /user/:username instead of just /:username because that could get tricky and handling that kind of "unified" path would not be very efficient. You'll essentially be querying the database on every request /xyz to check whether xyz is a valid user/name or just another path.
Now from the /logincheck you assigned the user object in session so it'll be available in req.session.user on each new request. So you can in a way just continue on from there.
You then want to define the path /user/:username
app.get('/user/:username', function(req, res, next){
// Here, if you don't want just anybody to view this page, you can verify
if(req.session.user.username != req.params.username) return res.status(401).send('Unauthorized!');
// Then continue to render whatever you like
res.render('home',{title:"Twiddle", user:req.session.user});
});
Some resources for more info on the following:
req.session,
req.params

How to print a response from Express.js into the POST requesting html page?

I wanted to print the login validation messages on the login page itself. But the response is being printed on a new blank page. Is there any way to fetch the response and print in on any existing div tags?
I'm using Express.js to handle the login validation.
app.post('/login',function(req,res){
var user_name=req.body.user;
var password=req.body.pwd;
console.log("User name = "+user_name+", password is "+password);
if (user_name=="sudheesh" && password=="pass") {
sess = req.session;
sess.user=user_name;
console.log("Logged in..");
res.send('done');
}
else {
res.send('not_done');
}
});
The HTML script looks like this,
<script>
$(document).ready(function(){
var user,pwd;
$("#submit").click(function(){
email=$("#user").val();
pass=$("#pwd").val();
/*
* Perform some validation here.
*/
$.post("http://localhost:3000/login",{user:user,pwd:pwd},function(data){
console.log(data);
if(data=='done')
{
alert("you have logged in..!");
window.location.href="/about";
}
});
});
});
</script>

Categories

Resources