首页 > 解决方案 > 在 MERN 堆栈中使用 Stripe 存储信用卡号

问题描述

我将 MERN 堆栈用于用户可以创建公司的应用程序。

一家公司有多个用户必须输入的字段:姓名、地址、电话、电子邮件等,以及有关信用卡的信息,例如:信用卡号(16 位)、到期日期(MM/YY)和 CCV(XYZ)。

问题是现在所有这些信息都存储在数据库中,这肯定是不行的。

我正在使用 Formik 进行字段验证,并且该应用程序具有以下结构:

反应:

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>
      </>
    );
  }
}

节点.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 });
      });
  },

}

猫鼬型号:

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 }
);

此代码适用于创建一家新公司,但它将所有信息存储在数据库中。

我的问题是是否可以通过这种方法添加 Stripe 功能以避免将卡信息存储在数据库中?如果是,应该怎么做?

标签: javascriptnode.jsreactjsmongoosestripe-payments

解决方案


Stripe 在客户端使用令牌化过程,以防止信用卡详细信息登陆您的服务器。

您可以通过 Stripe API 和 Customer 对象的 Payment Source创建一个Customer对象。

对于您的服务器端实现,我推荐使用官方Stripe npm package

客户端,使用react-stripe-checkout库。


推荐阅读