Skip to content

Commit

Permalink
Merge pull request #119 from 9oormthon-univ/feature/#111
Browse files Browse the repository at this point in the history
✨ [FEAT] swagger 추가 및 인증 로직 스케줄러 구현
  • Loading branch information
20210815 authored Dec 3, 2024
2 parents 4d7242b + f7e97a7 commit d61fe5e
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 90 deletions.
1 change: 1 addition & 0 deletions src/main/java/com/carely/backend/code/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public enum ErrorCode {
LIKE_NOT_FOUND(HttpStatus.NOT_FOUND, "그룹을 찜하지 않은 유저입니다."),
CERTIFICATE_FAIL(HttpStatus.NOT_FOUND, "자격증 인증에 실패했습니다."),
HAS_NOT_CERTIFICATE(HttpStatus.NOT_FOUND, "자격증이 존재하지 않는 유저입니다."),
NOT_IDENTITY_USER(HttpStatus.NOT_FOUND, "주민등록번호가 유효하지 않습니다."),

NEWS_NOT_FOUND(HttpStatus.NOT_FOUND, "소식을 찾을 수 없습니다."),
CACHE_NOT_FOUND(HttpStatus.NOT_FOUND, "캐시를 찾을 수 없거나 해당 트랜잭션은 이미 실행된 것입니다."),
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/carely/backend/code/SuccessCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public enum SuccessCode {
SUCCESS_ISSUE_CERTIFICATE(HttpStatus.OK, "자격증을 성공적으로 발급하였습니다."),
SUCCESS_RETRIEVE_ACTIVITY_LIST(HttpStatus.OK, "활동 목록을 성공적으로 조회하였습니다."),
SUCCESS_RETRIEVE_CERTIFICATE(HttpStatus.OK, "성공적으로 자격증 검색을 완료했습니다."),

SUCCESS_GET_IDENTITY(HttpStatus.OK, "주민등록번호가 인증되었습니다."),


/**
Expand Down
208 changes: 129 additions & 79 deletions src/main/java/com/carely/backend/controller/EasyCodefController.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
package com.carely.backend.controller;

import com.carely.backend.code.SuccessCode;
import com.carely.backend.controller.docs.EasyCodefAPI;
import com.carely.backend.dto.easyCodef.AdditionalAuthDTO;
import com.carely.backend.dto.easyCodef.RequestUserIdentityDTO;
import com.carely.backend.dto.easyCodef.UserIdentityDTO;
import com.carely.backend.dto.response.ResponseDTO;
import com.carely.backend.exception.IdentityNotAcceptableException;
import com.carely.backend.exception.ObjectNullException;
import com.carely.backend.service.CacheService;
import com.carely.backend.service.EasyCodef.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.cache.annotation.Cacheable;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

@RequestMapping
@RestController
@RequiredArgsConstructor
public class EasyCodefController {
public class EasyCodefController implements EasyCodefAPI {
private final EasyCodef easyCodef;
private final EasyCodefProperties easyCodefProperties;
private final CacheService cacheService;
private final String url = "/v1/kr/public/mw/identity-card/check-status";

@PostMapping("/token")
Expand All @@ -36,8 +45,10 @@ public String getToken() throws IOException {
}

@PostMapping("/connect")
public EasyCodefResponse connectAPI(@RequestBody RequestUserIdentityDTO requestUserIdentityDTO) throws InterruptedException, UnsupportedEncodingException, JsonProcessingException {
public ResponseEntity<ResponseDTO> connectAPI(@RequestBody RequestUserIdentityDTO requestUserIdentityDTO) throws InterruptedException, UnsupportedEncodingException, JsonProcessingException {
System.out.println(easyCodefProperties.getDemoAccessToken());

// UserIdentityDTO 생성
UserIdentityDTO userIdentityDTO = UserIdentityDTO.builder()
.organization("0002")
.loginType("6")
Expand All @@ -54,90 +65,129 @@ public EasyCodefResponse connectAPI(@RequestBody RequestUserIdentityDTO requestU
.identityEncYn("")
.build();

// DTO → HashMap 변환
HashMap<String, Object> resultMap = new ObjectMapper().convertValue(userIdentityDTO, HashMap.class);

HashMap<String, Object> resultMap = new HashMap<>();
ObjectMapper mapper = new ObjectMapper();
try {
// DTO -> HashMap
String json = mapper.writeValueAsString(userIdentityDTO);
resultMap = mapper.readValue(json, HashMap.class);
System.out.println("Deserialized HashMap: " + resultMap);

} catch (Exception e) {
e.printStackTrace();
}


// /connect 처리
EasyCodefResponse response = easyCodef.requestProduct(url, 1, resultMap);
System.out.println("Connect API Response: " + response);

EasyCodefResponse string = easyCodef.requestProduct(url, 1, resultMap);
// 'data' 객체 가져오기
Map<String, Object> dataMap = (Map<String, Object>) string.get("data");
Map<String, Object> dataMap = (Map<String, Object>) response.get("data");

// 'jti' 값 가져오기
// 'jti' 값 및 타임스탬프 가져오기
String jti = (String) dataMap.get("jti");

cacheService.save(jti, userIdentityDTO);
System.out.println(cacheService.get(jti));
return string;
Long twoWayTimestamp = (Long) dataMap.get("twoWayTimestamp");

// 동기식 응답 처리를 위한 CountDownLatch 생성
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<ResponseDTO> finalResponse = new AtomicReference<>();

// 7초 뒤 /additional-info 호출
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> {
try {
// 추가 인증 DTO 생성
AdditionalAuthDTO authDTO = AdditionalAuthDTO.builder()
.organization(userIdentityDTO.getOrganization())
.identity(userIdentityDTO.getIdentity())
.userName(userIdentityDTO.getUserName())
.issueDate(userIdentityDTO.getIssueDate())
.simpleAuth("1")
.is2Way(true)
.twoWayInfo(AdditionalAuthDTO.TwoWayInfoDTO.builder()
.jti(jti)
.twoWayTimestamp(twoWayTimestamp)
.jobIndex(0)
.threadIndex(0)
.build())
.build();

// 추가 인증 로직
LinkedHashMap<String, Object> twoResultMap = new ObjectMapper().convertValue(authDTO, LinkedHashMap.class);
EasyCodefResponse additionalResponse = easyCodef.requestCertification(url, 1, twoResultMap);

// 인증 결과 처리
Map<String, Object> resultMapper = (Map<String, Object>) additionalResponse.get("result");
String code = (String) resultMapper.get("code");
System.out.println("Additional Info API Response Code: " + code);

if (!Objects.equals(code, "CF-00000")) {
throw new IdentityNotAcceptableException("안 됨");
} else {
finalResponse.set(new ResponseDTO(SuccessCode.SUCCESS_GET_IDENTITY, "Authentication successful"));
}
} catch (Exception e) {
System.err.println("추가 인증 중 오류 발생: " + e.getMessage());
throw new IdentityNotAcceptableException("안 됨");
} finally {
latch.countDown(); // 작업 완료 신호
scheduler.shutdown(); // 스케줄러 종료
throw new IdentityNotAcceptableException("안 됨");

}
}, 7, TimeUnit.SECONDS);

// 작업 완료 대기
latch.await();

// 최종 응답 반환
return ResponseEntity
.status(SuccessCode.SUCCESS_GET_IDENTITY.getStatus().value())
.body(finalResponse.get());
}


//추가인증 특이사항
//
//- 간편인증시 인증을 완료하지 않고 간편인증(simpleAuth)에 "1"을 입력할 경우 2번까지는 재시도, 3번 시도시 CF-12872 오류 발생
@PostMapping("/additional-info")
public EasyCodefResponse handleAdditionalAuth(@RequestBody AdditionalAuthDTO.TwoWayInfoDTO twoWayInfoDTO) throws UnsupportedEncodingException, JsonProcessingException, InterruptedException {
if (cacheService.get(twoWayInfoDTO.getJti()) == null) {
throw new ObjectNullException("캐시 쓴 거임");
}
UserIdentityDTO userIdentityDTO = (UserIdentityDTO) cacheService.get(twoWayInfoDTO.getJti());
AdditionalAuthDTO authDTO = AdditionalAuthDTO.builder()
.organization(userIdentityDTO.getOrganization())
.identity(userIdentityDTO.getIdentity())
.userName(userIdentityDTO.getUserName())
.issueDate(userIdentityDTO.getIssueDate())
.simpleAuth("1")
.is2Way(true)
.twoWayInfo(twoWayInfoDTO)
.build();


LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
ObjectMapper mapper = new ObjectMapper();
try {
// DTO → JSON 변환
String json = mapper.writeValueAsString(authDTO);
System.out.println("Serialized JSON: " + json);

// JSON → HashMap 변환
resultMap = mapper.readValue(json, LinkedHashMap.class);
System.out.println("Deserialized HashMap: " + resultMap);

// 특정 값 확인
System.out.println("is2Way Value: " + resultMap.get("is2Way"));
System.out.println("TwoWayInfo: " + resultMap.get("twoWayInfo"));
} catch (Exception e) {
e.printStackTrace();
// 일단 갖고 있는 주민번호로 지움...
cacheService.clear(authDTO.getIdentity());
}


EasyCodefResponse string = easyCodef.requestCertification(url, 1, resultMap);

// 'result' 객체 가져오기
Map<String, Object> dataMap = (Map<String, Object>) string.get("result");

// 'code' 값 가져오기
String code = (String) dataMap.get("code");

if (!Objects.equals(code, "CF-00000")) { // 인증이 안 된 거임.
cacheService.clear(authDTO.getIdentity());
}
// 어떻게 해야 할지.....


return string;
}
// @PostMapping("/additional-info")
// public EasyCodefResponse handleAdditionalAuth(@RequestBody AdditionalAuthDTO.TwoWayInfoDTO twoWayInfoDTO) throws UnsupportedEncodingException, JsonProcessingException, InterruptedException {
// if (cacheService.get(twoWayInfoDTO.getJti()) == null) {
// throw new ObjectNullException("캐시 쓴 거임");
// }
// UserIdentityDTO userIdentityDTO = (UserIdentityDTO) cacheService.get(twoWayInfoDTO.getJti());
// AdditionalAuthDTO authDTO = AdditionalAuthDTO.builder()
// .organization(userIdentityDTO.getOrganization())
// .identity(userIdentityDTO.getIdentity())
// .userName(userIdentityDTO.getUserName())
// .issueDate(userIdentityDTO.getIssueDate())
// .simpleAuth("1")
// .is2Way(true)
// .twoWayInfo(twoWayInfoDTO)
// .build();
//
//
// LinkedHashMap<String, Object> resultMap = new LinkedHashMap<>();
// ObjectMapper mapper = new ObjectMapper();
// try {
// // DTO → JSON 변환
// String json = mapper.writeValueAsString(authDTO);
// System.out.println("Serialized JSON: " + json);
//
// // JSON → HashMap 변환
// resultMap = mapper.readValue(json, LinkedHashMap.class);
// System.out.println("Deserialized HashMap: " + resultMap);
//
// // 특정 값 확인
// System.out.println("is2Way Value: " + resultMap.get("is2Way"));
// System.out.println("TwoWayInfo: " + resultMap.get("twoWayInfo"));
// } catch (Exception e) {
// e.printStackTrace();
// }
//
//
// EasyCodefResponse string = easyCodef.requestCertification(url, 1, resultMap);
//
// // 'result' 객체 가져오기
// Map<String, Object> dataMap = (Map<String, Object>) string.get("result");
//
// // 'code' 값 가져오기
// String code = (String) dataMap.get("code");
//
// if (!Objects.equals(code, "CF-00000")) { // 인증이 안 된 거임.
// cacheService.clear(authDTO.getIdentity());
// }
// return string;
// }

}
50 changes: 50 additions & 0 deletions src/main/java/com/carely/backend/controller/docs/EasyCodefAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.carely.backend.controller.docs;

import com.carely.backend.dto.easyCodef.AdditionalAuthDTO;
import com.carely.backend.dto.easyCodef.RequestUserIdentityDTO;
import com.carely.backend.dto.response.ErrorResponseDTO;
import com.carely.backend.dto.response.ResponseDTO;
import com.carely.backend.service.EasyCodef.EasyCodefResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.UnsupportedEncodingException;

public interface EasyCodefAPI {
@Operation(summary = "주민번호 인증", description = "주민등록번호를 인증합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "주민번호 인증에 성공했을 경우",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = ResponseDTO.class),
examples = @ExampleObject(value = """
{
"status": 200,
"code": "SUCCESS_GET_IDENTITY",
"message": "주민등록번호가 인증되었습니다.",
"data": null
}
"""))),

@ApiResponse(responseCode = "404", description = "주민등록번호가 유효하지 않거나, 인증되지 않은 경우",
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = ErrorResponseDTO.class),
examples = {
@ExampleObject(value = """
{
"status": 404,
"code": "NOT_IDENTITY_USER",
"message": "주민등록번호가 유효하지 않습니다..",
"data": null
}
""")
}))
})
public ResponseEntity<ResponseDTO> connectAPI(@RequestBody RequestUserIdentityDTO requestUserIdentityDTO) throws InterruptedException, UnsupportedEncodingException, JsonProcessingException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.carely.backend.dto.document;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class ResponseDocumentDTO {
private String myType;
private String myName;
private String volunteerSessionType;
private String partnerType;
private String partnerName;
private String volunteerDate;
private String myIdentity;
private String address;
private int durationTimes;
private String content;
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ protected ResponseEntity<ErrorResponseDTO> handleObjectNullException(final Objec
.body(new ErrorResponseDTO(ErrorCode.CACHE_NOT_FOUND));
}

@ExceptionHandler(IdentityNotAcceptableException.class)
protected ResponseEntity<ErrorResponseDTO> handleIdentityNotAcceptableException(final IdentityNotAcceptableException e) {
return ResponseEntity
.status(ErrorCode.NOT_IDENTITY_USER.getStatus().value())
.body(new ErrorResponseDTO(ErrorCode.NOT_IDENTITY_USER));
}

@ExceptionHandler(AlreadyHasCertificateException.class)
protected ResponseEntity<ErrorResponseDTO> handleAlreadyHasCertificateException(final AlreadyHasCertificateException e) {
return ResponseEntity
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.carely.backend.exception;

public class IdentityNotAcceptableException extends RuntimeException{
public IdentityNotAcceptableException(String message) {
super(message);
}
}
20 changes: 10 additions & 10 deletions src/main/java/com/carely/backend/service/DocumentIssuedService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
public class DocumentIssuedService {
public final CertificateService certificateService;
public final UserRepository userRepository;


public void getDocumentIssuedList(String username, String documentType) {
User user = userRepository.findByKakaoId(username)
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));

List<VolunteerListDTO> list= certificateService.getVolunteerSessionsByUserIdAndType(documentType, user.getId().toString());


}
//
//
// public void getDocumentIssuedList(String username, String documentType) {
// User user = userRepository.findByKakaoId(username)
// .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다."));
//
// List<VolunteerListDTO> list= certificateService.getVolunteerSessionsByUserIdAndType(documentType, user.getId().toString());
//
//
// }
}
Loading

0 comments on commit d61fe5e

Please sign in to comment.