Charging a custom amount with Stripe and Node.js - javascript

I'm going to try and be thorough as possible. So what I'm trying to do is charge a user a percentage of the overall total that is calculated. How do we get the total? Well, the total cost is depended upon the progression of questions the user answers.
If the user needs a specific service then the cost might increase a bit, say to $100, but we're wanting to charge just 10% of that total that constantly changes like stated before. Currently, the amount is hardcoded, but since the amount changes depending on their services select, I can't have it hard coded.
I'm new to Stripe and Node but is there an easy way such as 'document.getElementById'? of something similar? The charge and everything work correctly but I believe I'm getting confused on the routing.
My HTML form (with the area where the total will be displayed):
<div class="" style="margin-top: 60px;">
<h2 class="quote-info">Estimated total: $<span id="new_text"></span> USD</h2>
<h2 class="quote-info">Reservation deposit: $<span id="new_text2"></span> USD</h2>
</div>
<!-- Payment 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"></div>
</div>
<input type="hidden" name="totalAmount" value="1000">
<button>Submit Payment</button>
</form>
My script tag that's found at the bottom of my HTML file that contains the form above:
<script type="text/javascript">
//Create a Stripe client
var stripe = Stripe('my_key_should_go_here');
// Create an instance of Elements
var elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
var style = {
base: {
color: '#32325d',
lineHeight: '24px',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
// Create an instance of the card Element
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
stripeTokenHandler(result.token);
}
});
});
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);
var formData = JSON.stringify({
mytoken: token.id
});
$.ajax({
type: "POST",
url: "/charge",
data: formData,
success: function(){alert("done")},
dataType: "json",
contentType: "application/json"
});
// alert("Created a token with value: "+token.id)
form.submit();
}
</script>
And lastly, my app.js file:
const express = require('express');
const stripe = require('stripe')('deleted_key');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
// Set Static Folder
app.use(express.static('public'));
// Index route
app.get('/charge', (req, res) => {
res.send();
});
// charge route
app.post('/charge', (req, res) => {
// const amount = 2500;
const amount = req.body.totalAmount;
stripe.customers.create({
email: "random#gmail.com",
source: req.body.mytoken
})
.then(customer => {
stripe.charges.create({
amount,
description:'specified service description here',
currency:'usd',
customer:customer.id
})})
.then(charge => res.send('success'));
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
My primary question is this, how would I go about obtaining the amount given in the 'new_text' area in my HTML file to use and charge the user in node?

To use the getElementById is to add an ID to your amount field first:
<input type="hidden" name="totalAmount" id="totalAmount" value="1000">
Then you can use the ID to get the value of the field:
const amount = document.getElementById("totalAmount").value;
Although, I can see that your input type is hidden - is that intentional?

Related

Stripe payment always succeeds and the amount of the paymentIntent cannot be changed

I am struggling for a long period of time to implement Stripe in my Laravel app, but I've encountered a lot of problems. I did somehow implemented the logic but I cannot or I don't know how I can send the current order total to create the paymentIntent, all of the payments are stored with a default amount of 500, set up in the Controller. I have to mention that after the success response from stripe, the current order should be stored in the database with user shipping details which are found in the first form and all the products ordered, stored in session. Let me show you for a better understanding.
This is the view (revieworder.blade.php) where I have a 2 forms, one with the user's shipping details, and the Stripe payment form, and a list of cart products from the session:
<ul class="list-group mb-3">
<?php $total = 0 ?>
#if(session('cart'))
#foreach(session('cart') as $id => $details)
<?php $total += $details['price'] * $details['quantity'] ?>
<li class="list-group-item d-flex justify-content-between lh-condensed">
<img src="../img/{{ $details['image'] }}" alt="{{ $details['name'] }}" width="60" height="60">
<div>
<h6 class="my-0">{{ $details['name'] }}</h6>
<small class="text-muted">{{ __('Quantity') }}: {{ $details['quantity'] }}</small><br>
<small class="text-muted">{{ __('Unit price') }}: {{ $details['price'] }} RON</small>
</div>
<span class="text-muted">{{ $details['price'] * $details['quantity'] }} RON</span>
</li>
#endforeach
#endif
<li class="list-group-item d-flex justify-content-between">
<span>Total (RON)</span>
<strong id="total">{{ $total.' RON' }}</strong>
</li>
</ul>
<form id="payment-form">
#csrf
<div id="card-element"><!--Stripe.js injects the Card Element--></div>
<button id="submit" class="submit-id">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay now</span>
</button>
<p id="card-error" role="alert"></p>
<p class="result-message hidden">
</p>
</form>
<script>
//Stripe script
var stripe = Stripe("pk_test_XXX");
// The items the customer wants to buy
var purchase = {
items: [{id: "prod"}] //sessions cart
};
console.log(purchase);
var elements = stripe.elements();
var style = {
base: { //some styling },
invalid: {
fontFamily: 'Arial, sans-serif',
color: "#fa755a"
}
};
var card = elements.create("card", { style: style });
// Stripe injects an iframe into the DOM
card.mount("#card-element");
card.on("change", function (event) {
// Disable the Pay button if there are no card details in the Element
document.querySelector("button").disabled = event.empty;
document.querySelector("#card-error").textContent = event.error ? event.error.message : "";
});
// Disable the button until we have Stripe set up on the page
document.getElementsByClassName("submit-id").disabled = true;
$('#payment-form').submit(function(){
fetch("{{ url(app()->getLocale().'/revieworder') }}", {
method: "POST",
headers: {
"Content-Type": "application/json",
'X-CSRF-TOKEN': "{{ csrf_token() }}"
},
body: JSON.stringify(purchase)
})
.then(function(data) {
$('#payment-form').submit(function(event) {
event.preventDefault();
// Complete payment when the submit button is clicked
payWithCard(stripe, card, data.clientSecret);
});
});
// Calls stripe.confirmCardPayment
var payWithCard = function(stripe, card, clientSecret) {
loading(true);
stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: card
}
})
.then(function(result) {
if (result.error) {
// Show error to your customer
showError(result.error.message);
} else {
// The payment succeeded!
// The order should be stored in the database
orderComplete(result.paymentIntent.id);
}
});
};
// Shows a success message when the payment is complete
var orderComplete = function(paymentIntentId) {
loading(false);
document
.querySelector(".result-message a")
.setAttribute(
"href",
"https://dashboard.stripe.com/test/payments/" + paymentIntentId
);
document.querySelector(".result-message").classList.remove("hidden");
document.getElementsByClassName("submit-id").disabled = true;
};
// Show the customer the error from Stripe if their card fails to charge
var showError = function(errorMsgText) {
loading(false);
var errorMsg = document.querySelector("#card-error");
errorMsg.textContent = errorMsgText;
setTimeout(function() {
errorMsg.textContent = "";
}, 4000);
};
// Show a spinner on payment submission
var loading = function(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.getElementsByClassName("submit-id").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.getElementsByClassName("submit-id").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
};
});
</script>
And then this is the controller which handles the secret client key and the paymentIntent (CheckoutController.php):
public function create(){
\Stripe\Stripe::setApiKey('sk_test_XXX');
header('Content-Type: application/json');
try {
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$paymentIntent = \Stripe\PaymentIntent::create([
'amount' => "500",
'currency' => 'ron',
]);
$output = [
'clientSecret' => $paymentIntent->client_secret,
];
echo json_encode($output);
} catch (Error $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
}
So, one of the problems is that whenever I get to pay for an order, no matter what credit card number I pass, it always succeeds, and that is a major bug. The second one, I need to pass the total of the current order, otherwise all orders will get a total amount of 500, the default value. I tried to pass the session cart items to the fetch but it didn't work. Even though I cannot send all the items from the cart to the intent, at least the total price should correspond.
If I wasn't clear enough with anything, please let me know. I would really appreciate any piece of advice. Thank you !
**Edit:
You can update the PaymentIntent amount via the API (reference) before you confirm it (either on the server or client side. If you're encountering errors sending this, please share the details of that error.
You need to say more about the "it always succeeds" and exactly what request you are making. You did not show how you are using Stripe.js. You should use the test cards that Stripe provides to test success and failure cases. If you are getting different results than specified you will need to provide more detail about what exactly you're doing and what you expect the result to be.

Access Vue props from plain javascript

I am implementing Stripe inside my application and the Stripe docs show just plain JS so I have been putting the Stripe API calls in the script tag without any of the Vue methods. Things have been working fine until now. I am passing props down from the parent component and I cannot access the props from inside of the Script.
Some of the Stripe documentation says to implement the JS after the HTML has rendered so I am using the mounted method for some of this. Any ideas on how to get this working?
I have tried putting the API call in a method and calling the method on a click event on the form, but when I do that it doesn't know what the token is that Stripe uses.
towards the bottom of the code you can see where I try to get the this.plan that is in props.
<template>
<form method="post" id="payment-form">
<h4 class="h4Spacing">Billing Information</h4>
<div class="form-group">
<b-form-input type="email" class="form-control" id="email" placeholder="Email Address"/>
</div>
<div class="form-group">
<b-form-input type="text" class="form-control" id="name_on_card" name="name" placeholder="Name on Card"/>
</div>
<div class="form-group">
<b-form-input type="text" class="form-control" id="address" name="address_line1" placeholder="Address"/>
</div>
<div class="form-group">
<b-form-input type="text" class="form-control" id="city" name="address_city" placeholder="City"/>
</div>
<div class="form-group">
<b-form-input type="text" class="form-control" id="state" placeholder="State"/>
</div>
<div class="form-group">
<div id="card-element" class="form-control">
<!-- A Stripe Element will be inserted here. -->
</div>
<div v-if="successful">
<h3 class="title" data-tid="elements_examples.success.title">Payment successful</h3>
<p class="message"><span data-tid="elements_examples.success.message">Thanks for trying Stripe Elements. No money was charged, but we generated a token: </span><span class="token">tok_189gMN2eZvKYlo2CwTBv9KKh</span></p>
<a class="reset" href="#">
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path fill="#000000" d="M15,7.05492878 C10.5000495,7.55237307 7,11.3674463 7,16 C7,20.9705627 11.0294373,25 16,25 C20.9705627,25 25,20.9705627 25,16 C25,15.3627484 24.4834055,14.8461538 23.8461538,14.8461538 C23.2089022,14.8461538 22.6923077,15.3627484 22.6923077,16 C22.6923077,19.6960595 19.6960595,22.6923077 16,22.6923077 C12.3039405,22.6923077 9.30769231,19.6960595 9.30769231,16 C9.30769231,12.3039405 12.3039405,9.30769231 16,9.30769231 L16,12.0841673 C16,12.1800431 16.0275652,12.2738974 16.0794108,12.354546 C16.2287368,12.5868311 16.5380938,12.6540826 16.7703788,12.5047565 L22.3457501,8.92058924 L22.3457501,8.92058924 C22.4060014,8.88185624 22.4572275,8.83063012 22.4959605,8.7703788 C22.6452866,8.53809377 22.5780351,8.22873685 22.3457501,8.07941076 L22.3457501,8.07941076 L16.7703788,4.49524351 C16.6897301,4.44339794 16.5958758,4.41583275 16.5,4.41583275 C16.2238576,4.41583275 16,4.63969037 16,4.91583275 L16,7 L15,7 L15,7.05492878 Z M16,32 C7.163444,32 0,24.836556 0,16 C0,7.163444 7.163444,0 16,0 C24.836556,0 32,7.163444 32,16 C32,24.836556 24.836556,32 16,32 Z"></path>
</svg>
</a>
<div class="caption">
<span data-tid="elements_examples.caption.no_charge" class="no-charge">Your card won't be charged</span>
<a class="source" href="https://github.com/stripe/elements-examples/#example-1">
<svg width="16px" height="10px" viewBox="0 0 16 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M1,8 L12,8 C12.5522847,8 13,8.44771525 13,9 C13,9.55228475 12.5522847,10 12,10 L1,10 C0.44771525,10 6.76353751e-17,9.55228475 0,9 C-6.76353751e-17,8.44771525 0.44771525,8 1,8 L1,8 Z M1,4 L8,4 C8.55228475,4 9,4.44771525 9,5 C9,5.55228475 8.55228475,6 8,6 L1,6 C0.44771525,6 6.76353751e-17,5.55228475 0,5 C-6.76353751e-17,4.44771525 0.44771525,4 1,4 L1,4 Z M1,0 L15,0 C15.5522847,-1.01453063e-16 16,0.44771525 16,1 L16,1 C16,1.55228475 15.5522847,2 15,2 L1,2 C0.44771525,2 6.76353751e-17,1.55228475 0,1 L0,1 L0,1 C-6.76353751e-17,0.44771525 0.44771525,1.01453063e-16 1,0 L1,0 Z" fill="#AAB7C4"></path>
</svg>
<span data-tid="elements_examples.caption.view_source">View source on GitHub</span>
</a>
</div>
</div>
</div>
<!-- <form action="/charge" method="post" id="payment-form">-->
<!-- <div class="form-row">-->
<!-- <label for="name"> Name </label>-->
<!-- <div id="name"></div>-->
<!-- <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>-->
<!-- <b-button class="space" id="payment-request-button">Submit Payment</b-button>-->
<!-- </form>-->
<b-button class="space" type="submit" >Submit Payment</b-button>
</form>
</template>
<script>
import registerElements from './stripeMethods'
// Create a Stripe client.
let stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');
// Create an instance of Elements.
let elements = stripe.elements();
// Custom styling can be passed to options when creating an Element.
// (Note that this demo uses a wider set of styles than the guide below.)
let style = {
base: {
color: '#32325d',
fontFamily: '"Roboto", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
let card = undefined;
import Vue from 'vue';
import axios from 'axios';
import authService from '../../services/authService';
export default {
props: ['plan'],
data: function() {
return {
successful: false,
monthly: {
id: 'prod_Flp17jVPzNUfFz',
price: 25
},
annual: {
id: 'prod_Flp17jVPzNUfFz',
price: 215
}
}
},
methods: {
submitPayment: function () {
}
},
mounted() {
// Create an instance of the card Element.
let card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function (event) {
let displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
let form = document.getElementById('payment-form');
form.addEventListener('submit', function (event) {
console.log(event);
event.preventDefault();
stripe.createToken(card).then(function (result) {
if (result.error) {
// Inform the user if there was an error.
let errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
return result.token
}
}).then(function (result) {
console.log(result);
axios({
method: "POST",
url: '/api/checkout',
headers: {
Authorization: `Bearer ${authService.idToken}`,
},
data: {
subscription: result.id,
plan: this.plan <----------------------------------- not working
},
}).then(function (res) {
// alert("It went through! How? ")
}).catch(function (err) {
console.log(err)
});
});
});
// Submit the form with the token ID.
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
let form = document.getElementById('payment-form');
let hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
}
}
}
</script>
This is a problem of scoping, nothing more. When you try to access this.plan, this is a reference to the callback being executed from the event listener. You need to declare a variable that is assigned the Vue instance to access these fields anywhere in a method:
mounted() {
var vm = this;
// Create an instance of the card Element.
let card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
// Handle real-time validation errors from the card Element.
card.addEventListener('change', function (event) {
let displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Handle form submission.
let form = document.getElementById('payment-form');
form.addEventListener('submit', function (event) {
console.log(event);
event.preventDefault();
stripe.createToken(card).then(function (result) {
if (result.error) {
// Inform the user if there was an error.
let errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
return result.token
}
}).then(function (result) {
console.log(result);
axios({
method: "POST",
url: '/api/checkout',
headers: {
Authorization: `Bearer ${authService.idToken}`,
},
data: {
subscription: result.id,
plan: vm.plan <----------------------------------- not working
},
}).then(function (res) {
// alert("It went through! How? ")
}).catch(function (err) {
console.log(err)
});
});
});

How to solve Undefined index: stripeToken in PHP?

I am getting this error and I have no clue about this and trying to sort out the things and tried many things but nothing works. Kindly check the errors below:
Notice: Undefined index: stripeToken in
/opt/lampp/htdocs/fullbrick/thankYou.php on line 42 NULL Fatal error:
Uncaught Stripe\Error\InvalidRequest: Must provide source or customer.
in /opt/lampp/htdocs/fullbrick/stripe-php/lib/ApiRequestor.php:181
from API request 'req_cuGvSG7abb9bzS' Stack trace: #0
/opt/lampp/htdocs/fullbrick/stripe-php/lib/ApiRequestor.php(144):
Stripe\ApiRequestor::_specificAPIError('{\n "error": {\n...', 400,
Array, Array, Array) #1
/opt/lampp/htdocs/fullbrick/stripe-php/lib/ApiRequestor.php(430):
Stripe\ApiRequestor->handleErrorResponse('{\n "error": {\n...', 400,
Array, Array) #2
/opt/lampp/htdocs/fullbrick/stripe-php/lib/ApiRequestor.php(97):
Stripe\ApiRequestor->_interpretResponse('{\n "error": {\n...', 400 ,
Array) #3
/opt/lampp/htdocs/fullbrick/stripe-php/lib/ApiOperations/Request.php(56):
Stripe\ApiRequestor->request('post', '/v1/charges', Array, Array) #4
/opt/lampp/htdocs/halfdrink/stripe-php/lib/ApiOperations/Create.php(23):
Stripe\ApiResource::_staticRequest('post', '/v1/charges', Array, NULL)
5 /opt/lampp/htdocs/fullbrick/thankYou.php(53): Stripe\Charge::create(Array) #6
{main} in
/opt/lampp/htdocs/fullbrick/stripe-php/lib/ApiRequestor.php on line
181
The code is:
<script>
// Errors For Stripe Payment Card Check
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the customer that there was an error.
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server.
stripeTokenHandler(result.token);
}
});
});
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();
}
// Custom styling can be passed to options when creating an Element.
var style = {
base: {
// Add your base input styles here. For example:
fontSize: '16px',
color: "#32325d",
}
};
// Create an instance of the card Element.
var card = elements.create('card', {style: style});
// Add an instance of the card Element into the `card-element` <div>.
card.mount('#card-element');
</script>
<form action="thankYou.php" method="post" id="payment-form">
<span class="bg-danger" id="payment_errors"></span>
<span class="bg-danger" id="card-errors"></span>
<div class="form-group col-md-6">
<label for="full_name">Full Name:</label>
<input class="form-control" type="text" name="full_name" id="full_name">
</div>
//Same as Email div, phone,address,city,state,zipcode,country,cardname,cardnumber,exp month, exp year, cvc
<button type="submit" class="btn btn-primary" id="checkout_button" style="display:none;">Check Out >></button>
</form>
On thanYou.php
//Getting Variable details like
$full_name = $_POST['full_name']; // same as email,phone, address,city ...
$metadata = array(
"cart_id" => $cart_id,
"tax" => $tax,
"sub_total" => $sub_total,
);
// 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
\Stripe\Stripe::setApiKey("sk_test_hiQjZlN9oJ9GcLGAlPVwAvfq"); // secret Key
// Token is created using Checkout or Elements!
// Get the payment token ID submitted by the form:
$token = $_POST['stripeToken']; // Here not getting token
var_dump($token);
try{ . // Here not getting inside the try because token is null
$charge = \Stripe\Charge::create([
'amount' => 999,
'currency' => 'usd',
'description' => 'Example charge',
'source' => $token,
'receipt_email' => $email,
'metadata' => $metadata,
]);
}catch(\Stripe\Error\card $e){
echo $e;
}
This ApiRequestor.php is the main problem I guess.

How to clear elements from Stripe elements in Angular2

I have form in modal, which include elements from Stripe. App is single app in Angular2. Problem is when user click on modal, type something without submitting form and close modal, on next opening modal is populated with previous data. It seems that I cannot change values of Stripe elements (for credit card number, cvv, postal code, exp date). I didn't manage to find any documented method for this from Stripe.js. I tried to change values of elements, Stripe blocks me. I tried to unmount and mount element again (in order to destroy and create it again), Stripe gives me multiple errors. Does anyone know how to reset Stripe elements in form so that form is clear on opening modal?
I think you should use element.clear()
$stripe_card = elements.create('card', {style: style});
$stripe_card.mount(..);
...
$stripe_card.clear();
Stripe Element Docs
simply unmount it(stripe element) first then mount.
Html part
<form class="stripe_payment_form_div" ng-submit="saveCard()">
<div class="stripe_card_element_div">
<label for="stripe-card-element"></label>
<div id="stripe-card-element" class="field"></div>
</div>
<div class="stripe_payment_completion_div_wrapper">
<div class="stripe_payment_completion_div">
<span class="stripe_card_save_btn_div">
<button class="md-btn md-btn-primary" type="submit">Save Card</button>
</span>
<span class="stripe_card_cancel_btn_div">
<a class="uk-text uk-text-center uk-text-middle" id="cancel_payment_method_btn">Cancel</a>
</span>
</div>
</div>
</form>
Controller part
$scope.stripe = Stripe('#your stripe key');
$scope.stripeCard = null;
var stripeCardElementMoutingId = "#stripe-card-element";
function buildStripeCardElement() {
if (null == $scope.stripe) {
$scope.stripe = Stripe('#your stripe key');
}
var stripeElements = $scope.stripe.elements();
var stripeCard = stripeElements.create('card', {
style: {
base: {
iconColor: '#9cabbc',
color: '#31325F',
lineHeight: '40px',
fontWeight: 300,
fontFamily: 'Helvetica Neue',
fontSize: '13px',
fontSmoothing: 'antialiased',
'::placeholder': {
color: '#9cabbc',
},
},
}, hidePostalCode: true,
iconStyle: 'solid'
});
return stripeCard;
}
var loadStripeElement = function () {
//----- Load Stripe Card Element Div -----//
$scope.stripeCard = buildStripeCardElement();
$scope.stripeCard.mount(stripeCardElementMoutingId);
$scope.stripeCard.on('change', function (event) {
//----- Handle error messages in case of invalid input -----//
stripeCreateTokenResponseHandler(event);
});
};
$("#cancel_payment_method_btn").click(function () {
//----- Below statements can be merge into a single function -----//
$scope.stripeCard.unmount();
$scope.stripeCard = buildStripeCardElement();
$scope.stripeCard.mount(stripeCardElementMoutingId);
$scope.stripeCard.on('change', function (event) {
stripeCreateTokenResponseHandler(event);
});
});
//------------- Load stripe element ------------------//
loadStripeElement();

Stripe.js - Cannot read property 'stripeToken' of undefined

I'm trying to integrate stripe.js into a web app I'm working on, however I'm being thrown the following error:
Cannot read property 'stripeToken' of undefined
The clientside is setting the hidden input of the token but for some reason, the server can't pull it this:
var stripeToken = request.body.stripeToken;
Any ides as to why this might be?
Client-side JS
jQuery(function($) {
$('#payment-form').submit(function(event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken({
number: $('.card-number').val(),
cvc: $('.card-cvc').val(),
exp_month: $('.card-expiry-month').val(),
exp_year: $('.card-expiry-year').val()
}, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
function stripeResponseHandler(status, response) {
// 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();
}
};
jQuery(function($) {
$('[data-numeric]').payment('restrictNumeric');
$('.cc-number').payment('formatCardNumber');
$('.cc-exp').payment('formatCardExpiry');
$('.cc-cvc').payment('formatCardCVC');
$.fn.toggleInputError = function(erred) {
this.parent('.form-group').toggleClass('has-error', erred);
return this;
};
$('form').submit(function(e) {
e.preventDefault();
var cardType = $.payment.cardType($('.cc-number').val());
$('.cc-number').toggleInputError(!$.payment.validateCardNumber($('.cc-number').val()));
$('.cc-exp').toggleInputError(!$.payment.validateCardExpiry($('.cc-exp').payment('cardExpiryVal')));
$('.cc-cvc').toggleInputError(!$.payment.validateCardCVC($('.cc-cvc').val(), cardType));
$('.cc-brand').text(cardType);
$('.validation').removeClass('text-danger text-success');
$('.validation').addClass($('.has-error').length ? 'text-danger' : 'text-success');
});
});
Server-side JS
app.post('/', function(req, res) {
var stripeToken = request.body.stripeToken;
var charge = stripe.charges.create({
amount: 1000, // amount in cents, again
currency: "usd",
source: stripeToken,
description: "Example charge"
}, function(err, charge) {
if (err && err.type === 'StripeCardError') {
// The card has been declined
}
});
});
Form (jade)
form(novalidate='', autocomplete='on', method='POST' id="payment-form")
.form-group
label.control-label(for='cc-number')
| Card number formatting
small.text-muted
| [
span.cc-brand
| ]
input#cc-number.input-lg.form-control.cc-number(type='tel', autocomplete='cc-number', placeholder='•••• •••• •••• ••••', required='')
.form-group
label.control-label(for='cc-exp') Card expiry formatting
input#cc-exp.input-lg.form-control.cc-exp(type='tel', autocomplete='cc-exp', placeholder='•• / ••', required='')
.form-group
label.control-label(for='cc-cvc') Card CVC formatting
input#cc-cvc.input-lg.form-control.cc-cvc(type='tel', autocomplete='off', placeholder='•••', required='')
button.btn.btn-lg.btn-primary(type='submit' class='submit') Submit
h2.validation
our request is in the variable req not request
this var stripeToken = request.body.stripeToken; should be var stripeToken = req.body.stripeToken;

Categories

Resources