2

I've looked all over for answers, but haven't found a solution. I'm using Stripe to charge users, however, the payment shouldn't be hardcoded since the pricing changes depending on the variest questions answered. What I'm wanting to do is grab the 'total price' given on the confirmation page (HTML) and charge that amount to Stripe (using Node).

I currently have the tokenization working and the charge is successful when the amount is hardcoded, but I need the charge amount to change. Does anyone know if this is possible with Stripe (www.stripe.com)?

my app.js file (portion):

// charge route
app.post('/charge', (req, res) => {
  const amount = 2500; <-- needs to change to not be hardcoded

  stripe.customers.create({
    email: "random-email@gmail.com",
    source: req.body.mytoken
  })
  .then(customer =>  {
    stripe.charges.create({
    amount,
    description:'item desc',
    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}`);
});

UPDATE

I also want to update the users' email information from the input form rather than it being hardcoded like it currently is on this line: email: "random-email@gmail.com"

Second Update

Stripe form:

<div class="" style="margin-top: 60px;">
  <h2 class="quote-info">Estimated total&#58; $<span id="new_text"></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>

        <button>Submit Payment</button>
   </form>

Function found at the bottom of HTML page in a script tag:

function stripeTokenHandler(token) {
    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"
    });
    form.submit();
  }
mur7ay
  • 803
  • 3
  • 16
  • 44
  • Can you provide a little bit more context here? It's hard to know exactly how to provide an answer without knowing what you're actually doing or attempting. Please share some of your relevant code if you can. – Jonny Asmar Jan 18 '18 at 04:33
  • 1
    @jonnyAsmar I've updated my question with some relevant code. – mur7ay Jan 18 '18 at 04:35

2 Answers2

1

What you need to do is communicate from your front-end to your backend and tell the backend to make a stripe charge of a certain amount + certain email. The way to do this is by making a POST request to your node backend from the front end in javascript. Here is what you need to do:

  • setup a POST endpoint in your server code to receive the post request. Inside the post request you will receive the data indicating the amount to charge and the email and then execute the Strip charge through the code you were previously hardcoding. This guide shows and example of making a POST endpoint.
  • In your front-end, create a javascript method that runs when the submit button on your form is clicked. In that function, make a post request to the backend at the URL you made in your backend

This stack overflow answer gives a good quick example of sending data from the frontend to the backend with this method.

Rohan Varma
  • 1,145
  • 6
  • 11
1

You need to retrieve the POST data from the form in Express.


Method 1 (hidden input)

Path of least resistance based on your current implementation.

First, you need to make sure the total amount is passed from your form to the backend:

function stripeTokenHandler(token) {
  var form = document.getElementById('payment-form');

  var token = document.createElement('input');
  token.setAttribute('type', 'hidden');
  token.setAttribute('name', 'stripeToken');
  token.setAttribute('value', token.id);

  var totalAmount = document.createElement('input');
  token.setAttribute('type', 'hidden');
  token.setAttribute('name', 'totalAmount');
  token.setAttribute('value', $('#new_text').innerHTML);
  // or, prefereably, grab this directly from the var you're using to update the #new_text span's value

  form.appendChild(token);
  form.appendChild(totalAmount);

  // You could also just use the variables here (i.e. token.id) instead of grabbing it from the inputs generated above
  var formData = JSON.stringify({
    mytoken: token.value,
    totalAmount: totalAmount.value
  });

  // You're not actually referencing the form here, so you don't technically need to append the inputs above.
  // I've only included them for consistency. You're setting the values to be submitted to /charge when you set
  // the variable formData above and then passing it via the data property of $.ajax below.
  $.ajax({
    type: "POST",
    url: "/charge",
    data: formData,
    success: function(){alert("done")},
    dataType: "json",
    contentType: "application/json"
  });
  form.submit();
}

Then you should be able to do this:

app.post('/charge', (req, res) => {
  const amount = req.param('totalAmount');
  ...

Method 2 (named route param)

In this case, you wouldn't add a hidden input to your form, but instead you would update the action for your form to be something like:

action="/charge/TOTAL_AMOUNT/EMAIL"

And then modify your Express route to reference this value likeso:

app.get('/charge/:totalAmount/:email', (req, res) => {
    const amount = req.params.totalAmount;
    const email = req.params.email;
    ...

Scotch.io also has a great explanation of handling POST parameters in Express.

Community
  • 1
  • 1
Jonny Asmar
  • 1,900
  • 14
  • 16
  • Where did the TOKENIZED_TOTAL come from? – mur7ay Jan 20 '18 at 04:41
  • ooops, I'm sorry. i had originally misunderstood your scenario. edited that in one spot and not the other. that's just an example of how to use the route created beneath it. i've edited accordingly. – Jonny Asmar Jan 20 '18 at 21:47
  • Ok, I'm just focusing on getting the payment total to work first. So I started the server, localhost:5000 and inputted the card value Stripe provides. Upon submission, it reroutes and says 'Cannot POST /charge/TOTAL_AMOUNT. I'm fairly new to node and especially Stripe. – mur7ay Jan 20 '18 at 22:48
  • I've updated my question with more code to show my actual form and the function that contains an ajax request. I think I'm getting confused on the path. – mur7ay Jan 20 '18 at 22:56
  • 1
    To use a path like that, you need to change the way you're processing it on the backend (app.js). `TOTAL_AMOUNT` was just a placeholder I put there. In that case, it should actually be the value (i.e. `/charge/2500`). However, I think your path of least resistance here is to use posted data since you're already doing that. I will update my answer shortly with some more specific code for you now that you've provided the code you're using to submit from the front-end. – Jonny Asmar Jan 21 '18 at 09:10
  • 1
    Awesome! You're a lifesaver. – mur7ay Jan 21 '18 at 16:28
  • Glad to help! Please don't forget to accept the answer if it helped you :) – Jonny Asmar Jan 21 '18 at 21:08