Skip to content

Commit

Permalink
Implemented cart transaction to braintree
Browse files Browse the repository at this point in the history
  • Loading branch information
EunsooJung committed Feb 21, 2020
1 parent 2682698 commit 7b12759
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"antd": "^3.26.9",
"braintree-web-drop-in-react": "^1.1.0",
"dotenv": "^8.2.0",
"moment": "^2.24.0",
"query-string": "^6.11.0",
Expand Down
2 changes: 1 addition & 1 deletion src/components/cart/CartLanding.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const CartLanding = () => {
<div>
<h2>
<Icon type='shopping' theme='twoTone' twoToneColor='#eb2f96' /> Your
cart has {`${items.length}`} Items
cart has {`${items.length}`} items
</h2>
<hr />
{items.map((product, i) => (
Expand Down
142 changes: 136 additions & 6 deletions src/components/cart/CheckoutProductInCart.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,54 @@

import React, { useState, useEffect } from 'react';
import Layout from '../Layout';
import { Component } from '../salesApi';
import {
getProducts,
getBraintreeClientToken,
processPayment
} from '../salesApi';
import Card from '../CardForProduct';
import { isAuthenticated } from '../../auth/';
import { Link } from 'react-router-dom';

import DropIn from 'braintree-web-drop-in-react';
/**
*
* @param {*} {products}
* @applied User authenctication
* @usedIn components/cart/CheckoutProductInCart.js
*/
const CheckoutProductInCart = ({ products }) => {
const CheckoutProductInCart = ({
products,
setRun = f => f,
run = undefined
}) => {
const [data, setData] = useState({
loading: false,
success: false,
clientToken: null,
error: '',
instance: {},
address: ''
});

const userId = isAuthenticated() && isAuthenticated().user._id;
const token = isAuthenticated() && isAuthenticated().token;

const getToken = (userId, token) => {
getBraintreeClientToken(userId, token).then(data => {
if (data.error) {
console.log(data.error);
setData({ ...data, error: data.error });
} else {
console.log(data);
setData({ clientToken: data.clientToken });
}
});
};

useEffect(() => {
getToken(userId, token);
}, []);

// return <div>{JSON.stringify(products)}</div>;
const getTotalItemsCountinCart = () => {
return products.reduce((currentValue, nextValue) => {
Expand All @@ -26,17 +62,111 @@ const CheckoutProductInCart = ({ products }) => {

const displayCheckoutInCart = () => {
return isAuthenticated() ? (
<buttton className='btn btn-success'>Checkout</buttton>
<div>{showDropIn()}</div>
) : (
<Link to='/signin'>
<button className='btn btn-primary'>Sign in to Checkout</button>
<button className='btn btn-primary'>Sign in to checkout</button>
</Link>
);
};

let deliveryAddress = data.address;

const buy = () => {
setData({ loading: true });
// send the nonce to your server
// nonce = data.instance.requestPaymentMethod()
let nonce;
let getNonce = data.instance
.requestPaymentMethod()
.then(data => {
// console.log(data);
nonce = data.nonce;
// once you have nonce (card type, card number) send nonce as 'paymentMethodNonce'
// and also total to be charged
// console.log(
// "send nonce and total to process: ",
// nonce,
// getTotalItemsCountinCart(products)
// );
const paymentData = {
paymentMethodNonce: nonce,
amount: getTotalItemsCountinCart(products)
};

processPayment(userId, token, paymentData)
.then(response => {
setData({ ...data, success: response.success });
//console.log(response))
// empty cart
// create order
})
.catch(error => console.log(error));
})
.catch(error => {
console.log('dropin error: ', error);
setData({ ...data, error: error.message });
});
};

const showDropIn = () => (
<div onBlur={() => setData({ ...data, error: '' })}>
{data.clientToken !== null && products.length > 0 ? (
<div>
<div className='gorm-group mb-3'>
<label className='text-muted'>Delivery address:</label>
<textarea
//onChange={handleAddress}
className='form-control'
value={data.address}
placeholder='Type your delivery address here...'
/>
</div>

<DropIn
options={{
authorization: data.clientToken,
paypal: {
flow: 'vault'
}
}}
onInstance={instance => (data.instance = instance)}
/>
<button onClick={buy} className='btn btn-success btn-block'>
Pay
</button>
</div>
) : null}
</div>
);

const showError = error => (
<div
className='alert alert-danger'
style={{ display: error ? '' : 'none' }}
>
{error}
</div>
);

const showSuccess = success => (
<div
className='alert alert-info'
style={{ display: success ? '' : 'none' }}
>
Your payment was successful!
</div>
);

const showLoading = loading =>
loading && <h2 className='text-danger'>Loading...</h2>;

return (
<div>
<h2>Total items in Cart: ${getTotalItemsCountinCart()}</h2>
<h2> Total payment: ${getTotalItemsCountinCart()}</h2>
{showLoading(data.loading)}
{showSuccess(data.success)}
{showError(data.error)}
{displayCheckoutInCart()}
</div>
);
Expand Down
44 changes: 44 additions & 0 deletions src/components/salesApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,47 @@ export const listRelated = productId => {
})
.catch(err => console.log(err));
};

/**
*
* @param {*} userId
* @param {*} token
* @requestTo router.get('/braintree/getToken/:userId', requireSignin, isAuth, generateToken); back-end
* @usedIn components/cart/CheckoutProductInCart.js
*/
export const getBraintreeClientToken = (userId, token) => {
return fetch(`${API}/braintree/getToken/${userId}`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};

/**
*
* @param {*} userId
* @param {*} token
* @param {*} paymentData
*/
export const processPayment = (userId, token, paymentData) => {
return fetch(`${API}/braintree/payment/${userId}`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
},
body: JSON.stringify(paymentData)
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};
Loading

0 comments on commit 7b12759

Please sign in to comment.