feat(email): add deposit confirmation email template and logic
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				CI / Get Changed Files (pull_request) Successful in 9s
				
			
		
			
				
	
				CI / Docker frontend validation (pull_request) Successful in 9s
				
			
		
			
				
	
				CI / eslint (pull_request) Has been skipped
				
			
		
			
				
	
				CI / oxlint (pull_request) Has been skipped
				
			
		
			
				
	
				CI / prettier (pull_request) Has been skipped
				
			
		
			
				
	
				CI / test-build (pull_request) Has been skipped
				
			
		
			
				
	
				CI / Docker backend validation (pull_request) Successful in 1m15s
				
			
		
			
				
	
				CI / Checkstyle Main (pull_request) Successful in 1m17s
				
			
		
		
	
	
		
	
		
			All checks were successful
		
		
	
	CI / Get Changed Files (pull_request) Successful in 9s
				
			CI / Docker frontend validation (pull_request) Successful in 9s
				
			CI / eslint (pull_request) Has been skipped
				
			CI / oxlint (pull_request) Has been skipped
				
			CI / prettier (pull_request) Has been skipped
				
			CI / test-build (pull_request) Has been skipped
				
			CI / Docker backend validation (pull_request) Successful in 1m15s
				
			CI / Checkstyle Main (pull_request) Successful in 1m17s
				
			This commit is contained in:
		
					parent
					
						
							
								d449af9732
							
						
					
				
			
			
				commit
				
					
						7fbe1c3753
					
				
			
		
					 5 changed files with 172 additions and 4 deletions
				
			
		|  | @ -3,10 +3,13 @@ package de.szut.casino.deposit; | |||
| import com.stripe.exception.StripeException; | ||||
| import com.stripe.model.checkout.Session; | ||||
| import com.stripe.param.checkout.SessionRetrieveParams; | ||||
| import de.szut.casino.security.service.EmailService; | ||||
| import de.szut.casino.user.UserEntity; | ||||
| import de.szut.casino.user.UserRepository; | ||||
| import jakarta.mail.MessagingException; | ||||
| import org.springframework.stereotype.Service; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.math.BigDecimal; | ||||
| import java.util.Optional; | ||||
| 
 | ||||
