Skip to content

Commit c4d067c

Browse files
committed
update payment service
1 parent 671d26e commit c4d067c

File tree

16 files changed

+632
-177
lines changed

16 files changed

+632
-177
lines changed

payment-service/pom.xml

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@
1818
<spring-cloud.version>2021.0.8</spring-cloud.version>
1919
</properties>
2020
<dependencies>
21+
<dependency>
22+
<groupId>io.springfox</groupId>
23+
<artifactId>springfox-boot-starter</artifactId>
24+
<version>3.0.0</version>
25+
</dependency>
26+
<dependency>
27+
<groupId>io.springfox</groupId>
28+
<artifactId>springfox-swagger2</artifactId>
29+
<version>3.0.0</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>io.springfox</groupId>
33+
<artifactId>springfox-swagger-ui</artifactId>
34+
<version>3.0.0</version>
35+
</dependency>
2136
<dependency>
2237
<groupId>org.springframework.boot</groupId>
2338
<artifactId>spring-boot-starter-data-jpa</artifactId>
@@ -34,7 +49,6 @@
3449
<groupId>org.springframework.cloud</groupId>
3550
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
3651
</dependency>
37-
3852
<dependency>
3953
<groupId>org.springframework.boot</groupId>
4054
<artifactId>spring-boot-devtools</artifactId>
@@ -74,6 +88,30 @@
7488
<artifactId>modelmapper</artifactId>
7589
<version>2.3.0</version>
7690
</dependency>
91+
<dependency>
92+
<groupId>org.springframework.boot</groupId>
93+
<artifactId>spring-boot-starter-security</artifactId>
94+
</dependency>
95+
<dependency>
96+
<groupId>io.jsonwebtoken</groupId>
97+
<artifactId>jjwt</artifactId>
98+
<version>0.9.1</version>
99+
<scope>compile</scope>
100+
</dependency>
101+
<dependency>
102+
<groupId>io.jsonwebtoken</groupId>
103+
<artifactId>jjwt-api</artifactId>
104+
<version>0.11.5</version>
105+
<scope>compile</scope>
106+
</dependency>
107+
<dependency>
108+
<groupId>org.springframework.boot</groupId>
109+
<artifactId>spring-boot-actuator</artifactId>
110+
</dependency>
111+
<dependency>
112+
<groupId>org.springframework.boot</groupId>
113+
<artifactId>spring-boot-actuator-autoconfigure</artifactId>
114+
</dependency>
77115
</dependencies>
78116
<dependencyManagement>
79117
<dependencies>
Lines changed: 102 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,143 @@
11
package com.hoangtien2k3.paymentservice.api;
22

33
import com.hoangtien2k3.paymentservice.dto.PaymentDto;
4-
import com.hoangtien2k3.paymentservice.dto.response.collection.DtoCollectionResponse;
5-
import com.hoangtien2k3.paymentservice.security.JwtValidate;
64
import com.hoangtien2k3.paymentservice.service.PaymentService;
5+
import io.swagger.annotations.ApiOperation;
6+
import io.swagger.annotations.ApiResponse;
7+
import io.swagger.annotations.ApiResponses;
78
import lombok.RequiredArgsConstructor;
89
import lombok.extern.slf4j.Slf4j;
9-
import org.apache.http.HttpStatus;
1010
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.data.domain.Page;
12+
import org.springframework.http.HttpStatus;
1113
import org.springframework.http.ResponseEntity;
14+
import org.springframework.security.access.prepost.PreAuthorize;
1215
import org.springframework.web.bind.annotation.*;
1316
import reactor.core.publisher.Mono;
1417

1518
import javax.validation.Valid;
1619
import javax.validation.constraints.NotBlank;
1720
import javax.validation.constraints.NotNull;
21+
import java.util.Collections;
1822
import java.util.List;
1923

