This commit is contained in:
Parpaillax
2024-04-30 13:18:38 +02:00
11 changed files with 331 additions and 99 deletions

View File

@@ -0,0 +1,8 @@
package fr.eni.enchere.bll;
import fr.eni.enchere.bo.Bank;
public interface BankService {
Bank isValideCart(String cartNumber, String cartExpired, int cartCVV);
void setCredit(Bank bank, float ammount);
}

View File

@@ -0,0 +1,25 @@
package fr.eni.enchere.bll;
import fr.eni.enchere.bo.Bank;
import fr.eni.enchere.dal.BankRepository;
import org.springframework.stereotype.Service;
@Service
public class BankServiceImpl implements BankService {
private BankRepository bankRepository;
public BankServiceImpl(BankRepository bankRepository) {
this.bankRepository = bankRepository;
}
@Override
public Bank isValideCart(String cartNumber, String cartExpired, int cartCVV) {
return bankRepository.verifCart(cartNumber, cartExpired, cartCVV);
}
@Override
public void setCredit(Bank bank, float ammount) {
bankRepository.editAmmountCart(bank, ammount);
}
}

View File

@@ -0,0 +1,71 @@
package fr.eni.enchere.bo;
public class Bank {
private int id;
private String cartNumber;
private String cartExpired;
private int cartCVV;
private String cartName;
private float cartAmount;
public Bank(){}
public Bank(int id, String cartNumber, String cartExpired, int cartCVV, String cartName, float cartAmount) {
setId(id);
setCartNumber(cartNumber);
setCartExpired(cartExpired);
setCartCVV(cartCVV);
setCartName(cartName);
setCartAmount(cartAmount);
}
public float getCartAmount() {
return cartAmount;
}
public void setCartAmount(float cartAmount) {
this.cartAmount = cartAmount;
}
public String getCartName() {
return cartName;
}
public void setCartName(String cartName) {
this.cartName = cartName;
}
public int getCartCVV() {
return cartCVV;
}
public void setCartCVV(int cartCVV) {
this.cartCVV = cartCVV;
}
public String getCartExpired() {
return cartExpired;
}
public void setCartExpired(String cartExpired) {
this.cartExpired = cartExpired;
}
public String getCartNumber() {
return cartNumber;
}
public void setCartNumber(String cartNumber) {
this.cartNumber = cartNumber;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}

View File

@@ -93,7 +93,7 @@ public class ArticleController {
}
return "article";
} else {
return "redirect:/enchere";
return "redirect:/login";
}
}

View File

