Skip to content

Commit cba8f33

Browse files
authored
Merge pull request #30 from Block-Guard/feat/#28/connet-fastapi-server
[Feat] FastAPI 서버 연동
2 parents fcd32a8 + 68fd4d8 commit cba8f33

File tree

6 files changed

+126
-20
lines changed

6 files changed

+126
-20
lines changed

src/main/java/com/blockguard/server/domain/analysis/application/FraudAnalysisService.java

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
package com.blockguard.server.domain.analysis.application;
22

3+
import com.blockguard.server.domain.analysis.domain.enums.RiskLevel;
34
import com.blockguard.server.domain.analysis.dto.request.FraudAnalysisRequest;
45
import com.blockguard.server.domain.analysis.dto.request.GptRequest;
56
import com.blockguard.server.domain.analysis.dto.response.FraudAnalysisResponse;
7+
import com.blockguard.server.domain.analysis.dto.response.GptResponse;
8+
import com.blockguard.server.global.common.codes.ErrorCode;
9+
import com.blockguard.server.global.exception.BusinessExceptionHandler;
610
import com.blockguard.server.infra.ocr.NaverOcrClient;
711
import lombok.AllArgsConstructor;
12+
import lombok.RequiredArgsConstructor;
813
import lombok.extern.slf4j.Slf4j;
14+
import org.springframework.beans.factory.annotation.Value;
15+
import org.springframework.http.*;
916
import org.springframework.stereotype.Service;
1017
import org.springframework.util.StringUtils;
18+
import org.springframework.web.client.RestClientException;
19+
import org.springframework.web.client.RestTemplate;
1120
import org.springframework.web.multipart.MultipartFile;
1221

1322
import java.io.IOException;
@@ -16,10 +25,14 @@
1625

