diff --git a/pom.xml b/pom.xml index ae0b196..d6ef542 100644 --- a/pom.xml +++ b/pom.xml @@ -73,6 +73,11 @@ jakarta.validation-api 3.1.0 + + org.springframework.boot + spring-boot-starter-webflux + + diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java b/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java index bbea5db..f557e3b 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/controller/OrderController.java @@ -1,9 +1,10 @@ package _11.asktpk.artisanconnectbackend.controller; -import _11.asktpk.artisanconnectbackend.dto.ClientDTO; -import _11.asktpk.artisanconnectbackend.dto.OrderDTO; -import _11.asktpk.artisanconnectbackend.dto.OrderStatusDTO; +import _11.asktpk.artisanconnectbackend.dto.*; +import _11.asktpk.artisanconnectbackend.entities.Order; +import _11.asktpk.artisanconnectbackend.service.ClientService; import _11.asktpk.artisanconnectbackend.service.OrderService; +import _11.asktpk.artisanconnectbackend.service.PaymentService; import _11.asktpk.artisanconnectbackend.utils.Enums; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -14,9 +15,11 @@ import org.springframework.web.bind.annotation.*; public class OrderController { private final OrderService orderService; + private final PaymentService paymentService; - public OrderController(OrderService orderService) { + public OrderController(OrderService orderService, PaymentService paymentService) { this.orderService = orderService; + this.paymentService = paymentService; } @PostMapping("/add") @@ -28,4 +31,21 @@ public class OrderController { public ResponseEntity changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) { return new ResponseEntity<>(orderService.changeOrderStatus(orderStatusDTO.getId(),orderStatusDTO.getStatus()), HttpStatus.OK); } + + @PostMapping("/token") + public ResponseEntity fetchToken() { + Order order = orderService.getOrderById(1L); + OAuthPaymentResponseDTO authPaymentDTO= paymentService.getOAuthToken(); + TransactionPaymentRequestDTO.Payer payer = new TransactionPaymentRequestDTO.Payer( + "patryk@test.pl", "Patryk Test"); + + String paymentDescription = order.getOrderType() == Enums.OrderType.ACTIVATION ? "Aktywacja ogłoszenia" : "Podbicie ogłoszenia"; + paymentDescription += order.getNotice().getTitle(); + TransactionPaymentRequestDTO request = new TransactionPaymentRequestDTO( + order.getAmount(), paymentDescription, payer); + String response = paymentService.createTransaction(order,authPaymentDTO.getAccess_token(), request); + System.out.println(response); + + return ResponseEntity.ok(authPaymentDTO.getAccess_token()); + } } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/OAuthPaymentResponseDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/OAuthPaymentResponseDTO.java new file mode 100644 index 0000000..a021310 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/OAuthPaymentResponseDTO.java @@ -0,0 +1,15 @@ +package _11.asktpk.artisanconnectbackend.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class OAuthPaymentResponseDTO { + private long issued_at; + private String scope; + private String token_type; + private int expires_in; + private String client_id; + private String access_token; +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/TransactionPaymentRequestDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/TransactionPaymentRequestDTO.java new file mode 100644 index 0000000..8ef1123 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/TransactionPaymentRequestDTO.java @@ -0,0 +1,25 @@ +package _11.asktpk.artisanconnectbackend.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class TransactionPaymentRequestDTO { + private double amount; + private String description; + private Payer payer; + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class Payer { + private String email; + private String name; + } +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/dto/TransactionPaymentResponseDTO.java b/src/main/java/_11/asktpk/artisanconnectbackend/dto/TransactionPaymentResponseDTO.java new file mode 100644 index 0000000..909219f --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/dto/TransactionPaymentResponseDTO.java @@ -0,0 +1,59 @@ +package _11.asktpk.artisanconnectbackend.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.Getter; +import lombok.Setter; + + @Getter + @Setter + @JsonIgnoreProperties(ignoreUnknown = true) + public class TransactionPaymentResponseDTO { + private String result; + private String requestId; + private String transactionId; + private String title; + private String posId; + private String status; + private DateInfo date; + private double amount; + private String currency; + private String description; + private String hiddenDescription; + private Payer payer; + private Payments payments; + private String transactionPaymentUrl; + + @Getter + @Setter + @JsonIgnoreProperties(ignoreUnknown = true) + public static class DateInfo { + private String creation; + private String realization; + } + + @Getter + @Setter + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Payer { + private String payerId; + private String email; + private String name; + private String phone; + private String address; + private String city; + private String country; + private String postalCode; + } + + @Getter + @Setter + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Payments { + private String status; + private String method; + private double amountPaid; + private DateInfo date; + } + } + + diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java index 14c4119..2d6bb56 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Notice.java @@ -41,6 +41,6 @@ public class Notice { @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) private List orders; - @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) - private List payments; +// @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL) +// private List payment; } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Payment.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Payment.java new file mode 100644 index 0000000..0618e49 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Payment.java @@ -0,0 +1,30 @@ +package _11.asktpk.artisanconnectbackend.entities; + +import _11.asktpk.artisanconnectbackend.utils.Enums; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Table(name = "payment") +@Getter @Setter +public class Payment { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long idPayment; + + @ManyToOne + @JoinColumn(name = "id_order") + private Order order; + + private Double amount; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private Enums.PaymentStatus status; + + private String transactionPaymentUrl; + + private String transactionId; +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Payments.java b/src/main/java/_11/asktpk/artisanconnectbackend/entities/Payments.java deleted file mode 100644 index 06efb18..0000000 --- a/src/main/java/_11/asktpk/artisanconnectbackend/entities/Payments.java +++ /dev/null @@ -1,30 +0,0 @@ -package _11.asktpk.artisanconnectbackend.entities; - -import _11.asktpk.artisanconnectbackend.utils.Enums.Status; - -import jakarta.persistence.*; - -@Entity -@Table(name = "payments") -public class Payments { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long idPayment; - - @ManyToOne - @JoinColumn(name = "id_order") - private Order order; - - @ManyToOne - @JoinColumn(name = "id_notice") - private Notice notice; - - private Double noticePublishPrice; - - @Enumerated(EnumType.STRING) - private Status status; - - private String sessionId; - - // Getters, setters, and constructors -} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java b/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java new file mode 100644 index 0000000..922dc58 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/repository/PaymentRepository.java @@ -0,0 +1,10 @@ +package _11.asktpk.artisanconnectbackend.repository; + +import _11.asktpk.artisanconnectbackend.entities.Payment; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PaymentRepository extends JpaRepository { + +} diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java index 8e74861..5a97f98 100644 --- a/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/OrderService.java @@ -71,4 +71,9 @@ public class OrderService { return order.getId(); } + + public Order getOrderById(Long id) { + return orderRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Nie znaleziono zamówienia o ID: " + id)); + } } diff --git a/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java b/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java new file mode 100644 index 0000000..f0640e2 --- /dev/null +++ b/src/main/java/_11/asktpk/artisanconnectbackend/service/PaymentService.java @@ -0,0 +1,81 @@ +package _11.asktpk.artisanconnectbackend.service; + +import _11.asktpk.artisanconnectbackend.dto.OAuthPaymentResponseDTO; +import _11.asktpk.artisanconnectbackend.dto.TransactionPaymentRequestDTO; +import _11.asktpk.artisanconnectbackend.dto.TransactionPaymentResponseDTO; +import _11.asktpk.artisanconnectbackend.entities.Order; +import _11.asktpk.artisanconnectbackend.entities.Payment; +import _11.asktpk.artisanconnectbackend.repository.PaymentRepository; +import _11.asktpk.artisanconnectbackend.utils.Enums; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +@Service +public class PaymentService { + private final WebClient webClient; + private final String clientId; + private final String clientSecret; + private final String authUrl; + private final String transactionUrl; + private final PaymentRepository paymentRepository; + + public PaymentService( + WebClient.Builder webClientBuilder, + @Value("${tpay.clientId}") String clientId, + @Value("${tpay.clientSecret}") String clientSecret, + @Value("${tpay.authUrl}") String authUrl, + @Value("${tpay.transactionUrl}") String transactionUrl, + PaymentRepository paymentRepository + ) { + this.webClient = webClientBuilder.baseUrl(authUrl).build(); + this.clientId = clientId; + this.clientSecret = clientSecret; + this.authUrl = authUrl; + this.transactionUrl = transactionUrl; + this.paymentRepository = paymentRepository; + } + + public OAuthPaymentResponseDTO getOAuthToken() { + return webClient.post() + .uri("") + .contentType(MediaType.MULTIPART_FORM_DATA) + .header("accept", "application/json") + .body(BodyInserters.fromMultipartData("client_id", clientId) + .with("client_secret", clientSecret)) + .retrieve() + .bodyToMono(OAuthPaymentResponseDTO.class) + .block(); + } + + public String createTransaction(Order order, String accessToken, TransactionPaymentRequestDTO transactionPaymentRequestDTO) { + TransactionPaymentResponseDTO response = webClient.post() + .uri(transactionUrl) + .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(transactionPaymentRequestDTO) + .retrieve() + .bodyToMono(TransactionPaymentResponseDTO.class) + .block(); + + if (response != null && "success".equalsIgnoreCase(response.getResult())) { + Payment payment = new Payment(); + payment.setOrder(order); + payment.setAmount(response.getAmount()); + + payment.setStatus(Enums.PaymentStatus.PENDING); + + payment.setTransactionId(response.getTransactionId()); + payment.setTransactionPaymentUrl(response.getTransactionPaymentUrl()); + paymentRepository.save(payment); + + return response.getTransactionPaymentUrl(); + } + + return null; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a2c0be0..ca1826a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -19,4 +19,7 @@ spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB tpay.clientId = 01JQKC048X62ST9V59HNRSXD92-01JQKC2CQHPYXQFSFX8BKC24BX -tpay.secret = e701f2feee2b9c967bf3e67a4e71c76377701f4b1e9d92f6af2e75c97e7df210 +tpay.clientSecret = 44898642be53381cdcc47f3e44bf5a15e592f5d270fc3a6cf6fb81a8b8ebffb9 +tpay.authUrl = https://openapi.sandbox.tpay.com/oauth/auth +tpay.transactionUrl = https://openapi.sandbox.tpay.com/transactions +