Integrate simple payment handling with WebClient and persist results
This commit is contained in:
5
pom.xml
5
pom.xml
@@ -73,6 +73,11 @@
|
|||||||
<artifactId>jakarta.validation-api</artifactId>
|
<artifactId>jakarta.validation-api</artifactId>
|
||||||
<version>3.1.0</version>
|
<version>3.1.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package _11.asktpk.artisanconnectbackend.controller;
|
package _11.asktpk.artisanconnectbackend.controller;
|
||||||
|
|
||||||
import _11.asktpk.artisanconnectbackend.dto.ClientDTO;
|
import _11.asktpk.artisanconnectbackend.dto.*;
|
||||||
import _11.asktpk.artisanconnectbackend.dto.OrderDTO;
|
import _11.asktpk.artisanconnectbackend.entities.Order;
|
||||||
import _11.asktpk.artisanconnectbackend.dto.OrderStatusDTO;
|
import _11.asktpk.artisanconnectbackend.service.ClientService;
|
||||||
import _11.asktpk.artisanconnectbackend.service.OrderService;
|
import _11.asktpk.artisanconnectbackend.service.OrderService;
|
||||||
|
import _11.asktpk.artisanconnectbackend.service.PaymentService;
|
||||||
import _11.asktpk.artisanconnectbackend.utils.Enums;
|
import _11.asktpk.artisanconnectbackend.utils.Enums;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -14,9 +15,11 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
public class OrderController {
|
public class OrderController {
|
||||||
|
|
||||||
private final OrderService orderService;
|
private final OrderService orderService;
|
||||||
|
private final PaymentService paymentService;
|
||||||
|
|
||||||
public OrderController(OrderService orderService) {
|
public OrderController(OrderService orderService, PaymentService paymentService) {
|
||||||
this.orderService = orderService;
|
this.orderService = orderService;
|
||||||
|
this.paymentService = paymentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/add")
|
@PostMapping("/add")
|
||||||
@@ -28,4 +31,21 @@ public class OrderController {
|
|||||||
public ResponseEntity changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) {
|
public ResponseEntity changeStatus(@RequestBody OrderStatusDTO orderStatusDTO) {
|
||||||
return new ResponseEntity<>(orderService.changeOrderStatus(orderStatusDTO.getId(),orderStatusDTO.getStatus()), HttpStatus.OK);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -41,6 +41,6 @@ public class Notice {
|
|||||||
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL)
|
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL)
|
||||||
private List<Order> orders;
|
private List<Order> orders;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "notice", cascade = CascadeType.ALL)
|
// @OneToMany(mappedBy = "notice", cascade = CascadeType.ALL)
|
||||||
private List<Payments> payments;
|
// private List<Payment> payment;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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<Payment, Long> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -71,4 +71,9 @@ public class OrderService {
|
|||||||
return order.getId();
|
return order.getId();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Order getOrderById(Long id) {
|
||||||
|
return orderRepository.findById(id)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Nie znaleziono zamówienia o ID: " + id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,4 +19,7 @@ spring.servlet.multipart.max-file-size=10MB
|
|||||||
spring.servlet.multipart.max-request-size=10MB
|
spring.servlet.multipart.max-request-size=10MB
|
||||||
|
|
||||||
tpay.clientId = 01JQKC048X62ST9V59HNRSXD92-01JQKC2CQHPYXQFSFX8BKC24BX
|
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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user