Reputation: 2127
I am attempting to save credit card information using stripe and react with a node backend. I am using the react-stripe-js
library since that is recommended to securely send PII data. I have set up a basic node api that creates a customer and now I want to setup Intents
since according to stripe docs that's the best way to save card data for later use. But I am unsure how to send the inputs to the api. How could I modify the code below to setup an intent?
node.js
...
//CREATE CUSTOMER ACCOUNT
app.post("/makeCustomer", cors(), async (req, res) => {
let data = {
name: req.body.name,
email: req.body.email
};
try {
const customer = await stripe.customers.create({
name: data.name,
email: data.email
});
res.send(customer);
} catch (error) {
console.log(err);
res.status(400)
res.send({ error: err })
return;
}
});
//CREATE SETUP INTENT
app.post("/makeIntent", cors(), async (req, res) => {
try {
const intent = await stripe.setupIntents.create({
payment_method_types: ['card'],
customer: customer.id
});
res.send(intent.client_secret );
} catch (err) {
console.log(err);
res.status(400)
res.send({ error: err })
return;
}
});
Buyer.js
import React, { Component } from 'react';
import { Button, Container, Col, Row, Tabs, Tab, Form } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
//import StripeCheckout from "react-stripe-checkout";
import { Elements, ElementsConsumer } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import SaveCardForm from './SaveCardForm';
const stripePromise = loadStripe('pk_test_51HhkvNBmZZhLkiuRzN5UwsSHQQbK9y1CALJpr3l23aT7bauIx1JzCdkKlVx26FrtFkFE8QtAUZctcuUtBhRxcqti00grkBypzH');
const InjectedSaveCardForm = () => (
<ElementsConsumer>
{({ stripe, elements }) => (
<SaveCardForm stripe={stripe} elements={elements} />
)}
</ElementsConsumer>
);
class Buyer extends Component {
constructor() {
super();
this.state = {
customerId: 'cus_INAnHdJRHAFgnG'
}
}
render() {
return (
<Container>
<h5 style={{ textAlign: 'center' }}>
As a buyer, place your information below and purchase your meal.
</h5>
<Tabs
id="controlled-tab-example"
>
<Tab eventKey="creditCart" title="Credit Card">
<br />
<h5>Enter card details below:</h5>
<br />
<Row>
<Col>
<Button onClick={this.props.makeCustomer}>
Create Customer
</Button>
</Col>
<Col>
<Button onClick={this.props.deleteCustomer}>
Delete Customer
</Button>
</Col>
<Col></Col>
</Row>
<br/>
<Row>
{/**SAVE CARD HERE */}
<Col>
<Elements stripe={stripePromise}>
<InjectedSaveCardForm />
</Elements>
</Col>
</Row>
</Tab>
<Tab eventKey="ApplePay" title="Apple Pay">
bye
</Tab>
<Tab eventKey="AndroidPay" title="Android Pay">
sup
</Tab>
</Tabs>
</Container>
);
}
}
export default Buyer;
SaveCardForm.js
import React, { Component } from "react";
import { Stripe, CardElement, injectStripe, Elements, ElementsConsumer } from "@stripe/react-stripe-js";
import {loadStripe} from '@stripe/stripe-js';
class SaveCardForm extends Component {
handleSubmit = async (event) => {
event.preventDefault();
const {stripe, elements} = this.props;
const {error, paymentMethod} = await stripe.createPaymentMethod({
type: 'card',
card: elements.getElement(CardElement),
});
};
render() {
const {stripe} = this.props;
return (
<form onSubmit={this.handleSubmit}>
<CardElement />
<button type="submit" disabled={!stripe}>
Save Card Data
</button>
</form>
);
}
}
export default SaveCardForm;
Upvotes: 3
Views: 7190
Reputation: 3361
I'm not a React expert but it looks like you're calling createPaymentMethod()
from Stripe.js here, which isn't what you need to do.
Instead, on handleSubmit()
you need to call confirmCardSetup()
, and pass in 2 things:
card
Elementas shown here: https://stripe.com/docs/payments/save-and-reuse#confirm-the-setupintent
If the SetupIntent was created with a Customer specified (which yours is), then on successful confirmation of the SetupIntent, the newly tokenized card PaymentMethod will auto-attach to that Customer.
Upvotes: 2