Retrieve token/Create charge - Stripe - javascript

This might be a stupid question but here we go.
I've set up Stripe Elements (https://stripe.com/docs/elements) to collect credit card info, and tockenize it.
Now I'm trying to set up charges, but I'm unsure of how to set up my "server-side" code.
Submitting the form in my controller.js:
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
https://stripe.com/docs/charges:
"On your server, grab the Stripe token in the POST parameters submitted by your form."
From my Nodecharge.js:
// Set your secret key: remember to change this to your live secret key in
production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = require("stripe")("sk_test_111111111111111111");
// Token is created using Stripe.js or Checkout!
// Get the payment token ID submitted by the form:
var token = request.body.stripeToken; // Using Express
// Charge the user's card:
stripe.charges.create({
amount: 1000,
currency: "sek",
description: "Example charge",
source: token,
}, function(err, charge) {
// asynchronously called
});
My HTML-form:
<form action="/charge" method="post" id="payment-form">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
Submitting a payment with the test card, I get redirected to /charge with a 404.
I'm new to this, and I've obviously copy/pasted some code, but I'm trying hard to wrap my head around it, and I want to understand it, not just make it work.
I kinda get how the credit card info retrieval works with js, but I'm a bit confused when it comes to the charging/redirecting/404/.
I mean, this action-line points me to a non-existing page on my end, right? Do I need to create this page?
<form action="/charge" method="post" id="payment-form">
Sorry for the length of this post, please help me understand what's going on here, or what I need to fix.
Appreciate any help.

How are you serving your backend --- Express?
If you're seeing a 404 when you submit your form to /charge it sounds like you might not have a app.post route setup for /charge in Express.
You can read through the guide on routing for a little more detail
https://expressjs.com/en/guide/routing.html
If you want to see a simple working example, take a look at this (make sure to replace the pk_test and sk_test with your actual test keys):
var stripe = require("stripe")("sk_test_xxxyyyzzz");
var express = require('express'), bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var app = express();
app.get('/',function(req, res) {
// for kicks, just sending checkout
res.send('<form action="/charge" method="POST">Buy it !<script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="pk_test_xxxyyyyzzzz"></script></form>')
});
app.post('/charge',urlencodedParser, function(req, res) {
// grab a token
var token = req.body.stripeToken;
// creating a charge, for real use add things like error handling
stripe.charges.create({
amount: 2000,
currency: "usd",
source: token, // obtained with Stripe.js
description: "Charge"
}, function(err, charge) {
res.send("You made a charge: "+ charge.id);
});
});
app.listen(5000)

