Reputation: 6186
I'm using MERN stack for an application with whom an user can create companies.
A company has multiple fields that the user must introduce: name, address, phone, email, etc and also information about the credit card like: credit card number (16 digits), expiration date (MM/YY) and CCV (XYZ).
The problem is that now all of this information is stored in the database which for sure it's not okay.
I'm using Formik for fields validation and the app has this structure:
React:
import React from 'react';
import { Redirect } from 'react-router-dom';
import { Formik, Form, Field } from 'formik';
import { Input, Button, Label, Grid } from 'semantic-ui-react';
import * as Yup from 'yup';
export default class CreateCompanyForm extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
name: '',
creditCardNumber: '',
creditCardDate: '',
creditCardCCV: '',
};
}
onChange = (e, { name, value }) => {
this.setState({ [name]: value });
};
handleSubmit = values => {
// creates the company
};
render() {
const { redirectCreate } = this.state;
if (redirectCreate) {
return <Redirect to="/companies" />;
}
const initialValues = {
name: '',
creditCardNumber: '',
creditCardDate: '',
creditCardCCV: '',
};
// Yup validation rules
const requiredErrorMessage = 'This field is required';
const validationSchema = Yup.object({
name: Yup.string().required(requiredErrorMessage),
creditCardNumber: Yup.string().required(requiredErrorMessage),
creditCardDate: Yup.string().required(requiredErrorMessage),
creditCardCCV: Yup.string().required(requiredErrorMessage),
});
return (
<>
<Button form="amazing">Create company</Button>
<Formik
htmlFor="amazing"
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={values => this.handleSubmit(values)}>
{({ errors, touched }) => (
<Form id="amazing">
<div>
<Grid columns={2}>
<Grid.Column>
<Label>Company name</Label>
<Field name="name" as={Input} />
<div className="add-fridge-error">
{touched.name && errors.name ? errors.name : null}
</div>
</Grid.Column>
</Grid>
<Grid.Column>
<Label>Credit card number</Label> // credit card number
<Field
name="creditCardNumber"
as={Input}
/>
<div>
{touched.creditCardNumber && errors.creditCardNumber
? errors.creditCardNumber
: null}
</div>
</Grid.Column>
<Grid.Column>
<Label>Date</Label> // expiration date
<Field name="creditCardDate" as={Input} placeholder="MM/YY" />
<div>
{touched.creditCardDate && errors.creditCardDate
? errors.creditCardDate
: null}
</div>
</Grid.Column>
<Grid.Column>
<Label>CCV</Label> // CCV information
<Field name="creditCardCCV" as={Input} />
<div>
{touched.creditCardCCV && errors.creditCardCCV
? errors.creditCardCCV
: null}
</div>
</Grid.Column>
</div>
</Form>
)}
</Formik>
</>
);
}
}
Node.js:
const { Company } = require('../models');
module.exports = {
create: (req, res) => {
if (!req.body) {
res.status(400).send({
message: 'Not enough information',
});
}
const {
name,
creditCardNumber,
creditCardDate,
creditCardCCV,
} = req.body.company;
const company = new Company({
name,
creditCardNumber,
creditCardDate,
creditCardCCV,
});
company
.save()
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({ message: err.message });
});
},
}
Mongoose model:
const { Schema } = mongoose;
const companySchema = new Schema(
{
name: {
type: String,
required: true,
},
creditCardNumber: {
type: String,
required: true,
},
creditCardDate: {
type: String,
required: true,
},
creditCardCCV: {
type: String,
required: true,
},
},
{ timestamps: true }
);
This code works for creatin a new company but it stores all the information in the database.
My question is if it's possible to add Stripe functionality over this approach in order to avoid storing the card information in the database? If yes, how should this be done?
Upvotes: 0
Views: 597
Reputation: 868
Stripe uses a tokenization process on the client-side that prevents credit card details from ever landing on your server.
You can create a Customer object via the Stripe API and a Payment Source for the Customer object.
For your implementation server-side, I'd recommend the official Stripe npm package.
Client-side, use react-stripe-checkout library.
Upvotes: 1