1726
@Service
1827
@Slf4j
19-
@AllArgsConstructor
28+
@RequiredArgsConstructor
2029
public class FraudAnalysisService {
2130

2231
private final NaverOcrClient naverOcrClient;
32+
private final RestTemplate restTemplate;
33+
34+
@Value("${ai.server.url}")
35+
private String aiBaseUrl;
2336

2437
public FraudAnalysisResponse fraudAnalysis(FraudAnalysisRequest fraudAnalysisRequest, List<MultipartFile> imageFiles) {
2538
List<String> keywords = new ArrayList<>();
@@ -29,17 +42,38 @@ public FraudAnalysisResponse fraudAnalysis(FraudAnalysisRequest fraudAnalysisReq
2942
String imageContent = "";
3043
imageContent = extractOcrText(imageFiles);
3144

32-
// TODO: gpt 서버와 연동 예정
3345
GptRequest gptRequest = buildGptRequest(fraudAnalysisRequest, keywords, additionalDescription, imageContent);
3446

35-
return FraudAnalysisResponse
36-
.builder()
37-
.keywords(keywords)
38-
.additionalDescription(additionalDescription)
39-
.messageContent(StringUtils.hasText(fraudAnalysisRequest.getMessageContent()) ? fraudAnalysisRequest.getMessageContent() : null)
40-
.imageContent(StringUtils.hasText(imageContent) ? imageContent : null)
41-
.build();
47+
try {
48+
HttpHeaders headers = new HttpHeaders();
49+
headers.setContentType(MediaType.APPLICATION_JSON);
4250

51+
HttpEntity<GptRequest> entity = new HttpEntity<>(gptRequest, headers);
52+
ResponseEntity<GptResponse> response = restTemplate.postForEntity(
53+
aiBaseUrl,
54+
entity,
55+
GptResponse.class
56+
);
57+
58+
if (response.getBody() == null || !response.getStatusCode().is2xxSuccessful()) {
59+
log.error("AI 서버 응답 오류: status={}, body={}", response.getStatusCode(), response.getBody());
60+
throw new BusinessExceptionHandler(ErrorCode.AI_SERVER_ERROR);
61+
}
62+
63+
double score = response.getBody().getScore();
64+
return FraudAnalysisResponse
65+
.builder()
66+
.keywords(response.getBody().getKeywords())
67+
.score(response.getBody().getScore())
68+
.estimatedFraudType(response.getBody().getEstimatedFraudType())
69+
.explanation(response.getBody().getExplanation())
70+
.riskLevel(RiskLevel.fromScore(score).getName())
71+
.build();
72+
73+
} catch (RestClientException e){
74+
log.error("AI 서버 통신 실패: {}", e.getMessage());
75+
throw new BusinessExceptionHandler(ErrorCode.AI_SERVER_ERROR);
76+
}
4377
}
4478

4579
private String extractOcrText(List<MultipartFile> imageFiles) {
Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,38 @@
11
package com.blockguard.server.domain.analysis.domain.enums;
22

3-
// Todo: 사기 클래스 확정 후 변경
3+
import lombok.Getter;
4+
5+
@Getter
46
public enum FraudType {
5-
PROSECUTOR_IMPERSONATION,
6-
FAMILY_IMPERSONATION,
7-
LOAN_FRAUD,
8-
CARD_DELIVERY_IMPERSONATION
7+
VOICE_PHISHING ("보이스피싱"),
8+
MESSENGER_PHISHING ("메신저피싱"),
9+
SMISHING ("스미싱"),
10+
INSTITUTION_IMPERSONATION("기관사칭형"),
11+
LOAN_FRAUD ("대출사기형"),
12+
CARD_COMPANY_IMPERSONATION("카드사 사칭형"),
13+
FAMILY_IMPERSONATION ("가족/지인사칭형"),
14+
CELEBRATORY_IMPERSONATION("경조사사칭형"),
15+
FIRST_BIRTHDAY_INVITE ("돌잔치 초대장형"),
16+
MOBILE_WEDDING_INVITE ("모바일 청첩장형"),
17+
OBITUARY_MESSAGE ("부고문자형"),
18+
PUBLIC_AGENCY_IMPERSONATION("공공기관 사칭형"),
19+
FINE_AND_PENALTY ("범칙금/과태료 부과형"),
20+
HEALTH_INSURANCE_IMPERSONATION("건강보험공단 사칭형"),
21+
POLICE_SUMMONS ("경찰출석요구형"),
22+
NATIONAL_TAX_SERVICE ("국세청 사칭형"),
23+
PART_TIME_SCAM ("알바/부업 사기형"),
24+
GOVERNMENT_GRANT_SCAM ("정부지원금 위장형"),
25+
DELIVERY_SCAM ("택배사기형"),
26+
INVESTMENT_SCAM ("투자사기형"),
27+
CRYPTOCURRENCY_SCAM ("가상화폐 사기형"),
28+
STOCK_INVESTMENT_SCAM ("주식투자 사기형"),
29+
IPO_SCAM ("청약 공모주 사기형"),
30+
FALSE_PAYMENT_SCAM ("허위결제사기형");
31+
32+
private final String korName;
33+
34+
FraudType(String korName) {
35+
this.korName = korName;
36+
}
37+
938
}
Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
package com.blockguard.server.domain.analysis.domain.enums;
22

3+
import lombok.Getter;
4+
5+
@Getter
36
public enum RiskLevel {
4-
Dangers, Caution, Safety
7+
Dangers("위험"),
8+
Caution("주의"),
9+
Safety("안전");
10+
11+
private final String name;
12+
13+
RiskLevel(String name) {
14+
this.name = name;
15+
}
16+
17+
public static RiskLevel fromScore(double score) {
18+
if (score <= 30) {
19+
return Safety;
20+
} else if (score <= 60) {
21+
return Caution;
22+
} else {
23+
return Dangers;
24+
}
25+
}
26+
527
}

src/main/java/com/blockguard/server/domain/analysis/dto/response/FraudAnalysisResponse.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
@AllArgsConstructor
1313
@NoArgsConstructor
1414
public class FraudAnalysisResponse {
15-
// for test
16-
private String messageContent;
15+
private String riskLevel;
16+
private Double score;
17+
private String estimatedFraudType;
1718
private List<String> keywords;
18-
private String additionalDescription;
19-
private String imageContent;
19+
private String explanation;
2020
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.blockguard.server.domain.analysis.dto.response;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
import java.util.List;
9+
10+
@Getter
11+
@Builder
12+
@AllArgsConstructor
13+
@NoArgsConstructor
14+
public class GptResponse {
15+
private Double score;
16+
private String estimatedFraudType;
17+
private List<String> keywords;
18+
private String explanation;
19+
}
20+

src/main/java/com/blockguard/server/global/common/codes/ErrorCode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ public enum ErrorCode {
2929
IMAGE_UPLOAD_LIMIT_EXCEEDED(HttpStatus.BAD_REQUEST, 4026, "이미지는 최대 2장까지만 업로드 가능합니다."),
3030

3131
// 5000~ : server error
32-
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000, "서버 오류가 발생했습니다.");
32+
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000, "서버 오류가 발생했습니다."),
33+
AI_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5001, "AI 서버와의 통신 오류가 발생했습니다.");
3334

3435
private final HttpStatus status;
3536
private final int code;

0 commit comments

Comments
 (0)