0

I am building React/Node/Stripe app, basic setup works fine but when i want to extend my app to collect email address from input form and sent it in body to node backend to use it to create customer or send email. I see in console.log that in req.body email is present but i can fetch this field.

React

email is collected

 import React, { Component } from "react";
import { CardElement, injectStripe } from "react-stripe-elements";
import styled from "styled-components";






    class CheckoutForm extends Component {
      constructor(props) {
        super(props);
        this.state = {
          complete: false,
          name: "",
          email: ""
        };
      }
      handleChange = input => e => {
        this.setState({
          [input]: e.target.value
        });
        console.log(this.state.email);
      };
   submit = async () => {
    let { token } = await this.props.stripe.createToken({
      name: this.state.name,
      email: this.state.email
    });
    console.log(token);
    const email = this.state.email;
    const data = {
      token: token.id,
      email
    };
    let response = await fetch("/charge", {
      method: "POST",
      headers: {
        "Content-Type": "text/plain"
      },
      body: JSON.stringify(data)
    });
    console.log(response);
    if (response.ok)
      this.setState({
        complete: true
      });
  };;

      render() {
        if (this.state.complete) return <h1> Purchase Complete </h1>;
        return (
          <CheckOut>
            <CheckOutForm>
              <CheckOutFieldSet>
                <InputRow>
                  <Label htmlFor=""> Name </Label>
                  <Input
                    type="text"
                    placeholder="Jane Doe"
                    onChange={this.handleChange("name")}
                  />
                </InputRow>
                <InputRow>
                  <Label htmlFor=""> Email </Label>
                  <Input
                    type="email"
                    placeholder="jane@doe.com"
                    onChange={this.handleChange("email")}
                  />
                </InputRow>
                <InputRow last>
                  <Label htmlFor=""> Phone </Label>
                  <Input type="phone" placeholder="+48 999 000 999" />
                </InputRow>
              </CheckOutFieldSet>
              <CheckOutFieldSet>
                <CardElement />
              </CheckOutFieldSet>
            </CheckOutForm>
            <ButtonCheckOut onClick={this.submit}> Send </ButtonCheckOut>
          </CheckOut>
        );
      }
    }

    export default injectStripe(CheckoutForm);

Response email is present but name is in card object

card: {id: "card_1", object: "card", 
address_city: null, 
address_country: null, 
address_line1: null, …}
created: 1546375333
email: "emial"
id: "tok_1Dnu4wj"
livemode: false
object: "token"
type: "card"
used: false
__proto__: Objec

Name

card:{
    last4: "4242"
    metadata: {}
    name: "Name"
}

BACKEND

app.post("/charge", (req, res) => {
console.log(req.body)
//{"token":"tok_1DnuwhFw7kwjoel1NsD2Qd1r","email":"lll"}
stripe.charges.create({
    amount: 4000,
    currency: "usd",
    description: req.body.email,
    source: req.body.token
}).then(
    status => {
        res.json({
            status
        })
        // isValid = status.ok

    }
).catch(err => res.send(err))

let mail = req.body.email
console.log(mail)
//undefined

I know that console.log(req.body) will give me token id but how to send more stuff like email address? One more? how it is possible that name i just collected on createToken? I is included in token?

regards

Exc
  • 1,473
  • 3
  • 15
  • 30
  • What do you mean by "Sending more stuff like email or address" ? Do you want to send not only the token id in fetch request body `body: token.id` ? – nook Jan 01 '19 at 20:55
  • yes i want to send more data – Exc Jan 01 '19 at 20:59
  • Then you might want to serialize your data. As someone answered below, there is a function `JSON.stringify(data)` which allows you to do that. – nook Jan 01 '19 at 21:01
  • please take a look i edited my questiiion in fetch section and back end to log data. I am getting undefined – Exc Jan 01 '19 at 21:08
  • You've set `'Content-Type': 'text/plain'`. It needs to be `'application/json'`. I've also edited my answer. – Ionut Achim Jan 01 '19 at 21:22
  • UnhandledPromiseRejectionWarning: Error: Can't set headers after they are sent. – Exc Jan 01 '19 at 21:31
  • please take a look at backend i edited this to reflect what i get – Exc Jan 01 '19 at 21:43
  • Maybe this could help https://stackoverflow.com/questions/5710358/how-to-retrieve-post-query-parameters Are you using bodyParser ? – Kevin Coulibaly Jan 02 '19 at 00:22

1 Answers1

3

You can send an object in body, just use body: JSON.stringify(data). Data can contain anything serializable.

Also, make sure you have 'Content-Type': 'application/json' in your request headers

As pointed out by @Dez, make sure your server is able to parse incoming requests with JSON payloads. With express you may use the body-parser middleware.

Ionut Achim
  • 937
  • 5
  • 10
  • UnhandledPromiseRejectionWarning: Error: Can't set headers after they are sent. – Exc Jan 01 '19 at 21:31
  • please take a look at backend i edited this to reflect what i get – Exc Jan 01 '19 at 21:43
  • 2
    Besides what you already pointed out, the OP should have set in the Node server this line: `app.use(bodyParser.json());` to be able to take JSON data requests. – Dez Jan 01 '19 at 22:22
  • @Damian, not sure why you are getting that error, your 'BACKEND' snippet doesn't show enough. I would suggest you take a look [here](https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client), see if that helps, or provide some more context. – Ionut Achim Jan 01 '19 at 23:57
  • it was bodyParser, but I am thinking why Stripe snippet has not json but text as bodyParser – Exc Jan 02 '19 at 21:49