To create source token via stripe, first need to refer stripe.js from stripe.com and it must be from stripe.com.
And then add below code to add your card info and generate a token.
var stripe = Stripe('Your stripe publisheable key');
var elements = stripe.elements;
stripe.createToken(elements[0], additionalData).then(function (result) {
example.classList.remove('submitting');
if (result.token) {
// If we received a token, show the token ID.
example.querySelector('.token').innerText = result.token.id;
example.classList.add('submitted');
}
Here, you will get a token, that will be necessary to create your customer. Use below code to create your customer. I used C#.NET
StripeConfiguration.SetApiKey("sk_test_JTJYT2SJCb3JjLQQ4I5ShDLD");
var options = new CustomerCreateOptions {
Description = "Customer for jenny.rosen#example.com",
SourceToken = "tok_amex"
};
var service = new CustomerService();
Customer customer = service.Create(options);
Now, you can get your required amount form this user from the card token you got from stripe like below:
StripeConfiguration.SetApiKey("sk_test_JTJYT2SJCb3JjLQQ4I5ShDLD");
var options = new ChargeCreateOptions {
Amount = 2000,
Currency = "aud",
Description = "Charge for jenny.rosen#example.com",
SourceId = "tok_amex" // obtained with Stripe.js, }; var service = new ChargeService();

Related

Recurly.js in sandboxmode - ThreeDSecure not returning anything after clicking "Succeed Test Authentication"

I have problem with implementation of 3ds verification for Recurly, i have followed example from https://github.com/recurly/recurly-js-examples/blob/master/public/3d-secure/authenticate.html
My problem is that first iframe is loading correctly, but after clicking "
Succeed Test Authentication" returns nothing to my threeDSecure.on('token' funcition(){}). It loads iframe with information "To complete your checkout process, please close this browser tab and return to your checkout form." Thanks for any responses.
My view file
https://pastebin.com/irCuGr48
<form id="pm-recurly-form-3ds" method="post" action="<?php echo esc_url( get_permalink( get_queried_object_id() ) ); ?>subscription/pay/">
<div id="container-3ds-authentication" class="three-d-secure-auth-container col-12 " ></div>
<div class="three-d-secure-submitting-messagge col-12">
Authenticating your payment method...
</div>
<?php wp_nonce_field( 'pm-register-subscription-nonce' ); ?>
<input type="hidden" name="pm-form-request" value="register-subscription" />
<input type="hidden" name="pm-price-plan" value="<?php echo esc_attr( $pm_price_plan ); ?>">
<input type="hidden" name="three-d-secure-token" id="three-d-secure-token" value="">
<input type="hidden" name="recurly-token" id="recurly-token" value="">
</form>
My JS file
https://pastebin.com/7zYDAEJs
// We expect this page to load with the following parameter pattern
// `/3d-secure.html#token_id=xxx&action_token_id`
// This is a simple parser for that pattern. You may use window.URLSearchParams
// instead if IE11 support is not needed
var hashParams = location.hash.substr(1).split('&').reduce(function (acc, i) {
var [k,v] = i.split('=');
acc[k]=v;
return acc;
}, {});
// Configure Recurly.js
recurly.configure(recurly_key);
// In order to remain backend agnostic, this example passes the Recurly.js credit card token
// to this page via the URL hash. Here we add it to the form so that it will be passed
// to our backend
document.querySelector('#recurly-token').setAttribute('value',hashParams.token_id);
// Now we construct the 3-D Secure authentication flow
var risk = recurly.Risk();
var threeDSecure = risk.ThreeDSecure({ actionTokenId: hashParams.action_token_id });
var container = document.querySelector('#container-3ds-authentication');
// Handle errors that occur during 3-D Secure authentication
threeDSecure.on('error', error);
// 'token' is called when your user completes the 3-D Secure authentication flow
threeDSecure.on('token', function (token) {
console.log(token);
// place the result token in your form so that it will be submitted
// when the customer re-submits
document.querySelector('#three-d-secure-token').setAttribute('value',token.id);
// Hide the container once we have a token
container.style.display = "none";
// Show the loading message
document.querySelector('.three-d-secure-submitting-messagge').style.display = "block";
// submit the form automatically
recurly_form_verify.submit();
});
// Attach our 3D Secure session to the container
threeDSecure.attach(container);
// Show the container
container.style.display = "block";
// runs some simple animations for the page
document.querySelector('body').classList.add( 'show' );
Second iframe
Resolved via issue in recurly-js repo:
https://github.com/recurly/recurly-js/issues/553

Stripe and NodeJS - Passing an amount to charge

EDIT: To clarify, the charge does actually process, the only thing I can't do is dynamically set the charge amount.
I've worked all day and haven't found any solution. Here is my server.js:
app.post('/charge', function(req, res) {
var stripeToken = req.body.stripeToken;
var amount = 12000;
console.log(req);
stripe.charges.create({
card: stripeToken,
currency: 'usd',
amount: amount
},
function(err, charge) {
if (err) {
res.send(500, err);
} else {
res.send(204);
}
});
});
And here is my dynamic stripe button.
$('#calcTransAmount').click(function(event) {
var amount = $('#transAmount').scope().totall;
//console.log(amount);
var holder = document.getElementById('hello');
var script = document.createElement('script');
script.src = 'https://checkout.stripe.com/checkout.js';
script.setAttribute('class', 'stripe-button');
script.setAttribute('data-amount', amount);
script.setAttribute('data-key',"KEY");
script.setAttribute('data-image', "IMG");
script.setAttribute('data-name', "NAME");
script.setAttribute('data-billing-address', "true");
script.setAttribute('data-description', "Purchase");
script.setAttribute('data-locale', "auto");
document.getElementById('btnCont').appendChild(script);
});
The button works with the dynamic amount and everything, now I just can't seem to figure out how the post to /charge receives the amount and sets it as a variable.
This is my req object:
{ stripeToken: 'tok_19t9jcLhf04QCVXXXXXXXX',
stripeTokenType: 'card',
stripeEmail: 'me#gmail.com',
stripeBillingName: 'Clark',
stripeBillingAddressCountry: 'United States',
stripeBillingAddressCountryCode: 'US',
stripeBillingAddressZip: 'Zip',
stripeBillingAddressLine1: 'My address',
stripeBillingAddressCity: 'City',
stripeBillingAddressState: 'State' }
And I can't find a way to get my data-amount attribute from the button to the server to charge a dynamic amount.
Thanks
Special thanks to #koopajah for the inspiration for the solution.
In the form on the client side, in addition to the javascript button, I passed a key value using a hidden input box that would allow my server side to grab the cart total from our DB.
<form action="/charge" method="POST">
<input name="coKey" value ="{{currentUser.coKey}}">
</form>
Then on the server side, I can pull the appropriate key like this: var coKey = req.body.coKey;

Proper display of user editing form (CRUD model) with checkbox

I'm making a simple CRUD model with input checkbox. I have no problems on server side, everything is fine. I use NodeJS +MongoDB. But I have problem in editing existing user. When I edit an existing user with a checked checkbox( I get JSON object with parameter checked=true ) how should I display it using JS? This is part of my users.js file in /routes/ folder
var express = require('express');
var router = express.Router();
var User = require('../../models/User');
var rest = require('restler');
router.get('/adduser', function(req, res){
var user = new User();
user.contacts.push({phone: '', email: ''});
rest.get('http://localhost:3000/api/adduser').on('complete', function(data) {
res.render('users/add', { title: 'Add New Users' , n: user});
});
});
And this is views/users/fields.jade part of file for better understanding:
.form-group
label.col-sm-2.control-label(for='email') E-mail:
.col-sm-10
input(type="email", placeholder="email", name="email", value = n.contacts[0].email,required)
.form-group
.col-sm-offset-2.col-sm-10
input#enabled(type="checkbox",style='text-align: center; vertical-align: middle;',placeholder="", name="enabled", value = n.enabled)
| Enable user
So my problem is that I don't understand how I should display that checkbox is really checked when loading existing user.
If user is checked attribute n.enabled=true and if not n.enabled=false. So if user is checked on load of that user I need the input filed to be checked.
I've tried it to do the following way, but it wrote me that n wasn't defined...and I don't know how to pass n as the parameter for that function:
$(document).ready(function(){
if(n.enabled=="true"){$("enabled").toggle(this.checked);}
});
In fields.jade, change value = n.enabled to checked = (n.enabled ? 'checked' : '')
Use # for id-selectors and use n.enabled directly to hide or show your element like,
$("#enabled").toggle(n.enabled);
//-^ prepend # before id selectors
toggle() will show/hide your element, To check uncheck use the prop() like
$(document).ready(function(){
$("#enabled").prop("checked",n.enabled);
});

Trouble with nested nodes with using Firebase + AngularJS for a chat app

I am trying to create a small chat app to help me learn AngularFire (Firebase + AngularJS). The only functionality i am trying to get is the ability to create chat rooms and then the ability to chat in each room. By the way, i'm doing this in Rails if it matters (my user login and everything is handled through Rails).
So far i have this as my sample code, this is what the view looks like:
<div ng-controller="RoomsCtrl">
<div ng-repeat="rm in rooms">
<div>
<ul>
<li class="message phm pvm pull-left" ng-repeat="msg in messages">
<span class="message-author">{{msg.from}}</span>
<span class="message-body">{{msg.body}}</span>
<span class="message-timestamp">{{msg.timestamp | date:'MMM d, yyyy h:mm a'}}</span>
</li>
</ul>
</div>
<form>
<span class="hidden"><%= current_user.full_name %></span>
<textarea ng-model="msgBody" ng-keydown="addMessage($event)" placeholder="What's on your mind..."></textarea>
</form>
</div>
<form>
<input type="text" ng-model="roomName" ng-keydown="addRoom($event)" placeholder="Enter a room name..."><
</form>
</div>
Here is my AngularFire script:
var app = angular.module("ChatApp", ["firebase"]);
function RoomsCtrl($scope, $firebase) {
var organizationId;
if (gon) {
organizationId = gon.organization_id;
}
var orgRef = new Firebase("https://glowing-fire-7051.firebaseio.com/"+organizationId);
$scope.rooms = $firebase(orgRef);
$scope.addRoom = function(e) {
if (e.keyCode != 13) return;
$scope.rooms.$add({name: $scope.roomName, timestamp: new Date().getTime()})
$scope.roomName = "";
e.preventDefault();
}
$scope.messages = $firebase(orgRef);
$scope.addMessage = function(e) {
if (e.keyCode != 13) return;
$scope.messages.$add({name: $scope.msgName, body: $scope.msgBody, timestamp: new Date().getTime()})
$scope.msgBody = "";
e.preventDefault();
}
}
Each user belongs_to and Organization as you can see by the gon part that is just getting the id of the organization that the current_user belongs to. The code i have for the addRoom does actually create a room under the organization. The Forge data looks like this:
<my forge id>
1
JHiiMka5OloVaqf-sA7
name: "Test Room"
timestamp: 1394500795299
JHjA0rwIDJNVDU4HVaF
name: "Another Room"
timestamp: 1394508307247
I am also seeing the data being reflected on the site as well. When i create a new room, the room displays on the site. My problem (i think) lies only with the messages. I have been researching for hours with little to no success on a the subject of nested references. I kind of understand it but i haven't been able to figure out how i can create a room (dynamically through the site) and then have access to create messages under that room's node in Firebase.
My view code above shows you how i was thinking it would display on the page. My question is, how do i tie the two together through Firebase / AngularFire? Thanks in advance for any help! And let me know if you have any questions that might shed more light on anything.
UPDATE:
I sent this question to Firebase support through their website and received a response helping me with almost all of it. I sent a follow up email to get clarification on a section i'm not understanding in their response and waiting to here back. Their advice was to replace:
var orgRef = new Firebase("https://glowing-fire-7051.firebaseio.com/"+organizationId);
with
var orgRef = new Firebase("https://glowing-fire-7051.firebaseio.com/").child(organizationId);
That would create a new Firebase reference for a child of an existing location. Then they said to use this for my $scope.messages definition:
$scope.messages = $firebase(orgRef.child(roomID).child("messages"));
This would assume that in /1/room/ there is a child named “messages” which holds your messages.
The part i am having trouble with is the .child(roomID) in the messages definition because it is telling me it is undefined (which it is). What should that be defined as...i'm assuming it should be the ID of the newly created room?
I finally got the answer to my question from posting on the Firebase + AngularJS google group. I was missing a couple things. Here is my final code:
var app = angular.module("ChatApp", ["firebase"]);
function RoomsCtrl($scope, $firebase) {
var organizationId;
if (gon) {
organizationId = gon.organization_id;
}
var orgRef = new Firebase("https://<my forge id>.firebaseio.com/").child(organizationId);
$scope.rooms = $firebase(orgRef.child('rooms'));
$scope.addRoom = function(e) {
if (e.keyCode != 13) return;
$scope.rooms.$add({name: $scope.roomName, timestamp: new Date().getTime()}).then(function(ref){
var roomId = ref.name();
$scope.messages = $firebase(orgRef.child('rooms').child(roomId).child("messages"));
});
$scope.roomName = "";
e.preventDefault();
}
$scope.addMessage = function(e) {
if (e.keyCode != 13) return;
$scope.messages.$add({name: $scope.msgName, body: $scope.msgBody, timestamp: new Date().getTime()})
$scope.msgBody = "";
e.preventDefault();
}
}
The main parts that i was missing was the .then() callback and i wasn't setting up the definition to $scope.messages correctly where it would be referencing the parent room. These lines are the major part of the fix:
$scope.rooms.$add({name: $scope.roomName, timestamp: new Date().getTime()}).then(function(ref){
var roomId = ref.name();
$scope.messages = $firebase(orgRef.child('rooms').child(roomId).child("messages"));
});
Hope this helps anyone else with a similar problem.

passing data between server and client (node.js + mongodb)

I'm working with node.js express and mongodb, I have a input data from client, I need to pass the data to server look for its property and send to the client in another page.
Now I have problem with req.body.age that suppossed to get the data from client's input and use find() to get its appropriate property.
Server side code:
functions are routed in another .js file
exports.find_user = function(req, res) {
res.render('find_user.jade');
};
exports.user = function(req, res){
member = new memberModel();
member.desc.age = req.body.age; //problem
console.log(req.body.age); //undefined
memberModel.find({desc: {age: '7'}}, function(err, docs){
res.render('user.jade', { members: docs });
console.log(docs);
});
};
memberModel.find({desc: {age: '7'}} just hardcode picking up user with age 7 (works)
client side code (jade):
page for data input:
find_user.jade
form(action='/', method='post')
fieldset
lable(for="age") Find user by age:
input(type="text", size="30", name="age", required="required")
input(type='button', value='Find', onclick='location.href=\'find_user/user/\'')
page for data output with its property:
user.jade
tr
th Name
th Age
tbody
- members.forEach(function(member){
tr
td= member['name']
td= member['desc']
- });
You are not submitting your data in find_user.jade file when the user clicks the button. Instead, the client is only redirected to another page.
This is how your find_user.jade file should look like:
form(action='find_user/user/', method='post')
fieldset
label(for="age") Find user by age:
input(type="text", size="30", name="age", required="required")
input(type='submit', value='Find', name="submit")

Categories