diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java index b1b94f51..e64b84fe 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/controller/BasLaancController.java @@ -5,6 +5,7 @@ import com.palnet.biz.api.bas.laanc.service.BasLaancService; import com.palnet.biz.api.comn.response.BasicResponse; import com.palnet.biz.api.comn.response.ErrorResponse; import com.palnet.biz.api.comn.response.SuccessResponse; +import com.palnet.biz.api.external.model.PilotValidRs; import com.palnet.comn.exception.CustomException; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -165,11 +166,10 @@ public class BasLaancController { return ResponseEntity.ok().body(new SuccessResponse<>(rs)); } -// @GetMapping(value = "/ts/qr", produces = MediaType.IMAGE_JPEG_VALUE) @GetMapping(value = "/ts/qr") @ApiOperation(value = "TS QR 코드 생성") @Tag(name = "LAANC", description = "LAANC 관련 API") - public ResponseEntity getQrCode(BasLaancQrcodeRq rq) { + public ResponseEntity getQrCode(BasLaancQrcodeRq rq) { BasLaancQrcodeRs rs = null; try { rs = basLaancService.createQrcode(rq); @@ -186,7 +186,32 @@ public class BasLaancController { .body(new ErrorResponse("Server Error", "-1")); } - return new ResponseEntity<>(rs, HttpStatus.OK); + return new ResponseEntity<>(new SuccessResponse<>(rs), HttpStatus.OK); } + + @GetMapping(value = "/ts/qr/{confirmKey}") + @ApiOperation(value = "TS QR 코드 확인 - RS왔는지 확인") + @Tag(name = "LAANC", description = "LAANC 관련 API") + public ResponseEntity checkRqcodeRs(@PathVariable("confirmKey") String confirmKey) { + PilotValidRs rs = null; + try { + rs = basLaancService.checkQrcode(confirmKey); + } catch (CustomException e) { + Map resultMap = new HashMap<>(); + log.error("IGNORE : ", e); + resultMap.put("result", false); + resultMap.put("errorCode", e.getErrorCode()); + resultMap.put("errorMessage", e.getMessage()); + return ResponseEntity.ok().body(new SuccessResponse(resultMap)); + } catch (Exception e) { + log.error("IGNORE : ", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(new ErrorResponse("Server Error", "-1")); + + } + return new ResponseEntity<>(new SuccessResponse<>(rs), HttpStatus.OK); + } + + } diff --git a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java index f2338bc2..05fa5fcc 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/bas/laanc/service/BasLaancService.java @@ -18,8 +18,8 @@ import com.palnet.biz.api.external.service.TsService; import com.palnet.biz.jpa.entity.*; import com.palnet.biz.jpa.entity.type.ArcrftWghtCd; import com.palnet.biz.jpa.entity.type.FltMethod; -import com.palnet.biz.jpa.entity.type.FltPurpose; import com.palnet.biz.jpa.entity.type.FltType; +import com.palnet.biz.jpa.repository.com.ComConfirmBasRepository; import com.palnet.biz.jpa.repository.com.ComRiseSetQueryRepository; import com.palnet.biz.jpa.repository.flt.*; import com.palnet.biz.jpa.repository.pty.PtyCstmrQueryRepository; @@ -45,9 +45,9 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -82,6 +82,7 @@ public class BasLaancService { private final JwtTokenUtil jwtTokenUtil; private final AreaUtils areaUtils; private final ComRiseSetQueryRepository comRiseSetQueryRepository; + private final ComConfirmBasRepository comConfirmBasRepository; @Value("${app.host}") private String APP_HOST; @@ -613,25 +614,19 @@ public class BasLaancService { // QR code 생성 public BasLaancQrcodeRs createQrcode(BasLaancQrcodeRq rq) { -// if(rq == null || rq.getFltPurpose() == null || rq.getIdntfNum() == null || rq.getIdntfNum().isEmpty()) { -// throw new CustomException(ErrorCode.NON_VALID_PARAMETER); -// } - Integer cstmrSno = jwtTokenUtil.getCstmrSnoByToken(); + String userId = jwtTokenUtil.getUserIdByToken(); AnctCstmrModel cstmrInfo = ptyCstmrQueryRepository.findByCstmrSno(cstmrSno); String userCi = cstmrInfo.getIpinCi(); -// String fltPurposeCode = null; -// if (rq != null && rq.getFltPurpose() != null && !rq.getFltPurpose().isEmpty()) { -//// fltPurposeCode = Objects.requireNonNull(FltPurpose.fromCode(rq.getFltPurpose())).getCode(); -// fltPurposeCode = rq.getFltPurpose(); -// } + String idntfNum = null; - if(rq != null && rq.getIdntfNum() != null && !rq.getIdntfNum().isEmpty()){ + if (rq != null && rq.getIdntfNum() != null && !rq.getIdntfNum().isEmpty()) { idntfNum = rq.getIdntfNum(); } String confirmKey = UUID.randomUUID().toString(); + String jsonParams = null; byte[] qr = null; try { TsQrcodeRq tsRq = TsQrcodeRq.builder() @@ -641,16 +636,25 @@ public class BasLaancService { .applyUser(userCi) .build(); - String str = JsonUtils.toJson(tsRq); + jsonParams = JsonUtils.toJson(tsRq); - qr = tsService.createQrcode(str); + qr = tsService.createQrcode(jsonParams); } catch (WriterException | IOException e) { log.error("ERROR: ", e); throw new CustomException(ErrorCode.FAIL, "QR코드 생성 실패"); } // db 저장 - confirmKey(uuid) + ComConfirmBas comConfirmBas = ComConfirmBas.builder() + .confirmKey(confirmKey) + .status("GENERATED") + .targetType("TS_QRCODE") + .rqData(jsonParams) + .createUserId(userId) + .updateUserId(userId) + .build(); + comConfirmBasRepository.save(comConfirmBas); return BasLaancQrcodeRs.builder() .qrcode(qr) @@ -658,4 +662,31 @@ public class BasLaancService { .build(); } + + // QR code 확인 + public PilotValidRs checkQrcode(String confirmKey) { + + String userIdByToken = jwtTokenUtil.getUserIdByToken(); + ComConfirmBas entity = comConfirmBasRepository.findFirstByConfirmKeyOrderByCreateDtDesc(confirmKey); + if (entity == null || "RECEIVED".equals(entity.getStatus())) throw new CustomException(ErrorCode.DATA_NOTFIND, "QR코드 조회 실패"); + + // TODO 일자 검증 - 3분 초과 + Instant createDt = entity.getCreateDt().plus(3, ChronoUnit.MINUTES); + boolean flag = !createDt.isAfter(Instant.now()); + if (!flag) { + entity.setStatus("EXPIRED"); + entity.setUpdateUserId(userIdByToken); + comConfirmBasRepository.save(entity); + comConfirmBasRepository.flush(); + throw new CustomException(ErrorCode.FAIL, "QR 기간 만료"); + } + + PilotValidRs rs = null; + String rsData = entity.getRsData(); + if(rsData != null && !rsData.isEmpty()){ + rs = JsonUtils.fromJson(rsData, PilotValidRs.class); + } + + return rs; + } } diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java b/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java index 8c1333c1..1d00fdd8 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java +++ b/pav-server/src/main/java/com/palnet/biz/api/external/controller/ExternalLaancController.java @@ -1,5 +1,8 @@ package com.palnet.biz.api.external.controller; +import com.palnet.biz.api.bas.laanc.service.BasLaancService; +import com.palnet.biz.api.external.model.TsQrcodeRs; +import com.palnet.biz.api.external.service.TsService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; @@ -14,6 +17,8 @@ import org.springframework.web.bind.annotation.RestController; @RestController public class ExternalLaancController { + private final BasLaancService basLaancService; + private final TsService tsService; // TS로 부터 비행 신청 정보 - endpoint @PostMapping("/plan/ost") @@ -22,12 +27,11 @@ public class ExternalLaancController { return ResponseEntity.ok().build(); } - - // TS VC 유효성 검토 callback url - endpoint @PostMapping("/vc/callback") - public ResponseEntity vcCallback(@RequestBody String body) { - log.info(">>>> vc/callback body: {}", body); + public ResponseEntity vcCallback(@RequestBody TsQrcodeRs rs) { + log.info(">>>> vc/callback body: {}", rs); + tsService.vcCallback(rs); return ResponseEntity.ok().build(); } diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java b/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java index 26b30ced..66d272f7 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java +++ b/pav-server/src/main/java/com/palnet/biz/api/external/model/TsQrcodeRs.java @@ -23,6 +23,7 @@ import lombok.NoArgsConstructor; public class TsQrcodeRs { private String rspCode; // 결과코드 private String rspMessage; // 결과메시지 + private String rqID; // 요청ID-UUID private String pilotcredentialyn; // 조종사자격증명여부 private String arcrftinsuranceyn; // 기체보험가입여부 private String arcrftdeclaration; // 기체신고여부 diff --git a/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java b/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java index 5a1254f4..923f5b6c 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/external/service/TsService.java @@ -9,6 +9,10 @@ import com.google.zxing.qrcode.QRCodeWriter; import com.palnet.biz.api.external.model.PilotValidRq; import com.palnet.biz.api.external.model.PilotValidRs; import com.palnet.biz.api.external.model.TsQrcodeRq; +import com.palnet.biz.api.external.model.TsQrcodeRs; +import com.palnet.biz.jpa.entity.ComConfirmBas; +import com.palnet.biz.jpa.repository.com.ComConfirmBasRepository; +import com.palnet.comn.utils.JsonUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -50,6 +54,8 @@ public class TsService { private String TS_HOST; private final String ACCOUNT_VALIDATE_URI = "/api/account/getValidate"; + private final ComConfirmBasRepository comConfirmBasRepository; + // 이전 TS 연동 public List getAccountValidate(List rqList) { @@ -100,7 +106,7 @@ public class TsService { log.error("TS API 호출 중 오류가 발생하였습니다. {}", e.getMessage()); String erroCode = "500"; String errorMessage = "TS API error"; - if(e instanceof WebClientResponseException){ + if (e instanceof WebClientResponseException) { WebClientResponseException wcre = (WebClientResponseException) e; erroCode = String.valueOf(wcre.getRawStatusCode()); errorMessage = wcre.getStatusText(); @@ -145,4 +151,16 @@ public class TsService { return outputStream.toByteArray(); } + + // QR return url + public void vcCallback(TsQrcodeRs rs) { + String rspCode = rs.getRspCode(); + ComConfirmBas entity = comConfirmBasRepository.findFirstByConfirmKey(rs.getRqID()); + if (entity != null) { + String rsJsonStr = JsonUtils.toJson(rs); + entity.setRsData(rsJsonStr); + entity.setStatus(("200".equals(rspCode)) ? "RECEIVED" : "FAILED"); + comConfirmBasRepository.save(entity); + } + } } diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java index 1419be44..b12d56cb 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java @@ -40,7 +40,7 @@ public class CnsFaqBas implements Serializable { @Column(name="DEL_YN") private String delYn = "N"; - @Column(name="CREATE_USER_ID") + @Column(name="CREATE_USER_ID", updatable = false) private String createUserId; @CreationTimestamp diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComConfirmBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComConfirmBas.java new file mode 100644 index 00000000..6df3323e --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/ComConfirmBas.java @@ -0,0 +1,58 @@ +package com.palnet.biz.jpa.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import javax.persistence.*; +import java.time.Instant; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "COM_CONFIRM_BAS") +public class ComConfirmBas { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "CONFIRM_SNO") + private Integer confirmSno; + + @Column(name = "STATUS") + private String status; // GENERATED, RECEIVED, CHECKED, FAILED, EXPIRED + + @Column(name = "CONFIRM_KEY") + private String confirmKey; + + @Column(name = "TARGET_TYPE") + private String targetType; + + @Column(name = "RQ_DATA") + private String rqData; + + @Column(name = "RS_DATA") + private String rsData; + + @Column(name = "RM") + private String rm; + + @Column(name = "CREATE_USER_ID") + private String createUserId; + + @CreationTimestamp + @Column(name = "CREATE_DT", columnDefinition = "TIMESTAMP", updatable = false) + private Instant createDt; + + @Column(name = "UPDATE_USER_ID") + private String updateUserId; + + @UpdateTimestamp + @Column(name = "UPDATE_DT", columnDefinition = "TIMESTAMP") + private Instant updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComConfirmBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComConfirmBasRepository.java new file mode 100644 index 00000000..105d0d6d --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComConfirmBasRepository.java @@ -0,0 +1,13 @@ +package com.palnet.biz.jpa.repository.com; + +import com.palnet.biz.jpa.entity.ComConfirmBas; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ComConfirmBasRepository extends JpaRepository { + + ComConfirmBas findFirstByConfirmKey(String confirmKey); + + ComConfirmBas findFirstByConfirmKeyOrderByCreateDtDesc(String confirmKey); +}