Spring boot kim's Shop/리팩토링

Springboot 결제 시스템 리팩토링!(1) 카드/가상계좌 세틀뱅크

디비드킴 2021. 9. 15. 23:38

바보였다

테스트 신청하자마자 하면 되는 거였는데 

3일 전에 알고 부랴부랴 시스템을 개편했다

진짜 힘들었다

 

변동사항

 

결제 요청

이전

아임 포트-> 세틀 뱅크

현재

세틀 뱅크 디렉트 연결

 

예약시스템

이전

총액 받기->가상계좌라면 날짜 받기

현재

필요 정보 한 번에 다 받기

 

예약+결제

이전

예약 시도-> 결제 후 검증-> db저장

현재

예약 시도-> 결제/상품 임시 테이블 저장-> 결제 검증-> 메인테이블 저장

임시 테이블은 재고에 안 잡히고 결제 영향도 없는 테이블이다

그냥 스프링 스케줄러+배치로 하루에 한 번씩만 비워주면 될 거 같다

 

테이블 구조도 변경하였다

예약은 예약정보만/결제는 결제정보만 들고 있을 수 있게 했다

결제 테이블도 card/vbank/kakaopay 이렇게 종류별로 나눴다

 

아 개편하는데 아예 새로 만드는 과정이어서

정말 힘들었다

 

주의사항

세틀 뱅크 가이드를 잘 봐야 한다

 

pg사를 디렉트로 붙이면서 오히려 

더 명확히 정리되는 거 같다

 

프런트 서버

card
vbank

세틀 뱅크 요청전 

세틀뱅크 가이드대로 정보를 가공해서 가져온다

vbnk
vbank

여기서 통신이 이뤄지고

웹 훅

 "notiUrl": "http://kim80800.iptime.org:8080/auth/settlebank",

결제 완료 후 페이지

"nextUrl": "https://localhost:8443/doneSettlebankPage.jsp",

결제 취소 페이지는

"cancUrl": "http://kim80800.iptime.org:8080/auth/settlebank",

그냥 안 만들어놔서 이상 태이다(추후 만들 예정)

 

결제 완료 페이지

jsp를 이용하였다

vscode

얘를 받으면 가능하다

doneSettlebankPage.jsp
doneSettlebankPage.jsp

 

jsp는 세틀 뱅크 예제 소스에 나와있다 복붙 하면 된다

스크립트 부분은 좀 막일인데 json으로 만들어서 백엔드 에게 던지면 된다

백엔드로 가보자

 

백엔드 서버

paymentService

paymentService.java

예약/일반상품인지 구별

 String kind=aboutPayEnums.valueOf(getHashInfor.getKind()).getString();

결제 총액 계산

 String price=Integer.toString(priceService.responeTotalprice(getHashInfor.getProductNameAndCount()));

세틀 뱅크에서 요구하는대로 해시한다

String pktHash=sha256.encrypt(requestPayString(getHashInfor));

String hashPrice=aes256.encrypt(price);

임시 결제 테이블 저장

 tempService.insert(emailmchtTrdNoprice);

가상계좌였다면 입금 기한 생성      response.put("expiredate",  getVbankDate(kindgetHashInfor.getYear(), getHashInfor.getMonth() , getHashInfor.getDate(), getHashInfor.getTimes()));

임시 예약/상품 테이블 저장

if(kind.equals(aboutPayEnums.reservation.getString())){

 

responeTotalprice

priceService.java

구매한 상품 이름/개수가 들어있는 배열

String[][] productNameAndCount

(json이 아니여서 어질어질하다 ㅋㅋ)

상품 이름으로 상품정보 찾아오기

productDto productDto=selectProduct(productNameAndCount[i][0]);

재고 검사 및 유효성 검사

priceEnums priceEnums=confrimProduct(productDto,count);

가격 계산

totalPrice+=getTotalPrice(productDto.getPrice(),count);

 

requestPayString

paymentService.java

세틀 뱅크 요구 사항대로 해시할 문자열을 만든다

 

나머지 해시 규격은

세틀뱅크 요구 사항대로 해시해야 한다

샘플 소스를 다운로드하여서 그대로 넣었다

이거 때문에 엄청 고생했다 

결국 샘플 소스에 있는걸 그대로 넣으니 성공했다

(홈페이지에서 로그인 후 다운 받을 수있다)

 

 

나머지도 많이 바뀌었으나

큰 틀은 그대로이니 넘어가자

 

여기까지 성공했으면 결제창을 띄울 수 있다

 

테스트

카드
가상계좌

결제창 띄우기가 제일 어렵다 

거의 다 한 거다 여기까지 왔다면 ㅋㅋㅋ

dto

getHashInfor.java

 

결제 후 검증

 

paymentService

paymentService.java

받은 정보 복호화

byte[] aesCipherRaw=aes256.decodeBase64(reseponseSettleDto.getTrdAmt());

String trdAmt =new String(aes256.aes256DecryptEcb(aesCipherRaw),"UTF-8");

결제방식에 따라 테이블 저장

if(reseponseSettleDto.getMchtId().equals(aboutPayEnums.cardmehtod.getString()))

상품에 따라 테이블 저장

if(reseponseSettleDto.getMchtTrdNo().startsWith(aboutPayEnums.reservation.getString()))

상품 아이디 발급 때 예약이면 reservation뭐 일반이면 product뭐 이렇게 붙어있다

(일반상품은 아직 미구현)

검증 실패시

채번취소/환불 

 throw new failBuyException(e.getMessage(),reseponseSettleDto);

(환불 로직은 다음장에서 보자)

 

테스트

 

상품 구매 시도(결제 전)

임시 테이블에 정보 저장

https://localhost:8443/reservationPagevar3.html

trid가 6000번 때인 이유는

함수 한번 잘못 돌렸다 저렇게 됐다 크흡

 

결제 완료/요청 후

https://localhost:8443/reservationPagevar3.html
https://localhost:8443/reservationPagevar3.html
https://localhost:8443/showReservationPage.html

db에 잘 들어갔다

 

카드결제 마찬가지로 잘된다!

(가상계좌 입금 테스트는 다음장에서 다뤄보자)

 

3일 동안 한 33시간 정도 코딩했다..

이게 결제시스템만 바꾼 게 아니라 

알고리즘 자체를 진짜 싹 갈아엎었다

현재 보고 있는 예약 내역 페이지도 

알고리즘이 바뀌었다

(다음장에서 다뤄보자)

덕분에 카카오 페이도 좀 손봐야 한다

일단 이거부터 끝내자!

 

++추가

paymentService.java

json이긴한데 애는 이렇게 통신해야한다

앞에 accept로 해줘야한다 

(이유는 모른다 샘플코드도 그냥 sjon으로 되어있는데..)

한참 헤매다가 

https://stackoverflow.com/questions/48799409/invalid-mime-type-in-spring-rest-template

 

Invalid mime type in spring rest template?

I am just trying to make a simple REST request like below String url = "some url"; MultiValueMap<string, string=""> headers = new LinkedMultiValueMap<>(); headers.add(HttpHeaders.CONTENT_...</string,>

stackoverflow.com

여기서 보고 찾았는데 작동했다