Skip to content

Commit

Permalink
[MERGE/#55] 네이버 명함 OCR API 연동
Browse files Browse the repository at this point in the history
[FEAT] #55 - 네이버 명함 OCR API 연동
  • Loading branch information
seokbeom00 authored Jul 10, 2024
2 parents 3b84a7d + 1ad23eb commit 7328887
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class SecurityConfig {

private static final String[] AUTH_WHITE_LIST = {
"/api/v1/**",
"/api/v1/ocr/**",
"/api/v1/auth/**",
"/actuator/health",
"/v3/api-docs/**",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
@Getter
public class OcrConfig {

@Value("${naver.ocr.api.url}")
private String apiUrl;
@Value("${naver.ocr.api.univ-url}")
private String univUrl;

@Value("${naver.ocr.api.univ-key}")
private String univUrlKey;

@Value("${naver.ocr.api.business-url}")
private String businessUrl;

@Value("${naver.ocr.api.business-key}")
private String businessKey;

@Value("${naver.ocr.api.key}")
private String apiKey;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import lombok.RequiredArgsConstructor;
import org.sopt.seonyakServer.global.common.external.naver.dto.OcrBusinessResponse;
import org.sopt.seonyakServer.global.common.external.naver.dto.OcrUnivResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -18,7 +19,14 @@ public class OcrController {
private final OcrService ocrService;

@PostMapping("/univ")
public ResponseEntity<OcrUnivResponse> ocrText(@RequestParam("imageFile") MultipartFile file) throws IOException {
return ResponseEntity.ok(ocrService.ocrText(file));
public ResponseEntity<OcrUnivResponse> ocrUniv(@RequestParam("imageFile") MultipartFile file)
throws IOException {
return ResponseEntity.ok(ocrService.ocrUniv(file));
}

@PostMapping("/business-card")
public ResponseEntity<OcrBusinessResponse> ocrBusiness(@RequestParam("imageFile") MultipartFile file)
throws IOException {
return ResponseEntity.ok(ocrService.ocrBusiness(file));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import lombok.RequiredArgsConstructor;
import org.json.JSONArray;
import org.json.JSONObject;
import org.sopt.seonyakServer.global.common.external.naver.dto.OcrBusinessResponse;
import org.sopt.seonyakServer.global.common.external.naver.dto.OcrUnivResponse;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
Expand All @@ -25,20 +26,43 @@
public class OcrService {
private final OcrConfig ocrConfig;

public OcrUnivResponse ocrText(MultipartFile file) throws IOException {
// 대학명 OCR
public OcrUnivResponse ocrUniv(MultipartFile file) throws IOException {
// OCR 설정파일로부터 URL, Secret Key 가져옴
String apiUrl = ocrConfig.getApiUrl();
String apiKey = ocrConfig.getApiKey();
String apiUrl = ocrConfig.getUnivUrl();
String apiKey = ocrConfig.getUnivUrlKey();

// 네이버 OCR API 요청 헤더 설정
// 대학교 OCR 응답 문자열로 받아옴
String response = requestNaverOcr(apiUrl, apiKey, file);
return OcrUnivResponse.of(extractUnivText(response));
}

// 명함 OCR
public OcrBusinessResponse ocrBusiness(MultipartFile file) throws IOException {
// OCR 설정파일로부터 URL, Secret Key 가져옴
String apiUrl = ocrConfig.getBusinessUrl();
String apiKey = ocrConfig.getBusinessKey();

//회사명, 휴대전화번호 JSON 응답에서 파싱
String company = extractTextByKey(requestNaverOcr(apiUrl, apiKey, file), "company");
String phoneNumber = extractTextByKey(requestNaverOcr(apiUrl, apiKey, file), "mobile");
String cleanedNumber = phoneNumber.replaceAll("[^\\d]", "");
String lastEightNumber =
cleanedNumber.length() > 8 ? cleanedNumber.substring(cleanedNumber.length() - 8) : cleanedNumber;
return OcrBusinessResponse.of(company, "010" + lastEightNumber);
}

// 네이버 OCR API 요청 구성
public static String requestNaverOcr(String apiUrl, String apiKey, MultipartFile file)
throws IOException {
String boundary = "----" + UUID.randomUUID().toString().replaceAll("-", "");
URL url = new URL(apiUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setUseCaches(false);
con.setDoInput(true);
con.setDoOutput(true);
con.setReadTimeout(30000);
con.setRequestMethod("POST");
String boundary = "----" + UUID.randomUUID().toString().replaceAll("-", "");
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
con.setRequestProperty("X-OCR-SECRET", apiKey);

Expand Down Expand Up @@ -75,11 +99,9 @@ public OcrUnivResponse ocrText(MultipartFile file) throws IOException {
response.append(inputLine);
}
br.close();

return OcrUnivResponse.of(extractUnivText(response.toString()));
return response.toString();
}


// 네이버 공식문서 대로 OCR 요청 보내는 함수
private static void writeMultiPart(OutputStream out, String jsonMessage, MultipartFile file, String boundary)
throws IOException {
Expand Down Expand Up @@ -140,4 +162,25 @@ private String extractUnivText(String jsonResponse) {
})
.collect(Collectors.joining(","));
}

// 명함 OCR 응답에서 keyword에 해당하는 필드값을 추출하는 함수
private String extractTextByKey(String jsonResponse, String key) {
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONArray imagesArray = jsonObject.getJSONArray("images");

return IntStream.range(0, imagesArray.length())
.mapToObj(imagesArray::getJSONObject)
.filter(imageObject -> imageObject.has("nameCard"))
.map(imageObject -> imageObject.getJSONObject("nameCard"))
.filter(nameCard -> nameCard.has("result"))
.map(nameCard -> nameCard.getJSONObject("result"))
.filter(result -> result.has(key))
.flatMap(result -> {
JSONArray textArray = result.getJSONArray(key);
return IntStream.range(0, textArray.length())
.mapToObj(textArray::getJSONObject);
})
.map(textObject -> textObject.getString("text"))
.collect(Collectors.joining(", "));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.seonyakServer.global.common.external.naver.dto;

public record OcrBusinessResponse(
String company,
String phoneNumber
) {
public static OcrBusinessResponse of(String company, String phoneNumber) {
return new OcrBusinessResponse(company, phoneNumber);
}
}

0 comments on commit 7328887

Please sign in to comment.