From 6c00b43f39a76f9bd7351c7ec8711c662069a1ea Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 11:18:05 +0300 Subject: [PATCH 01/12] added base stucture for paymentController, added Payment dtos and sample of StripeService --- pom.xml | 16 ++++--- .../controller/PaymentController.java | 35 ++++++++++++++ .../CreatePaymentSessionRequestDto.java | 14 ++++++ .../dto/payment/PaymentResponseDto.java | 4 ++ .../service/PaymentAmountHandler.java | 11 +++++ .../carsharingapp/service/PaymentService.java | 5 ++ .../service/impl/FineAmountHandler.java | 20 ++++++++ .../impl/PaymentAmountHandlerStrategy.java | 27 +++++++++++ .../impl/RegularPaymentAmountHandler.java | 19 ++++++++ .../service/impl/StripeService.java | 48 +++++++++++++++++++ src/main/resources/application.properties | 4 ++ 11 files changed, 197 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/project/carsharingapp/controller/PaymentController.java create mode 100644 src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java create mode 100644 src/main/java/com/project/carsharingapp/dto/payment/PaymentResponseDto.java create mode 100644 src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java create mode 100644 src/main/java/com/project/carsharingapp/service/PaymentService.java create mode 100644 src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java create mode 100644 src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java create mode 100644 src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java create mode 100644 src/main/java/com/project/carsharingapp/service/impl/StripeService.java diff --git a/pom.xml b/pom.xml index 150e63b..5849555 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,7 @@ checkstyle.xml 0.2.0 1.5.5.Final + 23.7.0 @@ -39,9 +40,9 @@ ${liquibase.version} - mysql - mysql-connector-java - 8.0.33 + com.mysql + mysql-connector-j + 8.1.0 org.projectlombok @@ -68,14 +69,17 @@ mapstruct ${mapstruct.version} - jakarta.validation jakarta.validation-api 2.0.2 - - + + com.stripe + stripe-java + ${stripe.version} + + diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java new file mode 100644 index 0000000..5f5bf39 --- /dev/null +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -0,0 +1,35 @@ +package com.project.carsharingapp.controller; + +import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; +import com.project.carsharingapp.dto.payment.PaymentResponseDto; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; + +@RestController +@RequestMapping("/payments") +public class PaymentController { + + @GetMapping + public List getAll() { + return List.of(); + } + + @PostMapping + public PaymentResponseDto create( + @RequestBody @Valid CreatePaymentSessionRequestDto requestDto + ) { + return new PaymentResponseDto(); + } + + @GetMapping("/success") + private void redirectToSuccessPage() { + + } + + @GetMapping("/cancel") + private void redirectToFailedPage() { + + } +} diff --git a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java new file mode 100644 index 0000000..f649a2e --- /dev/null +++ b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java @@ -0,0 +1,14 @@ +package com.project.carsharingapp.dto.payment; + +import com.project.carsharingapp.model.Payment; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class CreatePaymentSessionRequestDto { + @NotNull + private Long rentalId; + @NotNull + private String type; +} diff --git a/src/main/java/com/project/carsharingapp/dto/payment/PaymentResponseDto.java b/src/main/java/com/project/carsharingapp/dto/payment/PaymentResponseDto.java new file mode 100644 index 0000000..7fba6ec --- /dev/null +++ b/src/main/java/com/project/carsharingapp/dto/payment/PaymentResponseDto.java @@ -0,0 +1,4 @@ +package com.project.carsharingapp.dto.payment; + +public class PaymentResponseDto { +} diff --git a/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java b/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java new file mode 100644 index 0000000..bcfe51e --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java @@ -0,0 +1,11 @@ +package com.project.carsharingapp.service; + +import com.project.carsharingapp.model.Payment; + +import java.math.BigDecimal; + +public interface PaymentAmountHandler { + Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays); + + boolean isApplicable(Payment.Type type); +} diff --git a/src/main/java/com/project/carsharingapp/service/PaymentService.java b/src/main/java/com/project/carsharingapp/service/PaymentService.java new file mode 100644 index 0000000..9b1d316 --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/PaymentService.java @@ -0,0 +1,5 @@ +package com.project.carsharingapp.service; + +public interface PaymentService { + +} diff --git a/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java b/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java new file mode 100644 index 0000000..1ca635f --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java @@ -0,0 +1,20 @@ +package com.project.carsharingapp.service.impl; + +import java.math.BigDecimal; +import com.project.carsharingapp.model.Payment; +import com.project.carsharingapp.service.PaymentAmountHandler; +import org.springframework.stereotype.Component; + +@Component +public class FineAmountHandler implements PaymentAmountHandler { + private static final BigDecimal FINE_MULTIPLIER = BigDecimal.valueOf(1.25); + @Override + public Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays) { + return dailyFee.multiply(FINE_MULTIPLIER).longValue() * numberOfDays; + } + + @Override + public boolean isApplicable(Payment.Type type) { + return type.equals(Payment.Type.FINE); + } +} diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java new file mode 100644 index 0000000..a8ca658 --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java @@ -0,0 +1,27 @@ +package com.project.carsharingapp.service.impl; + +import com.project.carsharingapp.model.Payment; +import com.project.carsharingapp.service.PaymentAmountHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.NoSuchElementException; + +@Component +public class PaymentAmountHandlerStrategy { + @Autowired + private List paymentAmountHandlers; + + public PaymentAmountHandler getHandler(Payment.Type type) { + return paymentAmountHandlers.stream() + .filter(paymentAmountHandler -> paymentAmountHandler.isApplicable(type)) + .findAny() + .orElseThrow(() -> + new NoSuchElementException("Can't find a PaymentAmountHandler " + + "for such type as: " + type) + ); + + } + +} diff --git a/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java b/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java new file mode 100644 index 0000000..ee01f32 --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java @@ -0,0 +1,19 @@ +package com.project.carsharingapp.service.impl; + +import java.math.BigDecimal; +import com.project.carsharingapp.model.Payment; +import com.project.carsharingapp.service.PaymentAmountHandler; +import org.springframework.stereotype.Component; + +@Component +public class RegularPaymentAmountHandler implements PaymentAmountHandler { + @Override + public Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays) { + return dailyFee.longValue() * numberOfDays; + } + + @Override + public boolean isApplicable(Payment.Type type) { + return type.equals(Payment.Type.PAYMENT); + } +} diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java new file mode 100644 index 0000000..2ceb17a --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -0,0 +1,48 @@ +package com.project.carsharingapp.service.impl; + +import com.project.carsharingapp.model.Payment; +import com.project.carsharingapp.model.Rental; +import com.stripe.Stripe; +import com.stripe.model.checkout.Session; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.util.UriComponentsBuilder; + +import java.math.BigDecimal; + +@Service +public class StripeService { + private static final BigDecimal FINE_MULTIPLIER = BigDecimal.valueOf(1.25); + @Value("${stripe.secret}") + private String secretKey; + @Value("${app.host}") + private String host; + @Value("${app.port}") + private Integer port; + + + @PostConstruct + public void init() { + Stripe.apiKey = secretKey; + } + + public Session createSession(Rental rental, Payment.Type type) { + return null; + } + + private String createUrl(String type) { + return UriComponentsBuilder.newInstance() + .scheme("http") + .host(host) + .port(port) + .path("/" + type) + .build() + .encode() + .toUriString(); + } + + private BigDecimal calculateTotalAmount(Rental rental, Payment.Type type) { + return null; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6059ae8..e3d7586 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,3 +7,7 @@ server.servlet.context-path=/api spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true spring.jpa.open-in-view=false + +stripe.secret=pk_test_51NwluPLODs6ppc0LCeGCY3erMp2FtAW7MGbd1KKfRbd18rf3YezXevzdzOLlxiLpn1jGoLycqnBR5kzHcjHrlPsv00x6ivaHcU +app.host=localhost +app.port=8080 From 757837602b0571abcf68ab59378baef598060cb8 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 12:17:56 +0300 Subject: [PATCH 02/12] added stategy for choosing payment type, created initial structures for payment controller, service and stripe service --- pom.xml | 21 +++++++++++++++---- .../controller/PaymentController.java | 9 +++++--- .../CreatePaymentSessionRequestDto.java | 4 +--- .../service/PaymentAmountHandler.java | 1 - .../service/impl/FineAmountHandler.java | 3 ++- .../impl/PaymentAmountHandlerStrategy.java | 5 ++--- .../impl/RegularPaymentAmountHandler.java | 2 +- .../service/impl/StripeService.java | 4 +--- 8 files changed, 30 insertions(+), 19 deletions(-) diff --git a/pom.xml b/pom.xml index 60d3318..fd2a0a0 100644 --- a/pom.xml +++ b/pom.xml @@ -24,10 +24,19 @@ org.springframework.boot spring-boot-starter-data-jpa + + org.springframework.boot + spring-boot-starter-validation + org.springframework.boot spring-boot-starter-web + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.1.0 + org.liquibase liquibase-core @@ -39,8 +48,8 @@ ${liquibase.version} - mysql - mysql-connector-java + com.mysql + mysql-connector-j 8.1.0 @@ -68,13 +77,17 @@ mapstruct ${mapstruct.version} - jakarta.validation jakarta.validation-api 2.0.2 - + + com.stripe + stripe-java + 23.7.0 + + diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index 5f5bf39..d70359a 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -2,10 +2,13 @@ import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; import com.project.carsharingapp.dto.payment.PaymentResponseDto; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; import java.util.List; +import javax.validation.Valid; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/payments") diff --git a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java index f649a2e..8557115 100644 --- a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java @@ -1,9 +1,7 @@ package com.project.carsharingapp.dto.payment; -import com.project.carsharingapp.model.Payment; -import lombok.Data; - import javax.validation.constraints.NotNull; +import lombok.Data; @Data public class CreatePaymentSessionRequestDto { diff --git a/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java b/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java index bcfe51e..c2726c2 100644 --- a/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java +++ b/src/main/java/com/project/carsharingapp/service/PaymentAmountHandler.java @@ -1,7 +1,6 @@ package com.project.carsharingapp.service; import com.project.carsharingapp.model.Payment; - import java.math.BigDecimal; public interface PaymentAmountHandler { diff --git a/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java b/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java index 1ca635f..0acaaf9 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java +++ b/src/main/java/com/project/carsharingapp/service/impl/FineAmountHandler.java @@ -1,13 +1,14 @@ package com.project.carsharingapp.service.impl; -import java.math.BigDecimal; import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.service.PaymentAmountHandler; +import java.math.BigDecimal; import org.springframework.stereotype.Component; @Component public class FineAmountHandler implements PaymentAmountHandler { private static final BigDecimal FINE_MULTIPLIER = BigDecimal.valueOf(1.25); + @Override public Long getPaymentAmount(BigDecimal dailyFee, int numberOfDays) { return dailyFee.multiply(FINE_MULTIPLIER).longValue() * numberOfDays; diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java index a8ca658..1b96abf 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java @@ -2,11 +2,10 @@ import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.service.PaymentAmountHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - import java.util.List; import java.util.NoSuchElementException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; @Component public class PaymentAmountHandlerStrategy { diff --git a/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java b/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java index ee01f32..a8fbf31 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java +++ b/src/main/java/com/project/carsharingapp/service/impl/RegularPaymentAmountHandler.java @@ -1,8 +1,8 @@ package com.project.carsharingapp.service.impl; -import java.math.BigDecimal; import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.service.PaymentAmountHandler; +import java.math.BigDecimal; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java index 2ceb17a..7995d3f 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -5,12 +5,11 @@ import com.stripe.Stripe; import com.stripe.model.checkout.Session; import jakarta.annotation.PostConstruct; +import java.math.BigDecimal; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.util.UriComponentsBuilder; -import java.math.BigDecimal; - @Service public class StripeService { private static final BigDecimal FINE_MULTIPLIER = BigDecimal.valueOf(1.25); @@ -21,7 +20,6 @@ public class StripeService { @Value("${app.port}") private Integer port; - @PostConstruct public void init() { Stripe.apiKey = secretKey; From 04bea7cbc8cbce828e2eccfea8fb485ac42f588d Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 13:27:01 +0300 Subject: [PATCH 03/12] testing creating payment session --- .../controller/PaymentController.java | 18 +++++--- .../project/carsharingapp/model/Payment.java | 2 +- .../carsharingapp/service/PaymentService.java | 5 +++ .../service/impl/PaymentServiceImpl.java | 39 +++++++++++++++++ .../service/impl/StripeService.java | 43 ++++++++++++++++--- src/main/resources/application.properties | 2 +- 6 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index d70359a..2b75ee4 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -4,6 +4,10 @@ import com.project.carsharingapp.dto.payment.PaymentResponseDto; import java.util.List; import javax.validation.Valid; + +import com.project.carsharingapp.model.Payment; +import com.project.carsharingapp.service.PaymentService; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -12,7 +16,9 @@ @RestController @RequestMapping("/payments") +@RequiredArgsConstructor public class PaymentController { + private final PaymentService paymentService; @GetMapping public List getAll() { @@ -20,19 +26,19 @@ public List getAll() { } @PostMapping - public PaymentResponseDto create( + public Payment create( @RequestBody @Valid CreatePaymentSessionRequestDto requestDto ) { - return new PaymentResponseDto(); + return paymentService.create(requestDto); } @GetMapping("/success") - private void redirectToSuccessPage() { - + private String redirectToSuccessPage() { + return "success"; } @GetMapping("/cancel") - private void redirectToFailedPage() { - + private String redirectToFailedPage() { + return "cancel"; } } diff --git a/src/main/java/com/project/carsharingapp/model/Payment.java b/src/main/java/com/project/carsharingapp/model/Payment.java index 35c03c0..d16e290 100644 --- a/src/main/java/com/project/carsharingapp/model/Payment.java +++ b/src/main/java/com/project/carsharingapp/model/Payment.java @@ -31,7 +31,7 @@ public class Payment { private Type type; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "rental_id", nullable = false) - private Rental rentalId; + private Rental rental; @Column(name = "session_url", nullable = false) private String sessionUrl; @Column(name = "session_id", nullable = false) diff --git a/src/main/java/com/project/carsharingapp/service/PaymentService.java b/src/main/java/com/project/carsharingapp/service/PaymentService.java index 9b1d316..afff01e 100644 --- a/src/main/java/com/project/carsharingapp/service/PaymentService.java +++ b/src/main/java/com/project/carsharingapp/service/PaymentService.java @@ -1,5 +1,10 @@ package com.project.carsharingapp.service; +import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; +import com.project.carsharingapp.dto.payment.PaymentResponseDto; +import com.project.carsharingapp.model.Payment; + public interface PaymentService { + Payment create(CreatePaymentSessionRequestDto requestDto); } diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java new file mode 100644 index 0000000..c615b2b --- /dev/null +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java @@ -0,0 +1,39 @@ +package com.project.carsharingapp.service.impl; + +import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; +import com.project.carsharingapp.dto.payment.PaymentResponseDto; +import com.project.carsharingapp.model.Payment; +import com.project.carsharingapp.model.Rental; +import com.project.carsharingapp.repository.RentalRepository; +import com.project.carsharingapp.service.PaymentService; +import com.stripe.exception.StripeException; +import com.stripe.model.checkout.Session; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PaymentServiceImpl implements PaymentService { + private final RentalRepository rentalRepository; + private final StripeService stripeService; + + @Override + public Payment create(CreatePaymentSessionRequestDto requestDto) { + Rental rental = rentalRepository.getReferenceById(requestDto.getRentalId()); + try { + Session session = stripeService.createSession(rental, Payment.Type.valueOf(requestDto.getType())); + return generatePayment(session, rental); + } catch (StripeException e) { + throw new RuntimeException("Can't create a stripe checkout session!"); + } + } + + private Payment generatePayment(Session session, Rental rental) { + Payment payment = new Payment(); + payment.setStatus(Payment.Status.PENDING); + payment.setRental(rental); + payment.setSessionUrl(session.getUrl()); + payment.setSessionId(session.getId()); + return payment; + } +} diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java index 7995d3f..c104b91 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -2,17 +2,27 @@ import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.model.Rental; +import com.project.carsharingapp.service.PaymentAmountHandler; import com.stripe.Stripe; +import com.stripe.exception.StripeException; import com.stripe.model.checkout.Session; +import com.stripe.param.checkout.SessionCreateParams; import jakarta.annotation.PostConstruct; import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.Period; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.util.UriComponentsBuilder; @Service +@RequiredArgsConstructor public class StripeService { - private static final BigDecimal FINE_MULTIPLIER = BigDecimal.valueOf(1.25); + private static final String SUCCESS_ENDPOINT = "success"; + private static final String CANCEL_ENDPOINT = "cancel"; + private static final Long STANDARD_QUANTITY_OF_RENTAL_CART = 1L; + private final PaymentAmountHandlerStrategy handler; @Value("${stripe.secret}") private String secretKey; @Value("${app.host}") @@ -25,8 +35,22 @@ public void init() { Stripe.apiKey = secretKey; } - public Session createSession(Rental rental, Payment.Type type) { - return null; + public Session createSession(Rental rental, Payment.Type type) throws StripeException { + Long price = calculateTotalAmount(rental, type); + SessionCreateParams params = SessionCreateParams.builder() + .setMode(SessionCreateParams.Mode.PAYMENT) + .setSuccessUrl(createUrl(SUCCESS_ENDPOINT)) + .setCancelUrl(createUrl(CANCEL_ENDPOINT)) + .addLineItem( + SessionCreateParams.LineItem.builder() + .setQuantity(STANDARD_QUANTITY_OF_RENTAL_CART) + .setPrice(String.valueOf(price)) + + .build() + ) + .build(); + + return Session.create(params); } private String createUrl(String type) { @@ -40,7 +64,16 @@ private String createUrl(String type) { .toUriString(); } - private BigDecimal calculateTotalAmount(Rental rental, Payment.Type type) { - return null; + private Long calculateTotalAmount(Rental rental, Payment.Type type) { + PaymentAmountHandler amountHandler = handler.getHandler(type); + int rentalDays = getNumberOfRentalDays(rental); + BigDecimal dailyFee = rental.getCar().getDailyFee(); + return amountHandler.getPaymentAmount(dailyFee, rentalDays); + } + + private int getNumberOfRentalDays(Rental rental) { + LocalDate actualReturnDate = rental.getActualReturnDate().toLocalDate(); + LocalDate rentalDate = rental.getRentalDate().toLocalDate(); + return Period.between(rentalDate, actualReturnDate).getDays(); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3347895..e3d7586 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.datasource.url=jdbc:mysql://localhost:3306/car_sharing_db?serverTimezone=UTC spring.datasource.username=root -spring.datasource.password=root123 +spring.datasource.password=redblack0root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver server.servlet.context-path=/api From 93cf4758b5005ff25c50300338603e418869fe7a Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 16:44:33 +0300 Subject: [PATCH 04/12] implemented create payment and create stripe session endpoint, adjusted rental repository and made some sligth changes in create-payments yaml file --- .../controller/PaymentController.java | 14 +++-- .../repository/RentalRepository.java | 7 ++- .../service/impl/PaymentServiceImpl.java | 20 +++++-- .../service/impl/StripeService.java | 23 ++++++-- src/main/resources/application.properties | 2 +- .../changes/create-payments-table.yaml | 4 +- .../com/project/carsharingapp/StripeTest.java | 52 +++++++++++++++++++ 7 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 src/test/java/com/project/carsharingapp/StripeTest.java diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index 2b75ee4..c7ca113 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -2,12 +2,14 @@ import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; import com.project.carsharingapp.dto.payment.PaymentResponseDto; -import java.util.List; -import javax.validation.Valid; - import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.service.PaymentService; +import java.net.URI; +import java.util.List; +import javax.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -26,10 +28,12 @@ public List getAll() { } @PostMapping - public Payment create( + public ResponseEntity create( @RequestBody @Valid CreatePaymentSessionRequestDto requestDto ) { - return paymentService.create(requestDto); + Payment payment = paymentService.create(requestDto); + URI url = URI.create(payment.getSessionUrl()); + return ResponseEntity.status(HttpStatus.FOUND).location(url).build(); } @GetMapping("/success") diff --git a/src/main/java/com/project/carsharingapp/repository/RentalRepository.java b/src/main/java/com/project/carsharingapp/repository/RentalRepository.java index 306d34e..78ce9ef 100644 --- a/src/main/java/com/project/carsharingapp/repository/RentalRepository.java +++ b/src/main/java/com/project/carsharingapp/repository/RentalRepository.java @@ -2,8 +2,13 @@ import com.project.carsharingapp.model.Rental; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -@Repository +import java.util.Optional; + public interface RentalRepository extends JpaRepository { + @Query("FROM Rental r LEFT JOIN FETCH r.car " + + "LEFT JOIN FETCH r.user WHERE r.id = :id") + Optional findById(Long id); } diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java index c615b2b..f70a70d 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java @@ -1,13 +1,15 @@ package com.project.carsharingapp.service.impl; import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; -import com.project.carsharingapp.dto.payment.PaymentResponseDto; +import com.project.carsharingapp.exception.EntityNotFoundException; import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.model.Rental; +import com.project.carsharingapp.repository.PaymentRepository; import com.project.carsharingapp.repository.RentalRepository; import com.project.carsharingapp.service.PaymentService; import com.stripe.exception.StripeException; import com.stripe.model.checkout.Session; +import java.math.BigDecimal; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,25 +17,33 @@ @RequiredArgsConstructor public class PaymentServiceImpl implements PaymentService { private final RentalRepository rentalRepository; + private final PaymentRepository paymentRepository; private final StripeService stripeService; @Override public Payment create(CreatePaymentSessionRequestDto requestDto) { - Rental rental = rentalRepository.getReferenceById(requestDto.getRentalId()); + Rental rental = rentalRepository.findById(requestDto.getRentalId()).orElseThrow( + () -> new EntityNotFoundException("Can't find a Rental by id: " + + requestDto.getRentalId()) + ); + Payment.Type type = Payment.Type.valueOf(requestDto.getType()); try { - Session session = stripeService.createSession(rental, Payment.Type.valueOf(requestDto.getType())); - return generatePayment(session, rental); + Session session = stripeService.createSession(rental, type); + Payment payment = generatePayment(session, rental, type); + return paymentRepository.save(payment); } catch (StripeException e) { throw new RuntimeException("Can't create a stripe checkout session!"); } } - private Payment generatePayment(Session session, Rental rental) { + private Payment generatePayment(Session session, Rental rental, Payment.Type type) { Payment payment = new Payment(); payment.setStatus(Payment.Status.PENDING); + payment.setType(type); payment.setRental(rental); payment.setSessionUrl(session.getUrl()); payment.setSessionId(session.getId()); + payment.setAmount(BigDecimal.valueOf(session.getAmountTotal())); return payment; } } diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java index c104b91..5e6988b 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -1,16 +1,21 @@ package com.project.carsharingapp.service.impl; +import com.project.carsharingapp.model.Car; import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.model.Rental; import com.project.carsharingapp.service.PaymentAmountHandler; import com.stripe.Stripe; import com.stripe.exception.StripeException; +import com.stripe.model.Price; +import com.stripe.model.Product; import com.stripe.model.checkout.Session; import com.stripe.param.checkout.SessionCreateParams; import jakarta.annotation.PostConstruct; import java.math.BigDecimal; import java.time.LocalDate; import java.time.Period; +import java.util.Map; + import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -19,9 +24,11 @@ @Service @RequiredArgsConstructor public class StripeService { + private static final String DEFAULT_URL_PART = "/api/payments"; private static final String SUCCESS_ENDPOINT = "success"; private static final String CANCEL_ENDPOINT = "cancel"; private static final Long STANDARD_QUANTITY_OF_RENTAL_CART = 1L; + private static final String DEFAULT_CURRENCY = "USD"; private final PaymentAmountHandlerStrategy handler; @Value("${stripe.secret}") private String secretKey; @@ -36,6 +43,7 @@ public void init() { } public Session createSession(Rental rental, Payment.Type type) throws StripeException { + String productName = rental.getCar().getModel(); Long price = calculateTotalAmount(rental, type); SessionCreateParams params = SessionCreateParams.builder() .setMode(SessionCreateParams.Mode.PAYMENT) @@ -43,9 +51,18 @@ public Session createSession(Rental rental, Payment.Type type) throws StripeExce .setCancelUrl(createUrl(CANCEL_ENDPOINT)) .addLineItem( SessionCreateParams.LineItem.builder() + .setPriceData( + SessionCreateParams.LineItem.PriceData.builder() + .setCurrency(DEFAULT_CURRENCY) + .setProductData( + SessionCreateParams.LineItem.PriceData.ProductData.builder() + .setName(productName) + .build() + ) + .setUnitAmount(price) + .build() + ) .setQuantity(STANDARD_QUANTITY_OF_RENTAL_CART) - .setPrice(String.valueOf(price)) - .build() ) .build(); @@ -58,7 +75,7 @@ private String createUrl(String type) { .scheme("http") .host(host) .port(port) - .path("/" + type) + .path(DEFAULT_URL_PART + "/" + type) .build() .encode() .toUriString(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e3d7586..920190e 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,6 +8,6 @@ spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true spring.jpa.open-in-view=false -stripe.secret=pk_test_51NwluPLODs6ppc0LCeGCY3erMp2FtAW7MGbd1KKfRbd18rf3YezXevzdzOLlxiLpn1jGoLycqnBR5kzHcjHrlPsv00x6ivaHcU +stripe.secret=sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwyBNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI app.host=localhost app.port=8080 diff --git a/src/main/resources/db/changelog/changes/create-payments-table.yaml b/src/main/resources/db/changelog/changes/create-payments-table.yaml index ecce451..84e3239 100644 --- a/src/main/resources/db/changelog/changes/create-payments-table.yaml +++ b/src/main/resources/db/changelog/changes/create-payments-table.yaml @@ -32,12 +32,12 @@ databaseChangeLog: references: rentals(id) - column: name: session_url - type: varchar(255) + type: varchar(510) constraints: nullable: false - column: name: session_id - type: varchar(255) + type: varchar(510) constraints: nullable: false - column: diff --git a/src/test/java/com/project/carsharingapp/StripeTest.java b/src/test/java/com/project/carsharingapp/StripeTest.java new file mode 100644 index 0000000..82c82b7 --- /dev/null +++ b/src/test/java/com/project/carsharingapp/StripeTest.java @@ -0,0 +1,52 @@ +package com.project.carsharingapp; + +import com.stripe.Stripe; +import com.stripe.exception.StripeException; +import com.stripe.model.PaymentIntent; +import com.stripe.model.Price; +import com.stripe.model.checkout.Session; +import com.stripe.param.PaymentIntentCreateParams; +import com.stripe.param.checkout.SessionCreateParams; +import org.junit.jupiter.api.Test; + + +public class StripeTest { + + @Test + public void test() throws StripeException { + Stripe.apiKey = "sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwyBNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI"; + + SessionCreateParams params = SessionCreateParams.builder() + .setMode(SessionCreateParams.Mode.PAYMENT) + .setSuccessUrl("http://localhost:8080/success") + .setCancelUrl("http://localhost:8080/success") + .addLineItem( + SessionCreateParams.LineItem.builder() + .setPriceData( + SessionCreateParams.LineItem.PriceData.builder() + .setCurrency("USD") + .setProductData( + SessionCreateParams.LineItem.PriceData.ProductData.builder() + .putAllExtraParam(null) + .build() + ) + .setUnitAmount(1L) + .build() + ) + .setQuantity(1L) // todo quantity + .build() + ) + .build(); + + Session session = Session.create(params); + +// PaymentIntentCreateParams params = +// PaymentIntentCreateParams.builder() +// .setAmount(1099L) +// .setCurrency("usd") +// .addPaymentMethodType("card") +// .build(); +// PaymentIntent test = PaymentIntent.create(params); +// System.out.println(test); + } +} From 17640a590baeb19041ec4d5b86b4535cdb2e207a Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 18:34:14 +0300 Subject: [PATCH 05/12] improved payment controller, service and repository, adjusted stripe service --- .../carsharingapp/controller/PaymentController.java | 9 +++------ .../carsharingapp/repository/PaymentRepository.java | 4 +++- .../project/carsharingapp/service/PaymentService.java | 3 ++- .../carsharingapp/service/impl/PaymentServiceImpl.java | 9 +++++++++ .../carsharingapp/service/impl/StripeService.java | 3 ++- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index c7ca113..ac1378a 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -10,11 +10,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/payments") @@ -37,7 +33,8 @@ public ResponseEntity create( } @GetMapping("/success") - private String redirectToSuccessPage() { + private String redirectToSuccessPage(@RequestParam String sessionId) { + paymentService.updateStatus(sessionId); return "success"; } diff --git a/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java b/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java index 6755b06..0fb1562 100644 --- a/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java +++ b/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java @@ -3,6 +3,8 @@ import com.project.carsharingapp.model.Payment; import org.springframework.data.jpa.repository.JpaRepository; -public interface PaymentRepository extends JpaRepository { +import java.util.Optional; +public interface PaymentRepository extends JpaRepository { + Optional findBySessionId(String sessionId); } diff --git a/src/main/java/com/project/carsharingapp/service/PaymentService.java b/src/main/java/com/project/carsharingapp/service/PaymentService.java index afff01e..8f45244 100644 --- a/src/main/java/com/project/carsharingapp/service/PaymentService.java +++ b/src/main/java/com/project/carsharingapp/service/PaymentService.java @@ -1,10 +1,11 @@ package com.project.carsharingapp.service; import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; -import com.project.carsharingapp.dto.payment.PaymentResponseDto; import com.project.carsharingapp.model.Payment; public interface PaymentService { Payment create(CreatePaymentSessionRequestDto requestDto); + Payment updateStatus(String sessionId); + } diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java index f70a70d..66d46c1 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java @@ -36,6 +36,15 @@ public Payment create(CreatePaymentSessionRequestDto requestDto) { } } + @Override + public Payment updateStatus(String sessionId) { + Payment payment = paymentRepository.findBySessionId(sessionId).orElseThrow( + () -> new EntityNotFoundException("Can't find a Payment by the session") + ); + payment.setStatus(Payment.Status.PAID); + return paymentRepository.save(payment); + } + private Payment generatePayment(Session session, Rental rental, Payment.Type type) { Payment payment = new Payment(); payment.setStatus(Payment.Status.PENDING); diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java index 5e6988b..11c7c6b 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -25,6 +25,7 @@ @RequiredArgsConstructor public class StripeService { private static final String DEFAULT_URL_PART = "/api/payments"; + private static final String SUCCESS_ENDPOINT = "success"; private static final String CANCEL_ENDPOINT = "cancel"; private static final Long STANDARD_QUANTITY_OF_RENTAL_CART = 1L; @@ -76,8 +77,8 @@ private String createUrl(String type) { .host(host) .port(port) .path(DEFAULT_URL_PART + "/" + type) + .query("sessionId={CHECKOUT_SESSION_ID}") .build() - .encode() .toUriString(); } From 62657c54a9e611b4505c1a97532f4040f44d9c06 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 19:08:04 +0300 Subject: [PATCH 06/12] added swagger to the payment controller and fixed checkstyle issues --- pom.xml | 5 -- .../controller/CarController.java | 2 +- .../controller/PaymentController.java | 22 ++++++-- .../controller/UserController.java | 2 +- .../dto/car/CreateCarRequestDto.java | 6 +-- .../dto/car/UpdateCarRequestDto.java | 6 +-- .../CreatePaymentSessionRequestDto.java | 2 +- .../dto/user/UpdateUserProfileRequestDto.java | 2 +- .../dto/user/UpdateUserRoleRequestDto.java | 2 +- .../com/project/carsharingapp/model/Car.java | 2 +- .../repository/PaymentRepository.java | 7 ++- .../repository/RentalRepository.java | 4 +- .../carsharingapp/service/PaymentService.java | 4 ++ .../service/impl/PaymentServiceImpl.java | 8 +++ .../service/impl/StripeService.java | 8 +-- src/main/resources/application.properties | 2 +- .../com/project/carsharingapp/StripeTest.java | 52 ------------------- 17 files changed, 50 insertions(+), 86 deletions(-) delete mode 100644 src/test/java/com/project/carsharingapp/StripeTest.java diff --git a/pom.xml b/pom.xml index fd2a0a0..7d87086 100644 --- a/pom.xml +++ b/pom.xml @@ -77,11 +77,6 @@ mapstruct ${mapstruct.version} - - jakarta.validation - jakarta.validation-api - 2.0.2 - com.stripe stripe-java diff --git a/src/main/java/com/project/carsharingapp/controller/CarController.java b/src/main/java/com/project/carsharingapp/controller/CarController.java index fcbe3f1..e2c6c17 100644 --- a/src/main/java/com/project/carsharingapp/controller/CarController.java +++ b/src/main/java/com/project/carsharingapp/controller/CarController.java @@ -5,8 +5,8 @@ import com.project.carsharingapp.dto.car.UpdateCarRequestDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import java.util.List; -import javax.validation.Valid; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.DeleteMapping; diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index ac1378a..0df60e0 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -1,17 +1,25 @@ package com.project.carsharingapp.controller; import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; -import com.project.carsharingapp.dto.payment.PaymentResponseDto; import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.service.PaymentService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import java.net.URI; import java.util.List; -import javax.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +@Tag(name = "Payment controller", description = "Endpoint for managing payments") @RestController @RequestMapping("/payments") @RequiredArgsConstructor @@ -19,11 +27,13 @@ public class PaymentController { private final PaymentService paymentService; @GetMapping - public List getAll() { - return List.of(); + @Operation(summary = "Get all user's payments") + public List getAll(Pageable pageable) { + return paymentService.getAll(pageable); } @PostMapping + @Operation(summary = "Create a new payment session") public ResponseEntity create( @RequestBody @Valid CreatePaymentSessionRequestDto requestDto ) { @@ -33,12 +43,14 @@ public ResponseEntity create( } @GetMapping("/success") + @Operation(summary = "Redirect endpoint in case of successful payment") private String redirectToSuccessPage(@RequestParam String sessionId) { paymentService.updateStatus(sessionId); return "success"; } @GetMapping("/cancel") + @Operation(summary = "Redirect endpoint in case of paused payment") private String redirectToFailedPage() { return "cancel"; } diff --git a/src/main/java/com/project/carsharingapp/controller/UserController.java b/src/main/java/com/project/carsharingapp/controller/UserController.java index 762b32e..597fb15 100644 --- a/src/main/java/com/project/carsharingapp/controller/UserController.java +++ b/src/main/java/com/project/carsharingapp/controller/UserController.java @@ -5,7 +5,7 @@ import com.project.carsharingapp.dto.user.UserDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import javax.validation.Valid; +import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; diff --git a/src/main/java/com/project/carsharingapp/dto/car/CreateCarRequestDto.java b/src/main/java/com/project/carsharingapp/dto/car/CreateCarRequestDto.java index f171051..7aa03a2 100644 --- a/src/main/java/com/project/carsharingapp/dto/car/CreateCarRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/car/CreateCarRequestDto.java @@ -1,10 +1,10 @@ package com.project.carsharingapp.dto.car; import com.project.carsharingapp.model.Car; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import org.hibernate.validator.constraints.Length; diff --git a/src/main/java/com/project/carsharingapp/dto/car/UpdateCarRequestDto.java b/src/main/java/com/project/carsharingapp/dto/car/UpdateCarRequestDto.java index fb7367a..ab91820 100644 --- a/src/main/java/com/project/carsharingapp/dto/car/UpdateCarRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/car/UpdateCarRequestDto.java @@ -1,10 +1,10 @@ package com.project.carsharingapp.dto.car; import com.project.carsharingapp.model.Car; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import org.hibernate.validator.constraints.Length; diff --git a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java index 8557115..d8cbde3 100644 --- a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java @@ -1,6 +1,6 @@ package com.project.carsharingapp.dto.payment; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import lombok.Data; @Data diff --git a/src/main/java/com/project/carsharingapp/dto/user/UpdateUserProfileRequestDto.java b/src/main/java/com/project/carsharingapp/dto/user/UpdateUserProfileRequestDto.java index de4b766..899e835 100644 --- a/src/main/java/com/project/carsharingapp/dto/user/UpdateUserProfileRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/user/UpdateUserProfileRequestDto.java @@ -1,6 +1,6 @@ package com.project.carsharingapp.dto.user; -import javax.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; import lombok.Setter; import org.hibernate.validator.constraints.Length; diff --git a/src/main/java/com/project/carsharingapp/dto/user/UpdateUserRoleRequestDto.java b/src/main/java/com/project/carsharingapp/dto/user/UpdateUserRoleRequestDto.java index 453cbd1..7c83deb 100644 --- a/src/main/java/com/project/carsharingapp/dto/user/UpdateUserRoleRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/user/UpdateUserRoleRequestDto.java @@ -1,7 +1,7 @@ package com.project.carsharingapp.dto.user; import com.project.carsharingapp.model.RoleName; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/project/carsharingapp/model/Car.java b/src/main/java/com/project/carsharingapp/model/Car.java index 0d289ca..a924367 100644 --- a/src/main/java/com/project/carsharingapp/model/Car.java +++ b/src/main/java/com/project/carsharingapp/model/Car.java @@ -8,8 +8,8 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; +import jakarta.validation.constraints.PositiveOrZero; import java.math.BigDecimal; -import javax.validation.constraints.PositiveOrZero; import lombok.Getter; import lombok.Setter; import org.hibernate.annotations.SQLDelete; diff --git a/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java b/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java index 0fb1562..00b0fec 100644 --- a/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java +++ b/src/main/java/com/project/carsharingapp/repository/PaymentRepository.java @@ -1,10 +1,13 @@ package com.project.carsharingapp.repository; import com.project.carsharingapp.model.Payment; -import org.springframework.data.jpa.repository.JpaRepository; - import java.util.Optional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; public interface PaymentRepository extends JpaRepository { Optional findBySessionId(String sessionId); + + Page findAll(Pageable pageable); } diff --git a/src/main/java/com/project/carsharingapp/repository/RentalRepository.java b/src/main/java/com/project/carsharingapp/repository/RentalRepository.java index 78ce9ef..8ddb1a0 100644 --- a/src/main/java/com/project/carsharingapp/repository/RentalRepository.java +++ b/src/main/java/com/project/carsharingapp/repository/RentalRepository.java @@ -1,11 +1,9 @@ package com.project.carsharingapp.repository; import com.project.carsharingapp.model.Rental; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; - -import java.util.Optional; public interface RentalRepository extends JpaRepository { @Query("FROM Rental r LEFT JOIN FETCH r.car " diff --git a/src/main/java/com/project/carsharingapp/service/PaymentService.java b/src/main/java/com/project/carsharingapp/service/PaymentService.java index 8f45244..86e0894 100644 --- a/src/main/java/com/project/carsharingapp/service/PaymentService.java +++ b/src/main/java/com/project/carsharingapp/service/PaymentService.java @@ -2,10 +2,14 @@ import com.project.carsharingapp.dto.payment.CreatePaymentSessionRequestDto; import com.project.carsharingapp.model.Payment; +import java.util.List; +import org.springframework.data.domain.Pageable; public interface PaymentService { Payment create(CreatePaymentSessionRequestDto requestDto); Payment updateStatus(String sessionId); + List getAll(Pageable pageable); + } diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java index 66d46c1..84ce93c 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentServiceImpl.java @@ -10,7 +10,10 @@ import com.stripe.exception.StripeException; import com.stripe.model.checkout.Session; import java.math.BigDecimal; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @Service @@ -45,6 +48,11 @@ public Payment updateStatus(String sessionId) { return paymentRepository.save(payment); } + @Override + public List getAll(Pageable pageable) { + return paymentRepository.findAll(pageable).stream().collect(Collectors.toList()); + } + private Payment generatePayment(Session session, Rental rental, Payment.Type type) { Payment payment = new Payment(); payment.setStatus(Payment.Status.PENDING); diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java index 11c7c6b..c8351b7 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -1,21 +1,16 @@ package com.project.carsharingapp.service.impl; -import com.project.carsharingapp.model.Car; import com.project.carsharingapp.model.Payment; import com.project.carsharingapp.model.Rental; import com.project.carsharingapp.service.PaymentAmountHandler; import com.stripe.Stripe; import com.stripe.exception.StripeException; -import com.stripe.model.Price; -import com.stripe.model.Product; import com.stripe.model.checkout.Session; import com.stripe.param.checkout.SessionCreateParams; import jakarta.annotation.PostConstruct; import java.math.BigDecimal; import java.time.LocalDate; import java.time.Period; -import java.util.Map; - import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -56,7 +51,8 @@ public Session createSession(Rental rental, Payment.Type type) throws StripeExce SessionCreateParams.LineItem.PriceData.builder() .setCurrency(DEFAULT_CURRENCY) .setProductData( - SessionCreateParams.LineItem.PriceData.ProductData.builder() + SessionCreateParams.LineItem.PriceData + .ProductData.builder() .setName(productName) .build() ) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 920190e..fbcdbbc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.datasource.url=jdbc:mysql://localhost:3306/car_sharing_db?serverTimezone=UTC spring.datasource.username=root -spring.datasource.password=redblack0root +spring.datasource.password=root123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver server.servlet.context-path=/api diff --git a/src/test/java/com/project/carsharingapp/StripeTest.java b/src/test/java/com/project/carsharingapp/StripeTest.java deleted file mode 100644 index 82c82b7..0000000 --- a/src/test/java/com/project/carsharingapp/StripeTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.project.carsharingapp; - -import com.stripe.Stripe; -import com.stripe.exception.StripeException; -import com.stripe.model.PaymentIntent; -import com.stripe.model.Price; -import com.stripe.model.checkout.Session; -import com.stripe.param.PaymentIntentCreateParams; -import com.stripe.param.checkout.SessionCreateParams; -import org.junit.jupiter.api.Test; - - -public class StripeTest { - - @Test - public void test() throws StripeException { - Stripe.apiKey = "sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwyBNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI"; - - SessionCreateParams params = SessionCreateParams.builder() - .setMode(SessionCreateParams.Mode.PAYMENT) - .setSuccessUrl("http://localhost:8080/success") - .setCancelUrl("http://localhost:8080/success") - .addLineItem( - SessionCreateParams.LineItem.builder() - .setPriceData( - SessionCreateParams.LineItem.PriceData.builder() - .setCurrency("USD") - .setProductData( - SessionCreateParams.LineItem.PriceData.ProductData.builder() - .putAllExtraParam(null) - .build() - ) - .setUnitAmount(1L) - .build() - ) - .setQuantity(1L) // todo quantity - .build() - ) - .build(); - - Session session = Session.create(params); - -// PaymentIntentCreateParams params = -// PaymentIntentCreateParams.builder() -// .setAmount(1099L) -// .setCurrency("usd") -// .addPaymentMethodType("card") -// .build(); -// PaymentIntent test = PaymentIntent.create(params); -// System.out.println(test); - } -} From 0b203a5e68a4792591ca99ec8f79ff5e0d210dfa Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 19:08:47 +0300 Subject: [PATCH 07/12] added an option for easy testing --- .../com/project/carsharingapp/controller/PaymentController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index 0df60e0..6d664d7 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -39,6 +39,7 @@ public ResponseEntity create( ) { Payment payment = paymentService.create(requestDto); URI url = URI.create(payment.getSessionUrl()); + System.out.println(url); return ResponseEntity.status(HttpStatus.FOUND).location(url).build(); } From 0a8b36c46fd3b30267430e5e61aea5920453f8d5 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Tue, 3 Oct 2023 20:04:22 +0300 Subject: [PATCH 08/12] adjusted test properties file --- pom.xml | 1 - src/main/resources/application.properties | 5 +++-- src/test/resources/application.properties | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 7d87086..1aa2bd3 100644 --- a/pom.xml +++ b/pom.xml @@ -153,5 +153,4 @@ - diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index fbcdbbc..415e579 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.datasource.url=jdbc:mysql://localhost:3306/car_sharing_db?serverTimezone=UTC spring.datasource.username=root -spring.datasource.password=root123 +spring.datasource.password=redblack0root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver server.servlet.context-path=/api @@ -8,6 +8,7 @@ spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true spring.jpa.open-in-view=false -stripe.secret=sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwyBNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI +stripe.secret=sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwy\ + BNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI app.host=localhost app.port=8080 diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index bc2fdde..8d670bf 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -3,3 +3,8 @@ spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect + +stripe.secret=sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwy\ + BNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI +app.host=localhost +app.port=8080 From 422d6d0808733710e6af0ef970cc1823b5857af0 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk <119531944+ivan0dyatlyukkk@users.noreply.github.com> Date: Tue, 3 Oct 2023 20:10:26 +0300 Subject: [PATCH 09/12] Update application.properties --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 415e579..06beab8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.datasource.url=jdbc:mysql://localhost:3306/car_sharing_db?serverTimezone=UTC spring.datasource.username=root -spring.datasource.password=redblack0root +spring.datasource.password=root123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver server.servlet.context-path=/api From 425ad4e802c850e6989d7a8d59388d611e096ec6 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk <119531944+ivan0dyatlyukkk@users.noreply.github.com> Date: Tue, 3 Oct 2023 20:11:25 +0300 Subject: [PATCH 10/12] Updated PaymentAmountHandlerStrategy.java --- .../service/impl/PaymentAmountHandlerStrategy.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java b/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java index 1b96abf..24551ab 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java +++ b/src/main/java/com/project/carsharingapp/service/impl/PaymentAmountHandlerStrategy.java @@ -20,7 +20,5 @@ public PaymentAmountHandler getHandler(Payment.Type type) { new NoSuchElementException("Can't find a PaymentAmountHandler " + "for such type as: " + type) ); - } - } From 1506abdb21e239cd94df10949384c33defef90d3 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk <119531944+ivan0dyatlyukkk@users.noreply.github.com> Date: Tue, 3 Oct 2023 20:11:45 +0300 Subject: [PATCH 11/12] Updated PaymentService.java --- .../java/com/project/carsharingapp/service/PaymentService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/project/carsharingapp/service/PaymentService.java b/src/main/java/com/project/carsharingapp/service/PaymentService.java index 86e0894..2607316 100644 --- a/src/main/java/com/project/carsharingapp/service/PaymentService.java +++ b/src/main/java/com/project/carsharingapp/service/PaymentService.java @@ -11,5 +11,4 @@ public interface PaymentService { Payment updateStatus(String sessionId); List getAll(Pageable pageable); - } From 573167535e64a76320b3ba49e3a2593f51c6f1d8 Mon Sep 17 00:00:00 2001 From: Ivan Diatliuk Date: Wed, 4 Oct 2023 12:07:06 +0300 Subject: [PATCH 12/12] fixed small mistakes --- .../carsharingapp/controller/PaymentController.java | 12 +++--------- .../dto/payment/CreatePaymentSessionRequestDto.java | 6 ++++-- .../carsharingapp/service/impl/StripeService.java | 2 +- src/main/resources/application.properties | 3 ++- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/project/carsharingapp/controller/PaymentController.java b/src/main/java/com/project/carsharingapp/controller/PaymentController.java index 6d664d7..6bc634f 100644 --- a/src/main/java/com/project/carsharingapp/controller/PaymentController.java +++ b/src/main/java/com/project/carsharingapp/controller/PaymentController.java @@ -6,12 +6,9 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.net.URI; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -19,7 +16,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -@Tag(name = "Payment controller", description = "Endpoint for managing payments") +@Tag(name = "Payment management", description = "Endpoint for managing payments") @RestController @RequestMapping("/payments") @RequiredArgsConstructor @@ -34,13 +31,10 @@ public List getAll(Pageable pageable) { @PostMapping @Operation(summary = "Create a new payment session") - public ResponseEntity create( + public Payment create( @RequestBody @Valid CreatePaymentSessionRequestDto requestDto ) { - Payment payment = paymentService.create(requestDto); - URI url = URI.create(payment.getSessionUrl()); - System.out.println(url); - return ResponseEntity.status(HttpStatus.FOUND).location(url).build(); + return paymentService.create(requestDto); } @GetMapping("/success") diff --git a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java index d8cbde3..47450f2 100644 --- a/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java +++ b/src/main/java/com/project/carsharingapp/dto/payment/CreatePaymentSessionRequestDto.java @@ -1,9 +1,11 @@ package com.project.carsharingapp.dto.payment; import jakarta.validation.constraints.NotNull; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; -@Data +@Getter +@Setter public class CreatePaymentSessionRequestDto { @NotNull private Long rentalId; diff --git a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java index c8351b7..8b33ad8 100644 --- a/src/main/java/com/project/carsharingapp/service/impl/StripeService.java +++ b/src/main/java/com/project/carsharingapp/service/impl/StripeService.java @@ -20,11 +20,11 @@ @RequiredArgsConstructor public class StripeService { private static final String DEFAULT_URL_PART = "/api/payments"; - private static final String SUCCESS_ENDPOINT = "success"; private static final String CANCEL_ENDPOINT = "cancel"; private static final Long STANDARD_QUANTITY_OF_RENTAL_CART = 1L; private static final String DEFAULT_CURRENCY = "USD"; + private final PaymentAmountHandlerStrategy handler; @Value("${stripe.secret}") private String secretKey; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 415e579..f7457e9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,6 @@ spring.datasource.url=jdbc:mysql://localhost:3306/car_sharing_db?serverTimezone=UTC spring.datasource.username=root -spring.datasource.password=redblack0root +spring.datasource.password=root123 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver server.servlet.context-path=/api @@ -8,6 +8,7 @@ spring.jpa.hibernate.ddl-auto=validate spring.jpa.show-sql=true spring.jpa.open-in-view=false + stripe.secret=sk_test_51NwluPLODs6ppc0Lt4vFUOmyqkOeMpnbizJwy\ BNFWQ0Y2rL79OtqPtydVF11PD2WoXiIkxCc3IrThcvWZkOmmn1e00ST12M2PI app.host=localhost