오늘의빵
서비스에서는 빵을 구독하는 기능을 제공하기 위해 스텝페이의 API를 사용합니다. 오늘은 오늘의빵
서비스에서 스텝페이의 API를 연결하는 과정을 담아봤습니다.
Spring Boot에서는 외부의 REST API를 사용하기 위해 Rest Template
를 많이 사용하는 것 같습니다. Rest Template
는 Spring 3부터 제공되는 기능으로 동기적으로 REST API를 요청하고 응답을 기다리는 방식입니다.
오늘의빵
서비스에서도 Rest Template
을 사용하여 스텝페이의 API를 사용하였습니다.
먼저 Rest Template
을 사용하기 위해 RestTemplateConfig
파일에서 Bean을 등록해주었습니다. Bean으로 등록하지 않아도 new RestTemplate()
로 사용이 가능하긴 하지만, 기본 설정 값을 유지시키기 위해 Bean에 등록하게 되었습니다.
/* RestTemplateConfig */
@Configuration
public class RestTemplateConfig {
@Value("${steppay.end-point}")
String baseUri;
@Value("${steppay.secret}")
String secretKey;
@Bean
public RestTemplate restTemplate() {
return new RestTemplateBuilder()
.rootUri(baseUri)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.ALL_VALUE)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader("Secret-Token", secretKey)
.build();
}
}
스텝페이의 API 사용하기 위해 Header에 Content-Type을 지정하였고, 발급 받은 Secret-Token을 넣어줬습니다.
Bean으로 등록된 RestTemplate
는 Spring에서 관리되고, 의존성을 주입 받을 수 있게 됩니다. 이제 RestTemplate
를 이용하여 실제로 스텝페이에 요청을 보내고 응답을 받는 서비스를 만들었습니다. 먼저, 스텝페이에 상품을 등록할 수 있는 API를 요청하는 부분입니다.
/* SteppayProductServiceImpl */
@Service
@RequiredArgsConstructor
public class SteppayProductServiceImpl implements SteppayProductService {
private final RestTemplate template;
public SteppayProductResponse create(SteppayCreateProductRequest request) {
return template.postForObject(
"/products",
request,
SteppayProductResponse.class
);
}
}
/* SteppayCreateProductRequest */
@Getter
public class SteppayCreateProductRequest {
String type;
String status;
String name;
String featuredImageUrl;
String description;
@Builder
public SteppayCreateProductRequest(
String name,
String featuredImageUrl,
String description
) {
this.type = "BOX";
this.status = "SALE";
this.name = name;
this.featuredImageUrl = featuredImageUrl;
this.description = description;
}
}
/* SteppayProductResponse */
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class SteppayProductResponse {
Integer id;
LocalDateTime createdAt;
LocalDateTime modifiedAt;
String code;
String type;
String status;
String name;
String featuredImageUrl;
String description;
List<SteppayPricePlanResponse> prices;
@Builder
public SteppayProductResponse(
Integer id,
LocalDateTime createdAt,
LocalDateTime modifiedAt,
String code,
String type,
String status,
String name,
String featuredImageUrl,
String description,
List<SteppayPricePlanResponse> prices
) {
this.id = id;
this.createdAt = createdAt;
this.modifiedAt = modifiedAt;
this.code = code;
this.type = type;
this.status = status;
this.name = name;
this.featuredImageUrl = featuredImageUrl;
this.description = description;
this.prices = prices;
}
}
스텝페이에서 상품 생성을 할때의 Request DTO는 SteppayCreateProductRequest
라는 이름으로 사용하였습니다. SteppayCreateProductRequest
에서 type
과 초기의 status
값은 일정하게 고정하기 위해 외부로부터 값을 받지 않고, 내부에서 초기화를 해주고 있습니다. status
의 경우 나중에 판매 상태를 종료하기 위해 변경할 수 있도록 '상품 수정' API를 호출하여 변경할 수 있도록 할 예정입니다.
또한 스텝페이에서 반환 받는 상품의 Response DTO는 SteppayProductResponse
라는 이름으로 사용하였습니다. SteppayProductResponse
에는 실제로 더 많은 값이 반환되지만, 저희의 서비스에서 필요한 부분만 객체로 변환하여 저장할 수 있도록 하였습니다.
API가 잘 작동하는지 확인하기 위해 테스트 코드를 작성하였습니다.
/* SteppayProductServiceImplTest */
@SpringBootTest
class SteppayProductServiceImplTest {
@Autowired
private SteppayProductServiceImpl steppayCreateProductService;
@Test
@DisplayName("스텝페이 상품을 생성할 수 있어요.")
public void create() {
SteppayProductResponse response = steppayCreateProductService.create(
SteppayCreateProductRequest.builder()
.name("test_package")
.featuredImageUrl("featured_image_url")
.description("test_package_description")
.build()
);
assertThat(response).isNotNull().isInstanceOf(SteppayProductResponse.class);
assertThat(response.getId()).isNotNull();
assertThat(response.getType()).isEqualTo("BOX");
assertThat(response.getStatus()).isEqualTo("SALE");
assertThat(response.getName()).isEqualTo("test_package");
assertThat(response.getFeaturedImageUrl()).isEqualTo("featured_image_url");
assertThat(response.getDescription()).isEqualTo("test_package_description");
}
}
Intellij에서 테스트를 진행했을때 다행히 테스트를 통과하는 것을 확인할 수 있었습니다.
이번에는 RestTemplate
로 API 호출이 잘 되는지 확인할 목적으로 직접 API 요청을 통해 테스트를 작성하였지만, SteppayProductServiceImpl
서비스가 다른 기능에서 사용될 때에는 해당 기능의 테스트에서 스텝페이의 API의 호출이 테스트를 실패시킬 수 있기 때문에 다른 방법을 이용하였습니다.
다른 기능을 테스트 할 때에 오늘의빵
에서 적용한 테스트 방법은 다음 포스트에서 살펴보도록 하겠습니다!