Payment



https://stripe.com/
https://www.npmjs.com/package/react-stripe-checkout
https://stripe.com/docs/api#create_charge
Payment Flow

Payment Flow




Client Side

Stripe Dialog
React -> Stripe
pending token from Stripe
React -> Node
Result
Payment Cmp
$npm install --save react-stripe-checkout
import React, { Component } from 'react';
import StripeCheckout from 'react-stripe-checkout';
import { connect } from 'react-redux';
import * as actions from '../actions';
class Payments extends Component {
render() {
return (
<StripeCheckout
name="Emaily"
description="$5 for 5 email credits"
amount={500}
token={token => this.props.handleToken(token)}
// token={token => console.log(token)}
stripeKey={process.env.REACT_APP_STRIPE_KEY}
>
<button className="btn">
Add Credits
</button>
</StripeCheckout>
);
}
}
export default connect(null, actions)(Payments);
callback hanlde
Action
import axios from 'axios';
import { FETCH_USER } from './types';
export const handleToken = token => async dispatch => {
const res = await axios.post('/api/stripe', token);
dispatch({ type: FETCH_USER, payload: res.data });
};
action
export const FETCH_USER = 'fetch_user';
type.js
Header Cmp
import Payments from './Payments';
class Header extends Component {
renderContent() {
switch (this.props.auth) {
case null:
return;
case false:
return <li><a href="/auth/google">Login With Google</a></li>;
default:
return [
<li key="1"><Payments /></li>,
<li key="2" style={{ margin: '0 10px' }}>
Credits: {this.props.auth.credits}
</li>,
<li key="3"><a href="/api/logout">Logout</a></li>
];
}
}
render() {
return (
<nav>
<div className="nav-wrapper">
<ul className="right">
{this.renderContent()}
</ul>
</div>
</nav>
)
}
}
const mapStateToProps = ({ auth }) => {return { auth }}
export default connect(mapStateToProps)(Header)
Login
Server Side
1. pay post(with pending token)
2. send to Stripe
3. callback -> add credit to User
check: if User is login
Handle Payment
Do sth..
$npm install --save stripe
$npm install --save body-parser
const mongoose = require('mongoose');
const { Schema } = mongoose;
const userSchmea = new Schema({
googleId: String,
credits: { type: Number, default: 0 }
})
mongoose.model('users', userSchmea);
app.use(bodyParser.json());
module.exports = (req, res, next) => {
if (!req.user) {
return res.status(401).send({ error: 'You must log in!' });
}
next();
};
User Model
index.js
Middleware(requireLogin.js)
Handle Payment
const keys = require('../config/key');
const stripe = require('stripe')(keys.stripeSecretKey);
const requireLogin = require('../middlewares/requireLogin');
module.exports = app => {
app.post('/api/stripe', requireLogin, async (req, res) => {
const charge = await stripe.charges.create({
amount: 500,
currency: 'usd',
description: '$5 for 5 credits',
source: req.body.id
});
req.user.credits += 5;
const user = await req.user.save();
res.send(user);
});
};
Pending Token
require('./routes/billngRoutes')(app);
Deployment Note

if (process.env.NODE_ENV === 'production') {
// Express will serve up production assets
// like our main.js file, or main.css file!
app.use(express.static('client/build'));
// Express will serve up the index.html file
// if it doesn't recognize the route
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
Deployment Note
"scripts": {
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client
&& npm run build --prefix client"
}
Payment Flow X React X Node X Mongo
By Matt Jhou
Payment Flow X React X Node X Mongo
- 301