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/free-solid-svg-icons": "^6.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/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -3395,6 +3397,24 @@
|
||||
"@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": {
|
||||
"version": "2.2.3",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"@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": {
|
||||
"version": "2.2.3",
|
||||
"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/free-solid-svg-icons": "^6.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/react": "^13.4.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 productTotal = (p) => {
|
||||
// return (p.quantity * (p.product.status == 3 || p.product.status == 4 ? p.product.promoPrice : p.product.price))
|
||||
// }
|
||||
|
||||
const getPriceHTML = (/*prods*/) => {
|
||||
|
||||
@ -19,9 +16,6 @@ export function TotalProductsPrice(/*{ products }*/) {
|
||||
var tvq = 0;
|
||||
var total;
|
||||
|
||||
// prods.map((p) => {
|
||||
// price += productTotal(p);
|
||||
// });
|
||||
|
||||
tps = price * (tpsRate / 100);
|
||||
tvq = price * (tvqRate / 100);
|
||||
|
@ -7,6 +7,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import Swal from "sweetalert2";
|
||||
import withReactContent from "sweetalert2-react-content";
|
||||
import { CartContext } from "../components/Cart";
|
||||
import StripeContainer from "../components/StripeContainer"
|
||||
|
||||
const ReviewInvoice = () => {
|
||||
|
||||
@ -28,26 +29,38 @@ const ReviewInvoice = () => {
|
||||
province: "",
|
||||
country: "",
|
||||
postalCode: "",
|
||||
prodQuant: []
|
||||
prodQuant: [],
|
||||
});
|
||||
|
||||
const [total, setTotal] = useState(-1);
|
||||
|
||||
useEffect(() => {
|
||||
const cookies = new Cookies();
|
||||
const thisInvoice = cookies.get('invoice');
|
||||
if (thisInvoice != null) {
|
||||
var dic = {};
|
||||
if (cart.items.length > 0) {
|
||||
cart.items.forEach((item) =>
|
||||
dic[item.id] = item.quantity
|
||||
cart.items.forEach((item) => {
|
||||
dic[item.id] = item.quantity;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async function test() {
|
||||
const tpsRate = 5;
|
||||
const tvqRate = 9.975;
|
||||
|
||||
const json = JSON.stringify(dic);
|
||||
console.log(await json);
|
||||
}
|
||||
test();
|
||||
var price = cart.getTotalCost();
|
||||
var tps = 0;
|
||||
var tvq = 0;
|
||||
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) => {
|
||||
@ -73,65 +86,12 @@ const ReviewInvoice = () => {
|
||||
}
|
||||
}, [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 = () => {
|
||||
navigate("/formulaire")
|
||||
}
|
||||
|
||||
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);
|
||||
console.log(json);
|
||||
|
||||
const response = await fetch(`https://localhost:7292/api/Invoice`, {
|
||||
method: 'POST',
|
||||
@ -167,69 +127,73 @@ const ReviewInvoice = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<h2 className="confirmer-infos">Veuillez confirmer les informations ci-dessous!</h2>
|
||||
<Col xs={6} md={4}>
|
||||
<>
|
||||
<Row>
|
||||
<h2 className="confirmer-infos">Veuillez confirmer les informations ci-dessous!</h2>
|
||||
<Col xs={6} md={4}>
|
||||
|
||||
<div className="review-invoice-info">
|
||||
<div>
|
||||
<label className="bold">Prénom: </label> <label>{thisInvoice.firstName}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Nom: </label> <label>{thisInvoice.lastName}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Téléphone: </label> <label>{thisInvoice.phoneNumber}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Courriel: </label> <label>{thisInvoice.emailAddress}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="review-invoice-address-container">
|
||||
<div>
|
||||
<label className="bold">Numéro civique: </label> <label>{thisInvoice.civicNumber}</label>
|
||||
</div>
|
||||
{thisInvoice.appartment != null ?
|
||||
<div className="review-invoice-info">
|
||||
<div>
|
||||
<label className="bold">Numéro d'appartement: </label> <label>{thisInvoice.appartment}</label>
|
||||
<label className="bold">Prénom: </label> <label>{thisInvoice.firstName}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Nom: </label> <label>{thisInvoice.lastName}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Téléphone: </label> <label>{thisInvoice.phoneNumber}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Courriel: </label> <label>{thisInvoice.emailAddress}</label>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<div>
|
||||
<label className="bold">Rue: </label> <label>{thisInvoice.street}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Ville: </label> <label>{thisInvoice.city}</label>
|
||||
|
||||
<div className="review-invoice-address-container">
|
||||
<div>
|
||||
<label className="bold">Numéro civique: </label> <label>{thisInvoice.civicNumber}</label>
|
||||
</div>
|
||||
{thisInvoice.appartment != null ?
|
||||
<div>
|
||||
<label className="bold">Numéro d'appartement: </label> <label>{thisInvoice.appartment}</label>
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<div>
|
||||
<label className="bold">Rue: </label> <label>{thisInvoice.street}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Ville: </label> <label>{thisInvoice.city}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Province (abréviation): </label> <label>{thisInvoice.province}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Pays: </label> <label>{thisInvoice.country}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Code postal: </label> <label>{thisInvoice.postalCode}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Province (abréviation): </label> <label>{thisInvoice.province}</label>
|
||||
<div className="review-invoice-info">
|
||||
<TotalProductsPrice
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Pays: </label> <label>{thisInvoice.country}</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="bold">Code postal: </label> <label>{thisInvoice.postalCode}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="review-invoice-info">
|
||||
<TotalProductsPrice
|
||||
/>
|
||||
</div>
|
||||
<Row className="invoice-buttons">
|
||||
{/* <Row className="invoice-buttons">
|
||||
<Col xs={6}>
|
||||
<Button className="invoice-button confirmer" onClick={handleConfirmer}>Confirmer</Button>
|
||||
</Col>
|
||||
<Col xs={6}>
|
||||
<Button className="invoice-button modifier" onClick={handleModify}>Modifier</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col xs={6} md={8}>
|
||||
<ReviewProdList
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</Row> */}
|
||||
</Col>
|
||||
<Col xs={6} md={8}>
|
||||
<ReviewProdList
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<StripeContainer cost={total} />
|
||||
</>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,44 @@ a {
|
||||
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 {
|
||||
background-color: beige;
|
||||
text-align: center;
|
||||
@ -770,7 +808,7 @@ a {
|
||||
|
||||
.invoice-item-products h3 {
|
||||
text-align: center !important;
|
||||
color:purple;
|
||||
color: purple;
|
||||
font-weight: bold;
|
||||
background-color: beige;
|
||||
width: auto;
|
||||
@ -831,12 +869,12 @@ a {
|
||||
}
|
||||
|
||||
.invoice-buttons {
|
||||
display:flex;
|
||||
margin:5%;
|
||||
display: flex;
|
||||
margin: 5%;
|
||||
}
|
||||
|
||||
.invoice-button {
|
||||
margin:2%;
|
||||
margin: 2%;
|
||||
width: 100%;
|
||||
align-content: center;
|
||||
}
|
||||
@ -851,7 +889,7 @@ a {
|
||||
|
||||
.confirmer-infos {
|
||||
text-align: center;
|
||||
color:white;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -861,6 +899,12 @@ a {
|
||||
/* -------------------------------------------------------- */
|
||||
@media(max-width:900px) {
|
||||
|
||||
.Payment-btn {
|
||||
margin-top: 10px;
|
||||
height: 70px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.invoice-item-container {
|
||||
display: block;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user