|  | @ -14,10 +17,12 @@ import java.util.Optional; | |||
| public class TransactionService { | ||||
|     private final TransactionRepository transactionRepository; | ||||
|     private final UserRepository userRepository; | ||||
|     private final EmailService emailService; | ||||
| 
 | ||||
|     public TransactionService(TransactionRepository transactionRepository, UserRepository userRepository) { | ||||
|     public TransactionService(TransactionRepository transactionRepository, UserRepository userRepository, EmailService emailService) { | ||||
|         this.transactionRepository = transactionRepository; | ||||
|         this.userRepository = userRepository; | ||||
|         this.emailService = emailService; | ||||
|     } | ||||
| 
 | ||||
|     public void createTransaction( | ||||
|  | @ -34,7 +39,7 @@ public class TransactionService { | |||
|         transactionRepository.save(transaction); | ||||
|     } | ||||
| 
 | ||||
|     public void fulfillCheckout(String sessionID) throws StripeException { | ||||
|     public void fulfillCheckout(String sessionID) throws StripeException, MessagingException, IOException { | ||||
|         SessionRetrieveParams params = SessionRetrieveParams.builder() | ||||
|                 .addExpand("line_items") | ||||
|                 .build(); | ||||
|  | @ -60,5 +65,6 @@ public class TransactionService { | |||
| 
 | ||||
|         userRepository.save(user); | ||||
|         transactionRepository.save(transaction); | ||||
|         emailService.sendDepositEmail(transaction); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import com.stripe.model.Event; | |||
| import com.stripe.model.checkout.Session; | ||||
| import com.stripe.net.Webhook; | ||||
| import jakarta.annotation.PostConstruct; | ||||
| import jakarta.mail.MessagingException; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
|  | @ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestHeader; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.Objects; | ||||
| 
 | ||||
| @RestController | ||||
|  | @ -38,7 +40,7 @@ public class WebhookController { | |||
|     } | ||||
| 
 | ||||
|     @PostMapping("/webhook") | ||||
|     public ResponseEntity<String> webhook(@RequestBody String payload, @RequestHeader("Stripe-Signature") String sigHeader) throws StripeException { | ||||
|     public ResponseEntity<String> webhook(@RequestBody String payload, @RequestHeader("Stripe-Signature") String sigHeader) throws StripeException, MessagingException, IOException { | ||||
|         Event event = Webhook.constructEvent(payload, sigHeader, webhookSecret); | ||||
| 
 | ||||
|         if (Objects.equals(event.getType(), "checkout.session.completed") || Objects.equals(event.getType(), "checkout.session.async_payment_succeeded")) { | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| package de.szut.casino.security.service; | ||||
| 
 | ||||
| import de.szut.casino.deposit.TransactionEntity; | ||||
| import de.szut.casino.user.UserEntity; | ||||
| import jakarta.mail.MessagingException; | ||||
| import jakarta.mail.internet.MimeMessage; | ||||
|  | @ -14,6 +15,7 @@ import java.io.IOException; | |||
| import java.io.InputStreamReader; | ||||
| import java.io.Reader; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.List; | ||||
| 
 | ||||
| @Service | ||||
| public class EmailService { | ||||
|  | @ -43,13 +45,31 @@ public class EmailService { | |||
|         MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); | ||||
| 
 | ||||
|         helper.setFrom(mailConfig.fromAddress); | ||||
|         helper.setTo(user.getEmail()); | ||||
|         helper.setTo(user.getEmailAddress()); | ||||
|         helper.setSubject("Willkommen bei Trustworthy Casino©"); | ||||
|         helper.setText(htmlContent, true); | ||||
| 
 | ||||
|         mailSender.send(message); | ||||
|     } | ||||
| 
 | ||||
|     public void sendDepositEmail(TransactionEntity transaction) throws IOException, MessagingException { | ||||
|         String template = loadTemplate("email/deposit.html"); | ||||
|         String htmlContent = template | ||||
|                 .replace("${username}", transaction.getUser().getUsername()) | ||||
|                 .replace("${amount}", String.valueOf(transaction.getAmount())) | ||||
|                 .replace("${feUrl}", feUrl); | ||||
| 
 | ||||
|         MimeMessage message = mailSender.createMimeMessage(); | ||||
|         MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); | ||||
| 
 | ||||
|         helper.setFrom(mailConfig.fromAddress); | ||||
|         helper.setTo(transaction.getUser().getEmailAddress()); | ||||
|         helper.setSubject("Einzahlung über ${amount}€ Erfolgreich".replace("${amount}", String.valueOf(transaction.getAmount()))); | ||||
|         helper.setText(htmlContent, true); | ||||
| 
 | ||||
|         mailSender.send(message); | ||||
|     } | ||||
| 
 | ||||
|     private String loadTemplate(String templatePath) throws IOException { | ||||
|         ClassPathResource resource = new ClassPathResource("templates/" + templatePath); | ||||
|         try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) { | ||||
|  |  | |||
|  | @ -64,4 +64,8 @@ public class UserEntity { | |||
| 
 | ||||
|         this.balance = this.balance.subtract(amountToSubtract); | ||||
|     } | ||||
| 
 | ||||
|     public String getEmailAddress() { | ||||
|         return "${name} <${email}>".replace("${name}", this.username).replace("${email}", this.email); | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										136
									
								
								backend/src/main/resources/templates/email/deposit.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								backend/src/main/resources/templates/email/deposit.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,136 @@ | |||
| <!DOCTYPE html> | ||||
| <html lang="de"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>Einzahlung bestätigt - Trustworthy Casino©</title> | ||||
|     <style> | ||||
|         body { | ||||
|             font-family: 'Arial', sans-serif; | ||||
|             line-height: 1.6; | ||||
|             background-color: #f8fafc; | ||||
|             color: #64748b; | ||||
|             max-width: 600px; | ||||
|             margin: 0 auto; | ||||
|             padding: 20px; | ||||
|         } | ||||
|         .container { | ||||
|             background-color: #0a1219; | ||||
|             border-radius: 8px; | ||||
|             overflow: hidden; | ||||
|             box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | ||||
|         } | ||||
|         .header { | ||||
|             background-color: #1a2835; | ||||
|             padding: 20px; | ||||
|             text-align: center; | ||||
|         } | ||||
|         .header h1 { | ||||
|             color: #ffffff; | ||||
|             margin: 0; | ||||
|             font-size: 28px; | ||||
|         } | ||||
|         .content { | ||||
|             background-color: #121e27; | ||||
|             padding: 30px; | ||||
|             color: #ffffff; | ||||
|         } | ||||
|         .footer { | ||||
|             background-color: #1a2835; | ||||
|             color: #94a3b8; | ||||
|             padding: 20px; | ||||
|             text-align: center; | ||||
|             font-size: 0.8em; | ||||
|         } | ||||
|         .button { | ||||
|             display: inline-block; | ||||
|             background-color: #10b981; | ||||
|             color: #ffffff; | ||||
|             padding: 12px 24px; | ||||
|             margin: 20px 0; | ||||
|             text-decoration: none; | ||||
|             border-radius: 6px; | ||||
|             font-weight: bold; | ||||
|             text-align: center; | ||||
|             transition: background-color 0.3s; | ||||
|         } | ||||
|         .button:hover { | ||||
|             background-color: #059669; | ||||
|         } | ||||
|         h2 { | ||||
|             color: #ffffff; | ||||
|             padding-bottom: 10px; | ||||
|             display: inline-block; | ||||
|         } | ||||
|         ul { | ||||
|             padding-left: 20px; | ||||
|             margin: 20px 0; | ||||
|         } | ||||
|         li { | ||||
|             margin-bottom: 8px; | ||||
|             color: #94a3b8; | ||||
|         } | ||||
|         li::marker { | ||||
|             color: #34d399; | ||||
|         } | ||||
|         .highlight { | ||||
|             color: #10b981; | ||||
|             font-weight: bold; | ||||
|         } | ||||
|         .divider { | ||||
|             height: 1px; | ||||
|             background-color: #1a2835; | ||||
|             margin: 20px 0; | ||||
|         } | ||||
|         p { | ||||
|             margin: 16px 0; | ||||
|         } | ||||
|         .amount-box { | ||||
|             background-color: #1a2835; | ||||
|             border-radius: 6px; | ||||
|             padding: 15px; | ||||
|             text-align: center; | ||||
|             margin: 20px 0; | ||||
|         } | ||||
|         .amount-value { | ||||
|             font-size: 28px; | ||||
|             font-weight: bold; | ||||
|             color: #10b981; | ||||
|         } | ||||
|     </style> | ||||
| </head> | ||||
| <body> | ||||
| <div class="container"> | ||||
|     <div class="header"> | ||||
|         <h1>Trustworthy Casino</h1> | ||||
|     </div> | ||||
|     <div class="content"> | ||||
|         <h2>Hallo <span class="highlight">${username}</span>,</h2> | ||||
| 
 | ||||
|         <p>vielen Dank für Ihre Einzahlung bei Trustworthy Casino. Wir bestätigen den Eingang Ihres Guthabens.</p> | ||||
| 
 | ||||
|         <div class="amount-box"> | ||||
|             <p>Eingezahlter Betrag</p> | ||||
|             <div class="amount-value">${amount}€</div> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="divider"></div> | ||||
| 
 | ||||
|         <p>Ihr Guthaben wurde Ihrem Konto sofort gutgeschrieben und steht ab sofort zum Spielen zur Verfügung.</p> | ||||
| 
 | ||||
|         <div style="text-align: center;"> | ||||
|             <a href="${feUrl}/games" class="button">Jetzt Spielen</a> | ||||
|         </div> | ||||
| 
 | ||||
|         <p>Bei Fragen zu Ihrer Einzahlung kontaktieren Sie bitte unseren Kundenservice.</p> | ||||
| 
 | ||||
|         <p>Mit freundlichen Grüßen,<br> | ||||
|             Ihr <span style="color: #10b981;">Trustworthy Casino</span> Team</p> | ||||
|     </div> | ||||
|     <div class="footer"> | ||||
|         <p>2025 Trustworthy Casino - Alle Rechte vorbehalten</p> | ||||
|         <p>Diese E-Mail wurde automatisch generiert. Bitte antworten Sie nicht darauf.</p> | ||||
|     </div> | ||||
| </div> | ||||
| </body> | ||||
| </html> | ||||
		Reference in a new issue