아앗 ! 이런 바보같은 실수를 !
[상황]
포트원 결제 API 요청하여 결제 완료 후
사용자의 신용카드 번호를 DB에 넣어야 함
[결제완료 카드 번호 데이터 넘기기 위해 아래 파일들 수정 과정]
1. StodDTO.java
private int creditNum;
신용카드 번호 데이터가 저장 될 컬럼 추가,
생성자 / getter / setter / toString 추가
2. StodMapper.xml
<!-- 사용자 결제 완료 시 결제 이력 테이블에 주문 정보 담기 위함 -->
<insert id="insertPayHty" parameterType="StodDTO">
INSERT INTO payHty (odNo, id, lstPrice, payType, slrName, slrNum, bsnsName, indst, kind, slrPhone, creditNum, state, cardType, instlFees, slrAddr)
VALUES (#{odNo}, #{id}, #{lstPrice}, #{payType}, #{slrName}, #{slrNum}, #{bsnsName}, #{indst}, #{kind}, #{slrPhone}, #{creditNum}, #{state}, #{cardType}, #{instlFees}, #{slrAddr})
</insert>
creditNum 추가
+ 사실 한꺼번에 담으려고 그 외 state, cardType 등을 많이 추가했음
3. order.jsp
<!-- iamport.payment.reponse.js -->
<script type="text/javascript" src="https://cdn.iamport.kr/v1/iamport.js"></script>
포트원 결제 reponse 값 받아오기 위함
<form id="orderData">
<input type="text" id="creditNum" name="creditNum">
</form>
order.jsp에 값이 제대로 넘어오는지 확인하기 위해 추가함
나중에는 type을 hidden으로 처리할 예정
4. order.js
// card 결제 API 호출
function payment(){
var IMP = window.IMP; //포트원 API 계정 번호
IMP.init("imp*****"); //포트원 API 계정 번호
const title = document.getElementById("title");
const lstPrice = document.getElementById("lstPrice");
const companyName = document.getElementById("bsnsName")
const id = document.getElementById("id");
const name = document.getElementById("name");
const phone = document.getElementById("phone");
const odNo = "jscd" + dateChange();
console.log(odNo);
IMP.request_pay({
pg: 'kcp',
pay_method: 'card',
merchant_uid: odNo,
name: title.value,
amount: lstPrice.value,
company: companyName.value, // 가져온 회사 이름을 사용
buyer_email: id.value,
buyer_name: name.value,
buyer_tel: phone.value,
}, function (rsp){
if(rsp.success){
console.log("creditNum:", rsp.card_number); //카드 번호
const creditNum = rsp.card_number;
console.log("creditNum 성공", creditNum);
console.log(odNo);
requestPay(odNo, creditNum);
}else{
console.log("실패");
}
});
}
rsp를 사용하면 포트원에서 결제 API 요청하여 결제 완료한 사용자의 카드 번호, 결제 시각 등의 파라미터 값을 가져올 수 있음.
rsp가 success 상태일 때, rsp.card_number를 creditNum 변수에 저장 후
requestPay()에 creditNum 인자를 추가하여 해당 메서드로 값이 넘어가게끔 하였음
//주문 및 결제 정보 데이터 넘기기
function requestPay(odNo, creditNum){
//odNo 값 추가해주기
$("#odNo").val(odNo);
//creditNum 값 추가해주기
$("#creditNum").val(creditNum);
console.log(creditNum);
// 1. serialize() 메서드를 사용하여 폼 데이터를 URL-encoded 문자열로 가져오기
const formDataString = $('#orderData').serialize();
// 2. URL-encoded 문자열을 객체로 변환
const formDataObject = {};
formDataString.split('&').forEach(pair => {
const [name, value] = pair.split('=');
formDataObject[name] = decodeURIComponent(value.replace(/\+/g, ' '));
});
// 2.1. creditNum 값을 formDataObject에 추가
formDataObject.creditNum = creditNum;
// 3. 객체를 JSON 문자열로 변환
const formDataJSON = JSON.stringify(formDataObject);
// JSON 문자열을 콘솔에 출력
console.log(formDataJSON);
$.ajax({
url: '/order/order',
type: 'POST',
contentType:"application/json; charset=utf-8",
data: formDataJSON,
success: function(response) {
console.log("성공");
}
});
}
payment()에서 넘겨받은 인자 creditNum의 value 값을 추가해주고,
만들어놓은 폼데이터인 formDataObject에 creditNum 값을 추가 후
해당 객체를 JSON 문자열로 변환해준 다음
ajax를 통해 /order/order url로 JSON 문자열을 OrderController.java 파일에 넘겨줌
5. OrderController.java
@PostMapping("/order")
@ResponseBody
public String submitOrder(@RequestBody StodDTO stodDto) throws Exception {
System.out.println("서버 측에서 주문 처리 중"+ stodDto);
//주문 정보 DB에 넣기
stodService.insertStod(stodDto);
//결제 정보 DB에 넣기
stodService.insertPayHty(stodDto);
return null;
}
order.js에서 ajax를 이용하여 POST 방식으로 formDataObject를 컨트롤러단에 전달하였으므로,
결제 정보를 DB에 넣는다.
그렇다면 ! 결제가 성공적으로 완료되었을 때,
결제이력 테이블인 payHty 테이블의 creditNum 컬럼에
결제 완료 된 신용카드 번호인 rsp.card_number의 value 값이 저장되어야 하는 것이 정상인데,
order.jsp에 creditNum의 데이터가 제대로 표시되었고, 잘 전달 된 것 같았는데
문제는 payHty 테이블의 creditNum 컬럼에 해당 데이터가 들어가지도 않았고,
아예 결제이력 테이블에 데이터가 insert 되지 않는 것 같다.
[문제 발생]
1. jsp 페이지단 에러 발생 (400 Bad Request)
결제 완료 했을 때 콘솔이나 jsp 페이지단에는 데이터가 잘 저장되었는데, 400 에러가 표시되었고,
▶️ 400 Bad Request
서버가 클라이언트 오류(예: 잘못된 요청 구문, 유효하지 않은 요청 메시지 프레이밍, 또는 변조된 요청 라우팅) 를 감지해
요청을 처리할 수 없거나, 하지 않는다는 것 의미
2. 서버 에러 발생 (NumberFormatException)
WARN : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: java.lang.NumberFormatException: Expected an int but was {rsp.card_Number} at line 1 column 283 path $.creditNum; nested exception is com.google.gson.JsonSyntaxException: java.lang.NumberFormatException: Expected an int but was {rsp.card_Number} at line 1 column 283 path $.creditNum
rsp.card_Number의 데이터 형식을 DB와 StodDTO.java 파일에서 int로 지정하였는데
rsp.card_Number로 받아오는 값이 신용카드 번호라서 이걸 숫자로 받아오기엔 int 범위에 초과되어 에러가 나는 모양이다.
[문제 해결 과정]
1. DB 수정 : 데이터 저장 형식 변경
문제의 creditNum 컬럼의 데이터 저장 형식을 VARCHAR(45)로 저장 후 Apply
commit;
인텔리제이와 연동하기 위해서 commit; 날려주면 DB 수정은 끝
2. StodDTO.java 수정 : 데이터 형식 변경
생성자, getter, setter, toString() 모두 지우고
private String creditNum;
기존 int 형식을 String 형식으로 변환 후
생성자, getter, setter, toString() 다시 추가해주었다.
[문제 해결 완료]
1. 콘솔창 출력 정상 확인
order.js에서 ajax로 넘긴 formDataJSON.creditNum의 value 값이 잘 출력되었음
2. DB에 creditNum 데이터 insert 정상 작동 확인
정상적으로 카드 번호가 잘 들어갔음
카드 번호, 영수증 번호 등
숫자 형식이라도 나열되는 숫자의 길이가 int의 범위를 벗어날 경우
StodDTO.java 파일에서 Integer 형식으로 저장하거나, String 형식으로 저장하는 방법을 사용할 수 있는데,
간편하게 String 형식으로 저장하였다.
뭐가 잘못된 것인가 한참을 고민했네
에러 메세지를 잘 보자.
'[Project] > 사이드 프로젝트' 카테고리의 다른 글
[404 Error] 파일 [/order/paySuccess.jsp]을(를) 찾을 수 없습니다. (0) | 2023.12.11 |
---|---|
[mysql/intellij] SQLException: Access denied for user 'root'@'localhost' (0) | 2023.12.10 |
[TypeError] order.js:113 Uncaught (in promise) TypeError (0) | 2023.12.09 |
[Spring] circular reference Error : 순환참조 에러 (1) | 2023.12.06 |
[Jscd/주문] 주문 내역 데이터 삽입 시점 (1) | 2023.12.06 |