@@ -1,16 +1,20 @@
package fr.eni.enchere.controllers;
import fr.eni.enchere.bll.ArticleService;
import fr.eni.enchere.bll.BankService;
import fr.eni.enchere.bll.UserService;
import fr.eni.enchere.bo.Bank;
import fr.eni.enchere.bo.UserProfil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import java.util.Calendar;
import java.util.regex.Pattern;
@Controller()
@RequestMapping("/bank")
@@ -18,27 +22,84 @@ public class BankController {
@Autowired
private final UserService userService;
private BankService bankService;
public BankController(UserService userService) {
public BankController(UserService userService, BankService bankService) {
this.userService = userService;
this.bankService = bankService;
}
@GetMapping
public String home() {
return "redirect:/bank/home";
}
@GetMapping("/home")
public String homeCredit(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!authentication.getName().equals("anonymousUser")){
if (authentication.getName().equals("anonymousUser")){
return "redirect:/enchere";
}
String username = authentication.getName();
UserProfil userProfile = userService.utilisateurByName(username);
model.addAttribute("userProfile", userProfile);
model.addAttribute("bank", new Bank());
return "bank";
}
@PostMapping("/checkout")
public String addCreditCheckout() {
return "bank";
public String addCreditCheckout(@ModelAttribute("bank") Bank infoBank, BindingResult result) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.getName().equals("anonymousUser")){
return "redirect:/accueil";
}
String username = authentication.getName();
UserProfil userProfile = userService.utilisateurByName(username);
//Vérification du prix demmander
if (infoBank.getCartAmount() > 2000000.0 || infoBank.getCartAmount() < 1.0){
result.rejectValue("cartAmount", "error.bank", "Le prix demander est incorrect.");
}
//Vérification du numéro de la carte
// Expression régulière pour vérifier si la variable contient exactement 16 chiffres
if (!Pattern.matches("^\\d{16}$", infoBank.getCartNumber())){
result.rejectValue("cartNumber", "error.bank", "Le numéro de la carte est invalide.");
}
//Vérification de la date d'expiration de la carte
if (!Pattern.matches("^(0[1-9]|1[0-2])/(1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-9]|[0-9]{2,3})\\d{2}$", infoBank.getCartExpired())){
result.rejectValue("cartExpired", "error.bank", "La date d'expiration est incorrecte.");
}else{
Calendar calendar = Calendar.getInstance();
int moisNow = calendar.get(Calendar.MONTH) + 1;
int anneeNow = calendar.get(Calendar.YEAR);
String[] parts = infoBank.getCartExpired().split("/");
int mois = Integer.parseInt(parts[0]);
int annee = Integer.parseInt(parts[1]);
if (annee < anneeNow){
result.rejectValue("cartExpired", "error.bank", "Votre carte est expiré.");
}
if(annee == anneeNow && mois < moisNow){
result.rejectValue("cartExpired", "error.bank", "Votre carte est expiré.");
}
}
//Vérification de du CVV de la carte
if (!Pattern.matches("^\\d{3}$", String.valueOf(infoBank.getCartCVV()))){
result.rejectValue("cartCVV", "error.bank", "Le CVV est incorrect.");
}
//Vérification du nom de la carte
if (infoBank.getCartName().isEmpty()){
result.rejectValue("cartName", "error.bank", "Le titulaire de la carte est obligatoire.");
}
//Passer au payement
Bank bank = bankService.isValideCart(infoBank.getCartNumber(), infoBank.getCartExpired(), infoBank.getCartCVV());
if (bank == null){
result.rejectValue("cartName", "error.bank", "Votre paiement n'a pas aboutie.");
}
if (result.hasErrors()) {
return "bank";
}
if (infoBank.getCartAmount() > bank.getCartAmount()){
return "bankDeny";
}
bankService.setCredit(bank, bank.getCartAmount()-infoBank.getCartAmount());
userService.setCredit(userProfile.getCredit()+infoBank.getCartAmount(), userProfile.getId());
return "bankAllow";
}
}

View File

@@ -0,0 +1,8 @@
package fr.eni.enchere.dal;
import fr.eni.enchere.bo.Bank;
public interface BankRepository {
Bank verifCart(String cartNumber, String cartExpired, int cartCVV);
void editAmmountCart(Bank bank, float ammount);
}

View File

@@ -0,0 +1,61 @@
package fr.eni.enchere.dal;
import fr.eni.enchere.bo.Bank;
import fr.eni.enchere.bo.ForgotPassword;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
@Repository
public class BankRepositoryImpl implements BankRepository {
@Autowired
private final JdbcTemplate jdbcTemplate;
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
public BankRepositoryImpl(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
}
public class BankRowMapper implements RowMapper<Bank> {
@Override
public Bank mapRow(ResultSet rs, int rowNum) throws SQLException {
Bank bank = new Bank();
bank.setId(rs.getInt("id"));
bank.setCartNumber(rs.getString("cardNumber"));
bank.setCartExpired(rs.getString("cardExpired"));
bank.setCartCVV(rs.getInt("cardCVV"));
bank.setCartName(rs.getString("cardName"));
bank.setCartAmount(rs.getFloat("credit"));
return bank;
}
}
@Override
public Bank verifCart(String cartNumber, String cartExpired, int cartCVV) {
String sql = "SELECT * FROM CREDITCARD WHERE cardNumber = ? AND cardExpired = ? AND cardCVV = ?";
try {
return jdbcTemplate.queryForObject(sql, new BankRepositoryImpl.BankRowMapper(), cartNumber, cartExpired, cartCVV);
} catch (EmptyResultDataAccessException e) {
// Aucun résultat trouvé, retourne null
return null;
}
}
@Override
public void editAmmountCart(Bank bank, float ammount) {
String sql = "UPDATE CREDITCARD SET credit = ? WHERE cardNumber = ? AND cardExpired = ? AND cardCVV = ?";
jdbcTemplate.update(sql, ammount, bank.getCartNumber(), bank.getCartExpired(), bank.getCartCVV());
}
}

