Front-end pour Stripe
This commit is contained in:
parent
5d64c7d8ca
commit
5ece2baea9
@ -11,6 +11,8 @@
|
|||||||
"@fortawesome/fontawesome-svg-core": "^6.2.0",
|
"@fortawesome/fontawesome-svg-core": "^6.2.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
|
"@stripe/react-stripe-js": "^1.15.0",
|
||||||
|
"@stripe/stripe-js": "^1.44.1",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
@ -3395,6 +3397,24 @@
|
|||||||
"@sinonjs/commons": "^1.7.0"
|
"@sinonjs/commons": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@stripe/react-stripe-js": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-nqIOuAbbAN1p/zj2d2vykMzd097ZiHbu0+EpPRcfiswBRQIQIZaPrUwmj6HGD8BRA6Wp89mZen1UJbqtsfc3ZA==",
|
||||||
|
"dependencies": {
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@stripe/stripe-js": "^1.44.1",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@stripe/stripe-js": {
|
||||||
|
"version": "1.44.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.44.1.tgz",
|
||||||
|
"integrity": "sha512-DKj3U6tS+sCNsSXsoZbOl5gDrAVD3cAZ9QCiVSykLC3iJo085kkmw/3BAACRH54Bq2bN34yySuH6G1SLh2xHXA=="
|
||||||
|
},
|
||||||
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
"node_modules/@surma/rollup-plugin-off-main-thread": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||||
@ -21007,6 +21027,19 @@
|
|||||||
"@sinonjs/commons": "^1.7.0"
|
"@sinonjs/commons": "^1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@stripe/react-stripe-js": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-nqIOuAbbAN1p/zj2d2vykMzd097ZiHbu0+EpPRcfiswBRQIQIZaPrUwmj6HGD8BRA6Wp89mZen1UJbqtsfc3ZA==",
|
||||||
|
"requires": {
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@stripe/stripe-js": {
|
||||||
|
"version": "1.44.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.44.1.tgz",
|
||||||
|
"integrity": "sha512-DKj3U6tS+sCNsSXsoZbOl5gDrAVD3cAZ9QCiVSykLC3iJo085kkmw/3BAACRH54Bq2bN34yySuH6G1SLh2xHXA=="
|
||||||
|
},
|
||||||
"@surma/rollup-plugin-off-main-thread": {
|
"@surma/rollup-plugin-off-main-thread": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
"@fortawesome/fontawesome-svg-core": "^6.2.0",
|
"@fortawesome/fontawesome-svg-core": "^6.2.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
|
"@stripe/react-stripe-js": "^1.15.0",
|
||||||
|
"@stripe/stripe-js": "^1.44.1",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
import React, { useState } from "react"
|
||||||
|
import { CardElement, useElements, useStripe } from "@stripe/react-stripe-js"
|
||||||
|
import { Button } from "react-bootstrap"
|
||||||
|
|
||||||
|
const CARD_OPTIONS = {
|
||||||
|
iconStyle: "solid",
|
||||||
|
style: {
|
||||||
|
base: {
|
||||||
|
iconColor: "black",
|
||||||
|
color: "white",
|
||||||
|
fontWeight: 500,
|
||||||
|
fontFamily: "Roboto, Open Sans, Segoe UI, sans-serif",
|
||||||
|
fontSize: "16px",
|
||||||
|
fontSmoothing: "antialiased",
|
||||||
|
":-webkit-autofill": { color: "beige" },
|
||||||
|
"::placeholder": { color: "lightgray" }
|
||||||
|
},
|
||||||
|
invalid: {
|
||||||
|
iconColor: "red",
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PaymentForm = ({ cost }) => {
|
||||||
|
|
||||||
|
const [success, setSuccess] = useState(false);
|
||||||
|
const stripe = useStripe();
|
||||||
|
const elements = useElements();
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const { error, paymentMethod } = await stripe.createPaymentMethod({
|
||||||
|
type: "card",
|
||||||
|
card: elements.getElement(CardElement)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (cost <= 0) {
|
||||||
|
console.log("Coût invalide: ", cost);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
const { id } = paymentMethod;
|
||||||
|
|
||||||
|
const json = JSON.stringify({ amount: cost, stripeId: id });
|
||||||
|
|
||||||
|
|
||||||
|
fetch(`https://localhost:7292/api/Payment`, {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'include',
|
||||||
|
mode: 'cors',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: json
|
||||||
|
}).then((response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
console.log("Successful payment");
|
||||||
|
setSuccess(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log("Error: ", error);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{!success ?
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<fieldset className="FormGroup">
|
||||||
|
<div className="FormRow">
|
||||||
|
<CardElement options={CARD_OPTIONS} />
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div className="Payment-btn-container">
|
||||||
|
<Button className="Payment-btn" type="submit">Payer</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
:
|
||||||
|
<div>
|
||||||
|
<h2>
|
||||||
|
L'achat s'est déroulé avec succès
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaymentForm;
|
@ -0,0 +1,19 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { loadStripe } from "@stripe/stripe-js"
|
||||||
|
import { Elements } from "@stripe/react-stripe-js"
|
||||||
|
import PaymentForm from "./PaymentForm";
|
||||||
|
|
||||||
|
const PUBLIC_KEY = "pk_test_51M8mzOEerenEZcQIUmJIrmsaZeeNlOil2G1JcMvvO68w50MJr8rDwUjVO44a8dDhSlsRH4GdzH9rDqtkg4Rtbzco00NqkHdn3H";
|
||||||
|
|
||||||
|
const stripeTestPromise = loadStripe(PUBLIC_KEY);
|
||||||
|
|
||||||
|
const StripeContainer = ({cost}) => {
|
||||||
|
return (
|
||||||
|
<Elements stripe={stripeTestPromise}>
|
||||||
|
<PaymentForm cost={cost}/>
|
||||||
|
</Elements>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default StripeContainer;
|
@ -5,9 +5,6 @@ export function TotalProductsPrice(/*{ products }*/) {
|
|||||||
|
|
||||||
const cart = useContext(CartContext);
|
const cart = useContext(CartContext);
|
||||||
|
|
||||||
// const productTotal = (p) => {
|
|
||||||
// return (p.quantity * (p.product.status == 3 || p.product.status == 4 ? p.product.promoPrice : p.product.price))
|
|
||||||
// }
|
|
||||||
|
|
||||||
const getPriceHTML = (/*prods*/) => {
|
const getPriceHTML = (/*prods*/) => {
|
||||||
|
|
||||||
@ -19,9 +16,6 @@ export function TotalProductsPrice(/*{ products }*/) {
|
|||||||
var tvq = 0;
|
var tvq = 0;
|
||||||
var total;
|
var total;
|
||||||
|
|
||||||
// prods.map((p) => {
|
|
||||||
// price += productTotal(p);
|
|
||||||
// });
|
|
||||||
|
|
||||||
tps = price * (tpsRate / 100);
|
tps = price * (tpsRate / 100);
|
||||||
tvq = price * (tvqRate / 100);
|
tvq = price * (tvqRate / 100);
|
||||||
|
@ -7,6 +7,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { CartContext } from "../components/Cart";
|
import { CartContext } from "../components/Cart";
|
||||||
|
import StripeContainer from "../components/StripeContainer"
|
||||||
|
|
||||||
const ReviewInvoice = () => {
|
const ReviewInvoice = () => {
|
||||||
|
|
||||||
@ -28,26 +29,38 @@ const ReviewInvoice = () => {
|
|||||||
province: "",
|
province: "",
|
||||||
country: "",
|
country: "",
|
||||||
postalCode: "",
|
postalCode: "",
|
||||||
prodQuant: []
|
prodQuant: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [total, setTotal] = useState(-1);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const cookies = new Cookies();
|
const cookies = new Cookies();
|
||||||
const thisInvoice = cookies.get('invoice');
|
const thisInvoice = cookies.get('invoice');
|
||||||
if (thisInvoice != null) {
|
if (thisInvoice != null) {
|
||||||
var dic = {};
|
var dic = {};
|
||||||
if (cart.items.length > 0) {
|
if (cart.items.length > 0) {
|
||||||
cart.items.forEach((item) =>
|
cart.items.forEach((item) => {
|
||||||
dic[item.id] = item.quantity
|
dic[item.id] = item.quantity;
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function test() {
|
const tpsRate = 5;
|
||||||
|
const tvqRate = 9.975;
|
||||||
|
|
||||||
const json = JSON.stringify(dic);
|
var price = cart.getTotalCost();
|
||||||
console.log(await json);
|
var tps = 0;
|
||||||
}
|
var tvq = 0;
|
||||||
test();
|
var totalCost;
|
||||||
|
|
||||||
|
tps = price * (tpsRate / 100);
|
||||||
|
tvq = price * (tvqRate / 100);
|
||||||
|
totalCost = price + tps + tvq;
|
||||||
|
totalCost = totalCost * 100;
|
||||||
|
totalCost = totalCost.toFixed(0);
|
||||||
|
|
||||||
|
setTotal(totalCost);
|
||||||
|
|
||||||
|
|
||||||
setThisInvoice((e) => {
|
setThisInvoice((e) => {
|
||||||
@ -73,65 +86,12 @@ const ReviewInvoice = () => {
|
|||||||
}
|
}
|
||||||
}, [cart]);
|
}, [cart]);
|
||||||
|
|
||||||
|
|
||||||
// const handleAddOne = (id) => {
|
|
||||||
|
|
||||||
// var modifiedPQ = prodQuant.filter((pq) => pq.id == id);
|
|
||||||
// var modifiedProd = prodQuant.filter((pq) => pq.product.id == id);
|
|
||||||
|
|
||||||
// modifiedPQ.quantity++;
|
|
||||||
// modifiedProd.quantity = modifiedPQ.quantity;
|
|
||||||
|
|
||||||
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id)), { ...modifiedPQ }].sort((a, b) => a.id - b.id));
|
|
||||||
// setProducts([...(products.filter((pq) => pq.product.id !== id)), { ...modifiedProd }].sort((a, b) => a.product.id - b.product.id));
|
|
||||||
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const handleRemoveOne = (id) => {
|
|
||||||
// var modifiedPQ = prodQuant.filter((pq) => pq.id == id);
|
|
||||||
// var modifiedProd = prodQuant.filter((pq) => pq.product.id == id);
|
|
||||||
|
|
||||||
// if (modifiedPQ.quantity - 1 <= 0) {
|
|
||||||
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id))].sort((a, b) => a.id - b.id));
|
|
||||||
// setProducts([...(products.filter((pq) => pq.product.id !== id))].sort((a, b) => a.product.id - b.product.id));
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// modifiedPQ.quantity--;
|
|
||||||
// modifiedProd.quantity = modifiedPQ.quantity;
|
|
||||||
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id)), { ...modifiedPQ }].sort((a, b) => a.id - b.id));
|
|
||||||
// setProducts([...(products.filter((pq) => pq.product.id !== id)), { ...modifiedProd }].sort((a, b) => a.product.id - b.product.id));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const handleRemoveProduct = (id) => {
|
|
||||||
|
|
||||||
// setProdQuant([...(prodQuant.filter((pq) => pq.id !== id))].sort((a, b) => a.id - b.id));
|
|
||||||
// setProducts([...(products.filter((pq) => pq.product.id !== id))].sort((a, b) => a.product.id - b.product.id));
|
|
||||||
// }
|
|
||||||
|
|
||||||
const handleModify = () => {
|
const handleModify = () => {
|
||||||
navigate("/formulaire")
|
navigate("/formulaire")
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleConfirmer = async () => {
|
const handleConfirmer = async () => {
|
||||||
|
|
||||||
// var dic = {};
|
|
||||||
// if (cart.items.length > 0) {
|
|
||||||
// cart.items.forEach((item) =>
|
|
||||||
// dic[item.id] = item.quantity
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// const json = JSON.stringify(dic);
|
|
||||||
// console.log(await json);
|
|
||||||
|
|
||||||
// const json1 = JSON.stringify(cart.items);
|
|
||||||
// console.log(await json1);
|
|
||||||
|
|
||||||
//setThisInvoice({ ...thisInvoice, prodQuant: dic });
|
|
||||||
|
|
||||||
const json = JSON.stringify(thisInvoice);
|
const json = JSON.stringify(thisInvoice);
|
||||||
console.log(json);
|
|
||||||
|
|
||||||
const response = await fetch(`https://localhost:7292/api/Invoice`, {
|
const response = await fetch(`https://localhost:7292/api/Invoice`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -167,6 +127,7 @@ const ReviewInvoice = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<Row>
|
<Row>
|
||||||
<h2 className="confirmer-infos">Veuillez confirmer les informations ci-dessous!</h2>
|
<h2 className="confirmer-infos">Veuillez confirmer les informations ci-dessous!</h2>
|
||||||
<Col xs={6} md={4}>
|
<Col xs={6} md={4}>
|
||||||
@ -216,20 +177,23 @@ const ReviewInvoice = () => {
|
|||||||
<TotalProductsPrice
|
<TotalProductsPrice
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Row className="invoice-buttons">
|
{/* <Row className="invoice-buttons">
|
||||||
<Col xs={6}>
|
<Col xs={6}>
|
||||||
<Button className="invoice-button confirmer" onClick={handleConfirmer}>Confirmer</Button>
|
<Button className="invoice-button confirmer" onClick={handleConfirmer}>Confirmer</Button>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={6}>
|
<Col xs={6}>
|
||||||
<Button className="invoice-button modifier" onClick={handleModify}>Modifier</Button>
|
<Button className="invoice-button modifier" onClick={handleModify}>Modifier</Button>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row> */}
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={6} md={8}>
|
<Col xs={6} md={8}>
|
||||||
<ReviewProdList
|
<ReviewProdList
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
<StripeContainer cost={total} />
|
||||||
|
</>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,44 @@ a {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Payment-btn-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Payment-btn {
|
||||||
|
margin: auto;
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FormGroup {
|
||||||
|
margin: 20px 15px 20px;
|
||||||
|
padding: 0;
|
||||||
|
border-style: none;
|
||||||
|
color: beige !important;
|
||||||
|
background-color: purple;
|
||||||
|
will-change: opacity, transform;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.FormRow {
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StripeElement--webkit-autofill {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.StripeElement {
|
||||||
|
width: 100%;
|
||||||
|
padding: 11px 15px 11px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.Contact {
|
.Contact {
|
||||||
background-color: beige;
|
background-color: beige;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -861,6 +899,12 @@ a {
|
|||||||
/* -------------------------------------------------------- */
|
/* -------------------------------------------------------- */
|
||||||
@media(max-width:900px) {
|
@media(max-width:900px) {
|
||||||
|
|
||||||
|
.Payment-btn {
|
||||||
|
margin-top: 10px;
|
||||||
|
height: 70px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
.invoice-item-container {
|
.invoice-item-container {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user