20-
@Slf4j
21-
@RequiredArgsConstructor
2224
@RestController
2325
@RequestMapping("/api/payments")
26+
@Slf4j
27+
@RequiredArgsConstructor
2428
public class PaymentController {
2529

2630
@Autowired
2731
private final PaymentService paymentService;
28-
@Autowired
29-
private final JwtValidate jwtValidate;
3032

33+
@ApiOperation(value = "Get all payment", notes = "Retrieve a list of all payment.")
34+
@ApiResponses({
35+
@ApiResponse(code = 200, message = "Payments retrieved successfully", response = List.class),
36+
@ApiResponse(code = 204, message = "No content", response = ResponseEntity.class)
37+
})
3138
@GetMapping
32-
public ResponseEntity<DtoCollectionResponse<PaymentDto>> findAll() {
33-
log.info("PaymentDto List, controller; fetch all payments");
34-
return ResponseEntity.ok(new DtoCollectionResponse<>(this.paymentService.findAll()));
39+
@PreAuthorize("hasAuthority('ADMIN')")
40+
public Mono<ResponseEntity<List<PaymentDto>>> findAll() {
41+
log.info("*** PaymentDto List, controller; fetch all categories *");
42+
return paymentService.findAll()
43+
.map(ResponseEntity::ok)
44+
.defaultIfEmpty(ResponseEntity.ok(Collections.emptyList()));
3545
}
3646

37-
// @GetMapping
38-
// public ResponseEntity<DtoCollectionResponse<PaymentDto>> findAll() {
39-
// log.info("PaymentDto List, controller; fetch all payments");
40-
//
41-
// // Gọi phương thức findAll() từ PaymentService để lấy danh sách PaymentDto
42-
// List<PaymentDto> paymentDtos = this.paymentService.findAll();
43-
//
44-
// // Trả về danh sách PaymentDto trong ResponseEntity
45-
// return ResponseEntity.ok(new DtoCollectionResponse<>(paymentDtos));
46-
// }
47-
48-
@GetMapping("/inventory-test")
49-
@ResponseBody
50-
public Mono<ResponseEntity<List<String>>> callServiceB() {
51-
String serviceBUrl = "http://localhost:8083/api/inventory?productName=iphone_13,iphone_13_red";
52-
53-
return paymentService.callServiceB(serviceBUrl)
47+
@ApiOperation(value = "Get all payments with paging", notes = "Retrieve a paginated list of all payments.")
48+
@ApiResponses({
49+
@ApiResponse(code = 200, message = "Payments retrieved successfully", response = Page.class),
50+
@ApiResponse(code = 204, message = "No content", response = ResponseEntity.class)
51+
})
52+
@GetMapping("/all")
53+
@PreAuthorize("hasAuthority('ADMIN')")
54+
public Mono<ResponseEntity<Page<PaymentDto>>> findAll(@RequestParam(defaultValue = "0") int page,
55+
@RequestParam(defaultValue = "10") int size,
56+
@RequestParam(defaultValue = "paymentId") String sortBy,
57+
@RequestParam(defaultValue = "asc") String sortOrder) {
58+
return paymentService.findAll(page, size, sortBy, sortOrder)
5459
.map(ResponseEntity::ok)
55-
.defaultIfEmpty(ResponseEntity.notFound().build());
60+
.defaultIfEmpty(ResponseEntity.noContent().build());
5661
}
5762

63+
@ApiOperation(value = "Get payment by ID", notes = "Retrieve cart information based on the provided ID.")
64+
@ApiResponses({
65+
@ApiResponse(code = 200, message = "Payment retrieved successfully", response = PaymentDto.class),
66+
@ApiResponse(code = 404, message = "Payment not found", response = ResponseEntity.class)
67+
})
5868
@GetMapping("/{paymentId}")
59-
public ResponseEntity<PaymentDto> findById(@PathVariable("paymentId")
60-
@NotBlank(message = "Input must not be blank")
61-
@Valid final Integer paymentId) {
62-
log.info("PaymentDto, resource; fetch payment by id");
63-
return ResponseEntity.ok(this.paymentService.findById(paymentId));
69+
@PreAuthorize("hasAuthority('USER') or hasAuthority('ADMIN')")
70+
public ResponseEntity<Mono<PaymentDto>> findById(@PathVariable("paymentId")
71+
@NotBlank(message = "Input must not be blank")
72+
@Valid final String paymentId) {
73+
log.info("*** PaymentDto, resource; fetch cart by id *");
74+
return ResponseEntity.ok(paymentService.findById(Integer.parseInt(paymentId)));
6475
}
6576

77+
@ApiOperation(value = "Save payment", notes = "Save a new payment.")
78+
@ApiResponses({
79+
@ApiResponse(code = 200, message = "Payment saved successfully", response = PaymentDto.class),
80+
@ApiResponse(code = 500, message = "Internal Server Error", response = ResponseEntity.class)
81+
})
6682
@PostMapping
67-
public ResponseEntity<PaymentDto> save(@RequestHeader(name = "Authorization") String authorizationHeader,
68-
@RequestBody @NotNull(message = "Input must not be NULL")
69-
@Valid final PaymentDto paymentDto) {
70-
if (!jwtValidate.validateTokenUserService(authorizationHeader)) {
71-
ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).build();
72-
}
73-
log.info("PaymentDto, resource; save payment");
74-
return ResponseEntity.ok(this.paymentService.save(paymentDto));
83+
@PreAuthorize("hasAuthority('USER')")
84+
public Mono<ResponseEntity<PaymentDto>> save(@RequestBody
85+
@NotNull(message = "Input must not be NULL!")
86+
@Valid final PaymentDto paymentDto) {
87+
log.info("*** PaymentDto, resource; save payments *");
88+
return paymentService.save(paymentDto)
89+
.map(ResponseEntity::ok)
90+
.defaultIfEmpty(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
7591
}
7692

93+
@ApiOperation(value = "Update payment", notes = "Update an existing payment.")
94+
@ApiResponses({
95+
@ApiResponse(code = 200, message = "Payment updated successfully", response = PaymentDto.class),
96+
@ApiResponse(code = 404, message = "Payment not found", response = ResponseEntity.class)
97+
})
7798
@PutMapping
78-
public ResponseEntity<PaymentDto> update(@RequestHeader(name = "Authorization") String authorizationHeader,
79-
@RequestBody @NotNull(message = "Input must not be NULL")
80-
@Valid final PaymentDto paymentDto) {
81-
if (!jwtValidate.validateTokenUserService(authorizationHeader)) {
82-
ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).build();
83-
}
84-
log.info("PaymentDto, resource; update payment");
85-
return ResponseEntity.ok(this.paymentService.update(paymentDto));
99+
@PreAuthorize("hasAuthority('ADMIN')")
100+
public Mono<ResponseEntity<PaymentDto>> update(@RequestBody
101+
@NotNull(message = "Input must not be NULL")
102+
@Valid final PaymentDto paymentDto) {
103+
log.info("*** CartDto, resource; update cart *");
104+
return paymentService.update(paymentDto)
105+
.map(ResponseEntity::ok)
106+
.defaultIfEmpty(ResponseEntity.notFound().build());
107+
}
108+
109+
110+
@ApiOperation(value = "Update payment by ID", notes = "Update an existing cart based on the provided ID.")
111+
@ApiResponses({
112+
@ApiResponse(code = 200, message = "Payment updated successfully", response = PaymentDto.class),
113+
@ApiResponse(code = 404, message = "Payment not found", response = ResponseEntity.class)
114+
})
115+
@PutMapping("/{paymentId}")
116+
@PreAuthorize("hasAuthority('USER')")
117+
public Mono<ResponseEntity<PaymentDto>> update(@PathVariable("paymentId")
118+
@NotBlank(message = "Input must not be blank")
119+
@Valid final Integer paymentId,
120+
@RequestBody
121+
@NotNull(message = "Input must not be NULL")
122+
@Valid final PaymentDto paymentDto) {
123+
log.info("*** PaymentDto, resource; update cart with paymentId *");
124+
return paymentService.update(paymentId, paymentDto)
125+
.map(ResponseEntity::ok)
126+
.defaultIfEmpty(ResponseEntity.notFound().build());
86127
}
87128

129+
@ApiOperation(value = "Delete payment by ID", notes = "Delete a cart based on the provided ID.")
130+
@ApiResponses({
131+
@ApiResponse(code = 200, message = "Payment deleted successfully", response = Boolean.class),
132+
@ApiResponse(code = 404, message = "Payment not found", response = ResponseEntity.class)
133+
})
88134
@DeleteMapping("/{paymentId}")
89-
public ResponseEntity<Boolean> deleteById(@RequestHeader(name = "Authorization") String authorizationHeader,
90-
@PathVariable("paymentId") final String paymentId) {
91-
if (!jwtValidate.validateTokenUserService(authorizationHeader)) {
92-
ResponseEntity.status(HttpStatus.SC_UNAUTHORIZED).build();
93-
}
94-
log.info("Boolean, resource; delete payment by id");
95-
this.paymentService.deleteById(Integer.parseInt(paymentId));
96-
return ResponseEntity.ok(true);
135+
@PreAuthorize("hasAuthority('USER')")
136+
public Mono<ResponseEntity<Boolean>> deleteById(@PathVariable("paymentId") final Integer paymentId) {
137+
log.info("*** Boolean, resource; delete payment by id *");
138+
return paymentService.deleteById(paymentId)
139+
.thenReturn(ResponseEntity.ok(true))
140+
.defaultIfEmpty(ResponseEntity.status(HttpStatus.NOT_FOUND).body(false));
97141
}
98142

99-
}
143+
}

payment-service/src/main/java/com/hoangtien2k3/paymentservice/config/mapper/MapperConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.fasterxml.jackson.databind.SerializationFeature;
66
import com.fasterxml.jackson.databind.json.JsonMapper;
7+
import org.modelmapper.ModelMapper;
8+
import org.modelmapper.convention.MatchingStrategies;
79
import org.springframework.context.annotation.Bean;
810
import org.springframework.context.annotation.Configuration;
911

@@ -13,4 +15,12 @@ public class MapperConfig {
1315
public ObjectMapper objectMapperBean() {
1416
return new JsonMapper().enable(SerializationFeature.INDENT_OUTPUT);
1517
}
18+
19+
@Bean
20+
public ModelMapper modelMapper() {
21+
ModelMapper modelMapper = new ModelMapper();
22+
modelMapper.getConfiguration()
23+
.setMatchingStrategy(MatchingStrategies.STRICT);
24+
return modelMapper;
25+
}
1626
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.hoangtien2k3.paymentservice.config.swagger;
2+
3+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;
4+
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
5+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
6+
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
7+
import org.springframework.boot.actuate.endpoint.web.*;
8+
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
9+
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
10+
import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;
11+
import org.springframework.context.annotation.Bean;
12+
import org.springframework.context.annotation.Configuration;
13+
import org.springframework.core.env.Environment;
14+
import org.springframework.util.StringUtils;
15+
import springfox.documentation.builders.ApiInfoBuilder;
16+
import springfox.documentation.builders.PathSelectors;
17+
import springfox.documentation.builders.RequestHandlerSelectors;
18+
import springfox.documentation.service.*;
19+
import springfox.documentation.spi.DocumentationType;
20+
import springfox.documentation.spi.service.contexts.SecurityContext;
21+
import springfox.documentation.spring.web.plugins.Docket;
22+
import springfox.documentation.swagger2.annotations.EnableSwagger2;
23+
24+
import java.util.ArrayList;
25+
import java.util.Collection;
26+
import java.util.Collections;
27+
import java.util.List;
28+
29+
@Configuration
30+
@EnableSwagger2
31+
public class Swagger2Config {
32+
@Bean
33+
public Docket api() {
34+
return new Docket(DocumentationType.SWAGGER_2)
35+
.select()
36+
.apis(RequestHandlerSelectors.any())
37+
.paths(PathSelectors.any())
38+
.build()
39+
.apiInfo(apiEndPointsInfo())
40+
.securitySchemes(List.of(apiKey()))
41+
.securityContexts(Collections.singletonList(securityContext()));
42+
}
43+
44+
private ApiInfo apiEndPointsInfo() {
45+
return new ApiInfoBuilder()
46+
.title("ORDER-SERVICE API")
47+
.description("API Documentation's ORDER-SERVICE")
48+
.contact(new Contact("hoangtien2k3", "https://hoangtien2k3qx1.github.io/", "hoangtien2k3qx1@gmail.com"))
49+
.license("MIT")
50+
.licenseUrl("https://mit-license.org/")
51+
.version("1.0.0")
52+
.build();
53+
}
54+
55+
private ApiKey apiKey() {
56+
return new ApiKey("JWT", "Authorization", "header");
57+
}
58+
59+
private SecurityContext securityContext() {
60+
return SecurityContext.builder()
61+
.securityReferences(defaultAuth())
62+
.build();
63+
}
64+
65+
private List<SecurityReference> defaultAuth() {
66+
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
67+
SecurityReference reference = new SecurityReference("JWT", new AuthorizationScope[]{authorizationScope});
68+
return List.of(reference);
69+
}
70+
71+
@Bean
72+
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
73+
ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
74+
EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
75+
WebEndpointProperties webEndpointProperties, Environment environment) {
76+
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
77+
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
78+
allEndpoints.addAll(webEndpoints);
79+
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
80+
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
81+
String basePath = webEndpointProperties.getBasePath();
82+
EndpointMapping endpointMapping = new EndpointMapping(basePath);
83+
boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment,
84+
basePath);
85+
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
86+
corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath),
87+
shouldRegisterLinksMapping, null);
88+
}
89+
90+
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment,
91+
String basePath) {
92+
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath)
93+
|| ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
94+
}
95+
96+
}

0 commit comments

Comments
 (0)