View File

@@ -21,7 +21,7 @@ public class WebSecurityConfig{
http.authorizeHttpRequests((requests) -> requests
.requestMatchers("/","/enchere", "/login", "/forgotPassword/**", "/inscription/**", "/searchArticle", "/article/show", "/change-language").permitAll()
.requestMatchers("/css/**", "/images/**", "/assets/**", "/img/**", "/js/**", "/assets/**", "/i18n/**").permitAll()
.requestMatchers("/profil/**", "/article/new/**", "/article/update", "/article/delete").authenticated()
.requestMatchers("/profil/**", "/article/new/**", "/article/update", "/article/delete", "/bank/**").authenticated()
.requestMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated())
.formLogin((form) -> form

View File

@@ -1,93 +1,61 @@
<!DOCTYPE html>
<html th:replace="~{modele-page :: layout('Créditer son compte',~{::link} , ~{::#container-main})}" xmlns:th="http://www.thymeleaf.org">
<html lang="fr" th:replace="~{modele-page :: layout('Crédits',~{::link} , ~{::#container-main})}" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="container-main" class="container py-5">
<h1 class="mb-4" th:text="#{article.add.heading}">Nouvelle vente</h1>
<form th:action="@{/article/new}" method="post" th:object="${article}" enctype="multipart/form-data" class="needs-validation" novalidate>
<div class="mb-3">
<label for="nom" class="form-label" th:text="#{article.add.form.label.name}">Article:</label>
<input type="text" class="form-control" th:field="*{nom}" id="nom" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
<body>
<div class="container" id="container-main">
<div class="row justify-content-center mt-5">
<form th:action="@{/bank/checkout}" method="post" th:object="${bank}" class="needs-validation" novalidate>
<div class="mb-3">
<label for="cartAmount" class="form-label">Nombre de crédits:</label>
<input type="number" class="form-control" th:field="*{cartAmount}" id="cartAmount" step="0.01" max="2000000" required/>
<div class="is-invalid text-danger" th:if="${#fields.hasErrors('cartAmount')}">
<ul>
<li th:each="erreur: ${#fields.errors('cartAmount')}" th:text="${erreur}"></li>
</ul>
</div>
</div>
<div class="mb-3">
<label for="cartNumber" class="form-label">Numéro de carte:</label>
<input type="text" class="form-control" th:field="*{cartNumber}" id="cartNumber" pattern="[0-9]{16}" maxlength="16" placeholder="1234 5678 9012 3456" required/>
<div class="is-invalid text-danger" th:if="${#fields.hasErrors('cartNumber')}">
<ul>
<li th:each="erreur: ${#fields.errors('cartNumber')}" th:text="${erreur}"></li>
</ul>
</div>
</div>
<div class="mb-3">
<label for="cartExpired" class="form-label">Date d'expiration:</label>
<input type="text" class="form-control" th:field="*{cartExpired}" id="cartExpired" pattern="(0[1-9]|1[0-2])\/[0-9]{4}" placeholder="MM/YYYY" required/>
<div class="is-invalid text-danger" th:if="${#fields.hasErrors('cartExpired')}">
<ul>
<li th:each="erreur: ${#fields.errors('cartExpired')}" th:text="${erreur}"></li>
</ul>
</div>
</div>
<div class="mb-3">
<label for="cartCVV" class="form-label">CVV:</label>
<input type="text" class="form-control" th:field="*{cartCVV}" id="cartCVV" pattern="[0-9]{3}" maxlength="3" required/>
<div class="is-invalid text-danger" th:if="${#fields.hasErrors('cartCVV')}">
<ul>
<li th:each="erreur: ${#fields.errors('cartCVV')}" th:text="${erreur}"></li>
</ul>
</div>
</div>
<div class="mb-3">
<label for="cartName" class="form-label">Nom du titulaire de la carte:</label>
<input type="text" class="form-control" th:field="*{cartName}" id="cartName" required/>
<div class="is-invalid text-danger" th:if="${#fields.hasErrors('cartName')}">
<ul>
<li th:each="erreur: ${#fields.errors('cartName')}" th:text="${erreur}"></li>
</ul>
</div>
</div>
<button type="submit" class="btn btn-primary w-100">Payer</button>
</form>
</div>
</div>
<div class="mb-3">
<label for="description" class="form-label" th:text="#{article.add.form.label.description}">Description:</label>
<textarea class="form-control" th:field="*{desc}" id="description" required></textarea>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<div class="mb-3">
<label for="categorie" class="form-label" th:text="#{article.add.form.label.category}">Catégorie:</label>
<select class="form-control" th:field="*{numCategorie}" id="categorie" required>
<option th:each="categorie : ${categories}" th:value="${categorie.id}" th:text="${categorie.libelle}"></option>
</select>
<div class="invalid-feedback" th:text="#{article.add.form.validation.category}">Veuillez sélectionner une catégorie.</div>
</div>
<div class="mb-3">
<label for="photo" class="form-label" th:text="#{article.add.form.label.photo}">Photo de l'article:</label>
<input type="file" class="form-control" th:field="*{photo}" id="photo" accept="image/jpeg">
</div>
<div class="mb-3">
<label for="prix" class="form-label" th:text="#{article.add.form.label.starting_price}">Mise à prix:</label>
<input type="number" class="form-control" th:field="*{prixInitial}" id="prix" min="0" max="2000000000" step="0.01" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<div class="mb-3">
<label for="dateDebut" class="form-label" th:text="#{article.add.form.label.start_date}">Date début enchère:</label>
<input type="date" class="form-control" id="dateDebut" name="dateDebut" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<div class="mb-3">
<label for="dateFin" class="form-label" th:text="#{article.add.form.label.end_date}">Date fin enchère:</label>
<input type="date" class="form-control" id="dateFin" name="dateFin" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<h4 th:text="#{article.add.form.label.removal}">Retrait</h4>
<div class="mb-3">
<label for="rue" class="form-label" th:text="#{article.add.form.label.street}">Rue:</label>
<input type="text" class="form-control" id="rue" name="rue" th:field="${user.rue}" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<div class="mb-3">
<label for="codePostal" class="form-label" th:text="#{article.add.form.label.postal_code}">Code postal:</label>
<input type="text" class="form-control" id="codePostal" name="code_postal" th:field="${user.code_postal}" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<div class="mb-3">
<label for="ville" class="form-label" th:text="#{article.add.form.label.city}">Ville:</label>
<input type="text" class="form-control" id="ville" name="ville" th:field="${user.ville}" required>
<div class="invalid-feedback" th:text="#{article.add.form.validation.required}">Ce champ est requis.</div>
</div>
<button type="submit" class="btn btn-primary" th:text="#{article.add.form.button.save}">Enregistrer</button>
<div th:if="${param.erreur != null}" class="mt-3">
<p style="color: red;" th:text="${param.erreur}"></p>
</div>
</form>
<form th:action="@{/enchere}" method="post" class="mt-3">
<button type="submit" class="btn btn-secondary" th:text="#{article.add.form.button.cancel}">Annuler</button>
</form>
<script>
var today = new Date();
var tomorrow = new Date(today);
tomorrow.setDate(tomorrow.getDate() + 1);
var formattedDateToday = today.toISOString().split('T')[0];
var formattedDateTomorrow = tomorrow.toISOString().split('T')[0];
document.getElementById('dateDebut').min = formattedDateToday;
document.getElementById('dateFin').min = formattedDateTomorrow;
</script>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
</body>
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="fr" th:replace="~{modele-page :: layout('Lien expiré',~{::link} , ~{::#container-main})}" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="container" id="container-main">
<div class="row justify-content-center mt-5">
<div class="col-md-6">
<h2 class="text-center mb-4">Le paiement a été validé !</h2>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="fr" th:replace="~{modele-page :: layout('Lien expiré',~{::link} , ~{::#container-main})}" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="container" id="container-main">
<div class="row justify-content-center mt-5">
<div class="col-md-6">
<h2 class="text-center mb-4">Le paiement a été refusé !</h2>
</div>
</div>
</div>
</body>
</html>