Skip to content

Commit efe7e4c

Browse files
committed
feat: FeignClient로 pg-simulator 모듈 내 결제 API 요청
- FeignClient 설정 - API Spec 정의 - 요청, 응답 본문 정의
1 parent 049886d commit efe7e4c

10 files changed

Lines changed: 163 additions & 11 deletions

File tree

apps/commerce-api/src/main/java/com/loopers/CommerceApiApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import org.springframework.boot.autoconfigure.SpringBootApplication;
66
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
77
import org.springframework.cache.annotation.EnableCaching;
8+
import org.springframework.cloud.openfeign.EnableFeignClients;
89

910
import java.util.TimeZone;
1011

1112
@ConfigurationPropertiesScan
1213
@SpringBootApplication
1314
@EnableCaching
15+
@EnableFeignClients
1416
public class CommerceApiApplication {
1517

1618
@PostConstruct
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.loopers.application.payment;
2+
3+
import com.loopers.infrastructure.payment.client.PgClient;
4+
import com.loopers.interfaces.api.ApiResponse;
5+
import com.loopers.interfaces.api.payment.PaymentV1Dto;
6+
import lombok.RequiredArgsConstructor;
7+
import org.springframework.stereotype.Component;
8+
9+
@Component
10+
@RequiredArgsConstructor
11+
public class PaymentFacade {
12+
private final PgClient pgClient;
13+
14+
public PaymentV1Dto.TransactionResponse pay(String userId, PaymentV1Dto.PaymentRequest request) {
15+
ApiResponse<PaymentV1Dto.TransactionResponse> result = pgClient.requestPayment(userId, request);
16+
17+
PaymentV1Dto.TransactionResponse response = result.data();
18+
19+
return response;
20+
}
21+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.loopers.domain.payment;
2+
3+
import com.loopers.domain.BaseEntity;
4+
import jakarta.persistence.Column;
5+
import jakarta.persistence.Entity;
6+
import jakarta.persistence.Table;
7+
import lombok.AccessLevel;
8+
import lombok.Getter;
9+
import lombok.NoArgsConstructor;
10+
11+
@Entity
12+
@Getter
13+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
14+
@Table(name = "payment")
15+
public class Payment extends BaseEntity {
16+
@Column(name = "ref_order_id", nullable = false)
17+
private Long orderId;
18+
19+
@Column(name = "ref_user_id", nullable = false)
20+
private Long userId;
21+
22+
@Column(name = "transaction_key")
23+
private String transactionKey;
24+
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.loopers.domain.payment;
2+
3+
public enum PaymentTransactionStatus {
4+
PENDING,
5+
SUCCESS,
6+
FAILED,
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.loopers.infrastructure.payment.client;
2+
3+
import feign.Request;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
public class FeignClientTimeoutConfig {
9+
@Bean
10+
public Request.Options feignOptions() {
11+
return new Request.Options(1000, 3000); // 연결/응답 타임아웃 (ms)
12+
}
13+
}
Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1-
package com.loopers.infrastructure.payment.client;
2-
3-
import org.springframework.cloud.openfeign.FeignClient;
4-
5-
@FeignClient
6-
public interface PgClient {
7-
}
1+
package com.loopers.infrastructure.payment.client;
2+
3+
import com.loopers.interfaces.api.ApiResponse;
4+
import com.loopers.interfaces.api.payment.PaymentV1Dto;
5+
import org.springframework.cloud.openfeign.FeignClient;
6+
import org.springframework.stereotype.Component;
7+
import org.springframework.web.bind.annotation.PostMapping;
8+
import org.springframework.web.bind.annotation.RequestBody;
9+
import org.springframework.web.bind.annotation.RequestHeader;
10+
11+
12+
@FeignClient(
13+
name = "pgClient",
14+
url = "http://localhost:8082",
15+
configuration = FeignClientTimeoutConfig.class
16+
)
17+
public interface PgClient {
18+
@PostMapping("/api/v1/payments")
19+
ApiResponse<PaymentV1Dto.TransactionResponse> requestPayment(
20+
@RequestHeader("X-USER-ID") String userId,
21+
@RequestBody PaymentV1Dto.PaymentRequest request
22+
);
23+
}

apps/commerce-api/src/main/java/com/loopers/infrastructure/payment/client/PgClientTimeoutConfig.java

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.loopers.interfaces.api.payment;
2+
3+
import com.loopers.application.payment.PaymentFacade;
4+
import com.loopers.interfaces.api.ApiResponse;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestBody;
8+
import org.springframework.web.bind.annotation.RequestHeader;
9+
import org.springframework.web.bind.annotation.RequestMapping;
10+
import org.springframework.web.bind.annotation.RestController;
11+
12+
@RestController
13+
@RequestMapping("/api/v1/payments")
14+
@RequiredArgsConstructor
15+
public class PaymentV1Controller implements PaymentV1Spec {
16+
private final PaymentFacade paymentFacade;
17+
18+
@PostMapping
19+
@Override
20+
public ApiResponse<PaymentV1Dto.TransactionResponse> pay(
21+
@RequestHeader String userId,
22+
@RequestBody PaymentV1Dto.PaymentRequest request
23+
) {
24+
PaymentV1Dto.TransactionResponse response = paymentFacade.pay(userId, request);
25+
26+
return ApiResponse.success(response);
27+
}
28+
29+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.loopers.interfaces.api.payment;
2+
3+
4+
public class PaymentV1Dto {
5+
public record TransactionResponse(
6+
String transactionKey,
7+
TransactionStatusResponse status,
8+
String reason
9+
) { }
10+
11+
public enum TransactionStatusResponse {
12+
PENDING,
13+
SUCCESS,
14+
FAILED,
15+
}
16+
17+
public record PaymentRequest(
18+
String orderId,
19+
CardTypeDto cardType,
20+
String cardNo,
21+
Long amount,
22+
String callbackUrl
23+
) { }
24+
25+
public enum CardTypeDto {
26+
SAMSUNG,
27+
KB,
28+
HYUNDAI
29+
}
30+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.loopers.interfaces.api.payment;
2+
3+
import com.loopers.interfaces.api.ApiResponse;
4+
import io.swagger.v3.oas.annotations.Operation;
5+
import io.swagger.v3.oas.annotations.tags.Tag;
6+
7+
@Tag(name = "Payment V1 API", description = "Payment V1 API Spec")
8+
public interface PaymentV1Spec {
9+
10+
@Operation(summary = "PG사 결제 요청")
11+
ApiResponse<PaymentV1Dto.TransactionResponse> pay(String userId, PaymentV1Dto.PaymentRequest request);
12+
13+
}

0 commit comments

Comments
 (0)