diff --git a/src/main/java/com/tripmate/api/controller/SpotController.java b/src/main/java/com/tripmate/api/controller/SpotController.java index b32c926..8483a97 100644 --- a/src/main/java/com/tripmate/api/controller/SpotController.java +++ b/src/main/java/com/tripmate/api/controller/SpotController.java @@ -6,19 +6,21 @@ import com.tripmate.api.domain.user.TripmateCharacter; import com.tripmate.api.domain.user.TripmateCharacterType; import com.tripmate.api.dto.companion.CompanionRecruitInfo; -import com.tripmate.api.dto.companion.HostInfo; import com.tripmate.api.dto.request.LocationBasedSpotSearchRequest; import com.tripmate.api.dto.response.LocationBasedSpotListResponse; import com.tripmate.api.dto.response.SpotDetailResponse; import com.tripmate.api.dto.response.TripmateApiResponse; import com.tripmate.api.dto.spot.LocationBasedSpotInfo; import com.tripmate.api.service.LocationBasedSpotSearchService; +import com.tripmate.integration.tourapi.dto.response.SpotCommonInfo; +import com.tripmate.integration.tourapi.service.TourApiService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import jakarta.validation.Valid; -import java.util.Arrays; + +import java.util.Collections; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -37,6 +39,8 @@ public class SpotController { private final LocationBasedSpotSearchService locationBasedSpotSearchService; + private final TourApiService tourApiService; + @Operation( summary = "여행지 검색 API", description = "위치(위도, 경도) 및 범위, 여행지 타입(예: EXPERIENCE), 여행지 타입 그룹(예: ACTIVITY)로 여행지 탐색" @@ -65,55 +69,64 @@ public ResponseEntity> getSpo }) @GetMapping("{spotId}") public ResponseEntity> getSpotDetail(@PathVariable Long spotId) { + SpotCommonInfo spotCommonInfo = tourApiService.getSpotDetailInfo(spotId); + SpotType spotType = SpotType.fromTourApiCategory(spotCommonInfo.cat2()); + + List companionRecruits = Collections.emptyList(); + return ResponseEntity.ok( TripmateApiResponse.success( new SpotDetailResponse( spotId, - "서핑 체험", - "Quae eius ea nihil quasi mollitia consectetur natus repudiandae aut. Sit maiores minus asperiores illum rem. Sunt commodi aliquam ipsam quas aliquam minima.", - SpotType.EXPERIENCE, - "https://dimg.donga.com/wps/NEWS/IMAGE/2021/07/16/107979650.1.jpg", - "010-0000-0000", + spotCommonInfo.title(), + spotCommonInfo.overview(), + spotType, + spotCommonInfo.firstImage(), + spotCommonInfo.tel(), new Location( - "37.7563022", - "128.922632", - new Address("강원 양양군 현북면 하조대해안길 119", "") + spotCommonInfo.mapY(), + spotCommonInfo.mapX(), + new Address( + spotCommonInfo.addr1(), + spotCommonInfo.addr2() + ) ), List.of( new TripmateCharacter("인스타 모험자 아기 돌고래", TripmateCharacterType.DOLPHIN), new TripmateCharacter("랜드마크 탐험가 아기 펭귄", TripmateCharacterType.PENGUIN), new TripmateCharacter("인생샷 찍는 인스타 인플루언서 꿀벌", TripmateCharacterType.HONEYBEE) ), - List.of( - new CompanionRecruitInfo( - 1L, - new HostInfo( - "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSq5wHDD6sXA3M1EhvtDL6MC38-6G27SiCg7g&s", - "나는야고윤정", - "인스타 인플루언서 아기 펭귄", - "PENGUIN", - Arrays.asList("맛집탐험형", "액티비티형", "쇼핑형"), - 70 - ), - "서피비치 인근에서 같이 식사할 사람 구해요!", - "여자", - "20대" - ), - new CompanionRecruitInfo( - 2L, - new HostInfo( - "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSq5wHDD6sXA3M1EhvtDL6MC38-6G27SiCg7g&s", - "춤추는 심바", - "쇼핑을 즐기는 비버", - "PENGUIN", - Arrays.asList("맛집탐험형", "액티비티형", "쇼핑형"), - 70 - ), - "서피비치 인근에서 같이 식사할 사람 구해요!", - "여자", - "30대" - ) - ) + companionRecruits +// List.of( +// new CompanionRecruitInfo( +// 1L, +// new HostInfo( +// "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSq5wHDD6sXA3M1EhvtDL6MC38-6G27SiCg7g&s", +// "나는야고윤정", +// "인스타 인플루언서 아기 펭귄", +// "PENGUIN", +// Arrays.asList("맛집탐험형", "액티비티형", "쇼핑형"), +// 70 +// ), +// "서피비치 인근에서 같이 식사할 사람 구해요!", +// "여자", +// "20대" +// ), +// new CompanionRecruitInfo( +// 2L, +// new HostInfo( +// "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSq5wHDD6sXA3M1EhvtDL6MC38-6G27SiCg7g&s", +// "춤추는 심바", +// "쇼핑을 즐기는 비버", +// "PENGUIN", +// Arrays.asList("맛집탐험형", "액티비티형", "쇼핑형"), +// 70 +// ), +// "서피비치 인근에서 같이 식사할 사람 구해요!", +// "여자", +// "30대" +// ) +// ) ) ) ); diff --git a/src/main/java/com/tripmate/api/domain/spot/SpotType.java b/src/main/java/com/tripmate/api/domain/spot/SpotType.java index 20f951c..1b3d427 100644 --- a/src/main/java/com/tripmate/api/domain/spot/SpotType.java +++ b/src/main/java/com/tripmate/api/domain/spot/SpotType.java @@ -10,27 +10,30 @@ @RequiredArgsConstructor public enum SpotType { - EXPERIENCE("체험", EnumSet.of(SpotMediumCategory.A0203, SpotMediumCategory.A0102)), - CULTURE_AND_ART("문화예술", EnumSet.of(SpotMediumCategory.A0206)), - FESTIVAL_AND_PERFORMANCE("축제∙공연", EnumSet.of(SpotMediumCategory.A0207, SpotMediumCategory.A0208)), - NATURE_AND_REST("자연∙휴양", EnumSet.of( + EXPERIENCE("체험", "12", EnumSet.of(SpotMediumCategory.A0203, SpotMediumCategory.A0102)), + CULTURE_AND_ART("문화예술", "14", EnumSet.of(SpotMediumCategory.A0206)), + FESTIVAL_AND_PERFORMANCE("축제∙공연", "15", EnumSet.of(SpotMediumCategory.A0207, SpotMediumCategory.A0208)), + NATURE_AND_REST("자연∙휴양", "12", EnumSet.of( SpotMediumCategory.A0101, SpotMediumCategory.A0102, SpotMediumCategory.A0202 )), - TRIP_ITINERARY("여행코스", EnumSet.of( + TRIP_ITINERARY("여행코스", "25", EnumSet.of( SpotMediumCategory.C0112, SpotMediumCategory.C0113, SpotMediumCategory.C0114, SpotMediumCategory.C0115, SpotMediumCategory.C0116, SpotMediumCategory.C0117 )), - HISTORY("역사", EnumSet.of(SpotMediumCategory.A0201, SpotMediumCategory.A0205)), - LEISURE_SPORTS("레포츠", EnumSet.of( + HISTORY("역사", "12", EnumSet.of(SpotMediumCategory.A0201, SpotMediumCategory.A0205)), + LEISURE_SPORTS("레포츠", "28", EnumSet.of( SpotMediumCategory.A0301, SpotMediumCategory.A0302, SpotMediumCategory.A0303, SpotMediumCategory.A0304, SpotMediumCategory.A0305 )), - ACCOMMODATION("숙박", EnumSet.of(SpotMediumCategory.B0201)), - SHOPPING("쇼핑", EnumSet.of(SpotMediumCategory.A0401)), - RESTAURANT_AND_CAFE("맛집∙카페", EnumSet.of(SpotMediumCategory.A0502)), - UNKNOWN("알수없음", EnumSet.noneOf(SpotMediumCategory.class)); + ACCOMMODATION("숙박", "32", EnumSet.of(SpotMediumCategory.B0201)), + SHOPPING("쇼핑", "38", EnumSet.of(SpotMediumCategory.A0401)), + RESTAURANT_AND_CAFE("맛집∙카페", "39", EnumSet.of(SpotMediumCategory.A0502)), + UNKNOWN("알수없음", "00", EnumSet.noneOf(SpotMediumCategory.class)); private final String typeName; + + private final String tourApiContentTypeId; + private final EnumSet tourApiCategorySet; public static SpotType fromTourApiCategory(final SpotMediumCategory category) { diff --git a/src/main/java/com/tripmate/integration/tourapi/dto/mapper/SpotDeserializer.java b/src/main/java/com/tripmate/integration/tourapi/dto/mapper/SpotDeserializer.java new file mode 100644 index 0000000..31d7de4 --- /dev/null +++ b/src/main/java/com/tripmate/integration/tourapi/dto/mapper/SpotDeserializer.java @@ -0,0 +1,31 @@ +package com.tripmate.integration.tourapi.dto.mapper; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.tripmate.integration.tourapi.dto.response.SpotCommonInfo; +import com.tripmate.integration.tourapi.dto.response.SpotCommonInfoApiResponse; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +public class SpotDeserializer extends JsonDeserializer { + + private final ObjectMapper mapper; + + public SpotDeserializer() { + this.mapper = new ObjectMapper(); + } + + @Override + public SpotCommonInfoApiResponse deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + JsonNode node = jp.getCodec().readTree(jp); + JsonNode items = node.findValue("item"); + + List spotItems = Arrays.stream(mapper.treeToValue(items, SpotCommonInfo[].class)).toList(); + return new SpotCommonInfoApiResponse(spotItems); + } +} diff --git a/src/main/java/com/tripmate/integration/tourapi/dto/request/TourApiRequestPath.java b/src/main/java/com/tripmate/integration/tourapi/dto/request/TourApiRequestPath.java index d59c033..61b3bc6 100644 --- a/src/main/java/com/tripmate/integration/tourapi/dto/request/TourApiRequestPath.java +++ b/src/main/java/com/tripmate/integration/tourapi/dto/request/TourApiRequestPath.java @@ -6,7 +6,9 @@ @Getter @RequiredArgsConstructor public enum TourApiRequestPath { - LOCATION_BASED_SPOT("B551011/KorService1/locationBasedList1"); + LOCATION_BASED_SPOT("B551011/KorService1/locationBasedList1"), + SPOT_COMMON_INFO("B551011/KorService1/detailCommon1"), + SPOT_DETAIL_INFO("B551011/KorService1/detailIntro1"); private final String path; } diff --git a/src/main/java/com/tripmate/integration/tourapi/dto/response/SpotCommonInfo.java b/src/main/java/com/tripmate/integration/tourapi/dto/response/SpotCommonInfo.java new file mode 100644 index 0000000..36f936b --- /dev/null +++ b/src/main/java/com/tripmate/integration/tourapi/dto/response/SpotCommonInfo.java @@ -0,0 +1,70 @@ +package com.tripmate.integration.tourapi.dto.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.tripmate.integration.tourapi.domain.SpotMediumCategory; +import com.tripmate.integration.tourapi.domain.SpotSmallCategory; +import com.tripmate.integration.tourapi.dto.mapper.SpotDeserializer; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record SpotCommonInfo( + + @JsonProperty("contentId") + String spotId, + + @JsonProperty("contenttypeid") + String contentTypeId, + + @JsonProperty("title") + String title, + + @JsonProperty("tel") + String tel, + + @JsonProperty("telname") + String telName, + + @JsonProperty("overview") + String overview, + + @JsonProperty("cat1") + String cat1, + + @JsonProperty("cat2") + SpotMediumCategory cat2, + + @JsonProperty("cat3") + SpotSmallCategory cat3, + + @JsonProperty("addr1") + String addr1, + + @JsonProperty("addr2") + String addr2, + + @JsonProperty("contentid") + Long contentId, + + @JsonProperty("firstimage") + String firstImage, + + @JsonProperty("firstimage2") + String firstImage2, + + @JsonProperty("mapx") + String mapX, + + @JsonProperty("mapy") + String mapY, + + @JsonProperty("mlevel") + int mLevel, + + @JsonProperty("modifiedtime") + String modifiedTime, + + @JsonProperty("sigungucode") + String siGunGuCode +) { +} \ No newline at end of file diff --git a/src/main/java/com/tripmate/integration/tourapi/dto/response/SpotCommonInfoApiResponse.java b/src/main/java/com/tripmate/integration/tourapi/dto/response/SpotCommonInfoApiResponse.java new file mode 100644 index 0000000..5bfd8e1 --- /dev/null +++ b/src/main/java/com/tripmate/integration/tourapi/dto/response/SpotCommonInfoApiResponse.java @@ -0,0 +1,17 @@ +package com.tripmate.integration.tourapi.dto.response; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.tripmate.integration.tourapi.dto.mapper.LocationBasedSpotListDeserializer; +import com.tripmate.integration.tourapi.dto.mapper.SpotDeserializer; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonDeserialize(using = SpotDeserializer.class) +public record SpotCommonInfoApiResponse( + @JsonProperty("item") + List spotItems +) { +} diff --git a/src/main/java/com/tripmate/integration/tourapi/service/TourApiService.java b/src/main/java/com/tripmate/integration/tourapi/service/TourApiService.java index 86d7909..0234a3d 100644 --- a/src/main/java/com/tripmate/integration/tourapi/service/TourApiService.java +++ b/src/main/java/com/tripmate/integration/tourapi/service/TourApiService.java @@ -3,6 +3,8 @@ import com.tripmate.integration.tourapi.TourApiRestClient; import com.tripmate.integration.tourapi.dto.request.TourApiRequestPath; import com.tripmate.integration.tourapi.dto.response.LocationBasedSpotApiResponse; +import com.tripmate.integration.tourapi.dto.response.SpotCommonInfo; +import com.tripmate.integration.tourapi.dto.response.SpotCommonInfoApiResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.util.LinkedMultiValueMap; @@ -28,4 +30,23 @@ public LocationBasedSpotApiResponse findSpotsByLocation(String latitude, String return response.getBody(); } + + public SpotCommonInfo getSpotDetailInfo(Long spotId) { + MultiValueMap queryParams = new LinkedMultiValueMap<>(); + queryParams.add("contentId", spotId.toString()); + queryParams.add("overviewYN", "Y"); + queryParams.add("mapinfoYN", "Y"); + queryParams.add("addrinfoYN", "Y"); + queryParams.add("catcodeYN", "Y"); + queryParams.add("defaultYN", "Y"); + queryParams.add("firstImageYN", "Y"); + + ResponseEntity response = tourApiRestClient.get( + TourApiRequestPath.SPOT_COMMON_INFO.getPath(), + SpotCommonInfoApiResponse.class, + queryParams + ); + + return response.getBody().spotItems().getFirst(); + } }