• 티스토리 홈
  • 프로필사진
    Song hyun
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
Song hyun
  • 프로필사진
    Song hyun
    • 분류 전체보기 (780)
      • 영어 (2)
        • Diary (0)
        • Toast Masters (2)
      • 메모 (13)
      • 설치 메뉴얼 (30)
      • Java (178)
      • MySQL (60)
      • JSP (67)
      • Springboot (46)
      • HTML,CSS, JS (71)
        • HTML (8)
        • CSS (12)
        • JavaScript (37)
        • HTML&CSS 스터디 (13)
      • C++ (7)
      • Linux (7)
      • JPA (34)
      • Kotlin (2)
      • Flutter (42)
      • Error Note (39)
      • 디자인 패턴 (12)
      • 디지털논리회로 (4)
      • 데이터베이스 시스템 (8)
      • 알고리즘 (7)
      • 운영체제 (3)
      • 이산수학 (3)
      • 인공지능 (1)
      • 자료 구조 (14)
        • 기본 개념 (14)
        • 자료구조 스터디 (0)
      • 💡My project (76)
        • 팩맨 : Java Swing 게임 제작 프로젝트 (6)
        • 네이트톡 : Java 소켓 통신 프로젝트 (4)
        • 포켓옥션 : HikariCP&JDBC CRUD 프.. (3)
        • 이지 부산 : BDIA-Devton 2024 프로.. (20)
        • 그린 유니버시티 : JSP를 사용한 학사관리 프로.. (1)
        • 애드 포커 : 웹 소켓과 Spring을 사용한 카.. (1)
        • 셸위 : 게임 친구 매칭 사이트 (21)
        • 다모아 : 개발자 중개 플랫폼 (20)
      • 📗스터디 (13)
        • CNN : 웹개발 스터디 (10)
        • Node&React로 유튜브 사이트 만들기 (3)
      • 📙독서 및 강연 기록 (36)
        • 강연 (14)
        • 독서 (22)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • [셸위:게임 친구 매칭 사이트] 토스 페이먼츠 API - 결제 기능
        2024년 09월 25일
        • Song hyun
        • 작성자
        • 2024.09.25.:14
        728x90
        반응형

        [셸위:게임 친구 매칭 사이트] 토스 페이먼츠 API - 결제 기능

         

         

         

         이번 프로젝트에서는 토스 페이먼츠, 카카오 페이 총 두 개의 결제 API를 사용해서 현금 결제 기능을 구현해봤다. 이번에는 토스 페이먼츠 결제 API에 대해 설명해보려고 한다.

        https://docs.tosspayments.com/reference#%EA%B2%B0%EC%A0%9C

         

        코어 API | 토스페이먼츠 개발자센터

        토스페이먼츠 API 엔드포인트(Endpoint)와 객체 정보, 파라미터, 요청 및 응답 예제를 살펴보세요.

        docs.tosspayments.com

         

         

         결제 API의 과정은 크게 아래와 같이 나뉜다.

        1. 클라이언트: 결제정보 전송
        2. 서버: 가주문 정보를 DB에 저장 + 토스 API에 결제 요청
        3. 토스 서버: 결제 요청에 대한 response 전달
        4. 서버: DB 상의 가주문 정보-response 대조 후 토스 서버에 결제 승인 요청
        5. 토스 서버: 결제 요청에 대한 response 전달
        6. 서버: 클라이언트 측에 결제에 대한 결과 출력

         

         

        1. 결제창 (JSP)

        -결제창 측에서는 라디오박스, 체크박스를 통해 유저가 조항에 동의했는지, 어떤 가격을 체크했는지를 점검한다. 해당 유효성 검사는 JS 측에서  onclick 함수를 통해 이뤄진다.

        -유효성 검사를 통과한 뒤에는 사용자가 어떤 결제 방식을 선택했는지/얼마를 결제할건지를 fetch를 통해 서버로 post 방식으로 보내게 된다.

         

        (1) html 코드

        				<h4>현재 보유 캐쉬 : ${user.currentCash}</h4>
        				<div class="choose-cash">
        					<h4> 충전할 캐쉬 </h4>
        					<h4> 결제 하실 금액 </h4>
        					<div class="choose-container">
        						<div>
        							1,000 원<input type="radio" name="cash-btn" value="1000">
        						</div> 
        						<div>
        							3,000 원<input type="radio" name="cash-btn" value="3000">
        						</div> 
        						<div>
        							5,000 원<input type="radio" name="cash-btn" value="5000">
        						</div> 
        						<div>
        							10,000 원<input type="radio" name="cash-btn" value="10000">
        						</div> 
        						<div>
        							30,000 원<input type="radio" name="cash-btn" value="30000">
        						</div> 
        					</div>
        				</div>
        				<div class="cash-container">
        					<input type="checkbox" class="check1">[필수] 전체 동의</div>
        					<input type="checkbox" class="check2">상품, 가격, 결제 전 주의사항을 확인하였습니다.</div>
        				</div>
        				<h5>결제 수단 선택</h5>
        				<div class="cash-container">
        					<div class="button-container">
        						<button class = "resultButton-1" onclick="startPayment(this)" value="kakao">카카오페이</button>
        						<button class = "resultButton-2" onclick="startPayment(this)" value="toss">토스페이</button>	
        					</div>
        				</div>

        (2) 자바스크립트

          // 약관 동의 체크박스
            var chk1 = document.querySelector(".check1");
            var chk2 = document.querySelector(".check2");
        
           
            
            
            // 결제 진행 함수
            function startPayment(button) {
                let btnValue = button.value;
                let cashAmount = document.querySelector('input[name="cash-btn"]:checked');
        
                // 유효성 검사 - 약관 동의
                if (!chk1.checked || !chk2.checked) {
                    alert('결제 전 주의사항과 동의 내역을 확인해주세요.');
                    return;
                }
        
                // 유효성 검사 - 결제 금액 선택
                if (!cashAmount) {
                    alert('결제할 금액을 선택해주세요.');
                    return;
                }
        
                // 결제 진행
                if (btnValue == "kakao") {
                    console.log("카카오 결제 요청" + cashAmount.value);
                    requestPaymentToKakao(cashAmount.value);
                } else if (btnValue == "toss") {
                    console.log("토스 결제 요청" + cashAmount.value);
                    requestPaymentToToss(cashAmount.value);
                }
            }

         

         

        2. TossController

        -컨트롤러 측에서는 크게 두 가지 메서드로 결제 API를 운용한다. 첫번째는 결제 요청, 두 번째는 결제 승인이다. 

        (1) 결제 요청에서는 DB에 보안을 위한 가주문 정보를 저장한다. 그리고 토스 서버에 결제 요청 메세지를 보내게 된다.

        (2) 결제 승인 단계에서는 가주문과 주문 내역의 orderId, userId, amount(결제 금액)을 대조하고, 결제 정보가 동일하다면 결제 승인 요청을 토스 서버에 전송하게 된다.

         해당 동작들을 TossService에 보내고, TossRepository-Order.xml에 차례대로 요청하게 된다.

        /**
        	 * 토스 페이 - 결제 전 정보 저장 (정보 무결성)
        	 * @param orderId
        	 * @param paymentKey
        	 * @param amount
        	 * @return
        	 * @throws UnsupportedEncodingException 
        	 * @throws IOException
        	 * @throws InterruptedException
        	 * @throws URISyntaxException
        	 */
        	@ResponseBody
        	@PostMapping("/send-request")
        	public void resultTossPay(@RequestBody Map<String, Object> payload) throws UnsupportedEncodingException, URISyntaxException {
        	    
        		// 받은 정보들 파싱
        		String orderId = (String) payload.get("orderId");
        	    Long amount = Long.valueOf(payload.get("totalAmount").toString());
        	    
        	    System.out.println(orderId);
        	    
        	    User user = (User)httpSession.getAttribute("principal");
        	    int userId = user.getUserId();
        	    // tosspayservice를 통해 toss에 결제 요청 - response 값 반환
        	 	String paymentKey = tossPayService.sendTossPayRequest(orderId, orderId, userId, amount);
        	 	SessionUtils.addAtribute("paymentKey", paymentKey); // paymentKey 생성
        	 	
        	 	return;
         }
            
        	
            /**
             * 토스 페이먼츠 - 결제 요청
             * @return 
             * @throws URISyntaxException 
             * @throws InterruptedException 
             * @throws IOException 
             */
         	@GetMapping("/success")
            public String resultTossPay(@RequestParam("orderId")String orderId,
            							@RequestParam("paymentKey")String paymentKey,
            							@RequestParam("amount") Long amount,
            							Model model) throws URISyntaxException, IOException, InterruptedException {
            	
         		User user = (User)httpSession.getAttribute("principal");
            	Integer userId = user.getUserId();
            	
            	// 가주문 생성
        	 	tossPayService.sendTossPayRequest(paymentKey, orderId, userId, amount);
        	 	SessionUtils.addAtribute("paymentKey", paymentKey); // paymentKey 생성
            	
            	// tosspayservice를 통해 toss에 결제 요청 - response 값 반환
            	String responseEntity = tossPayService.sendTossPayRequestFinish(orderId, paymentKey,amount);
            	String getResult = responseEntity.toString();
            	
            	// 주문 상태 변경
        	    orderService.changeOrderStatus(paymentKey);
            	
            	// 유저 캐쉬 상태 변경
        	    orderService.updateUsersCurrentCash(user.getUserId(),amount);
        	    User updateUser = userService.searchByUserId(user.getUserId());
        	    
        	    httpSession.setAttribute("principal",user);
        	    model.addAttribute("user", updateUser);
            	
            	if(responseEntity.contains("code")) {
            		return "/cash/chargeResult" ;
            	}
            	
            	return "/cash/chargeResult" ;
            }
            
            /**
             * 결제 성공 페이지
             * @param pgToken
             * @return
             */
            // http://localhost:8080/toss-pay/result
         	@GetMapping("/result11")
         	public String resultKakaoPay(@RequestParam("pg_token") String pgToken) {
         		
         		return "../test/main";
         	}

         


        -한 번 해보면 쉬워지는 게 API라고 느끼게 해준 계기였다. 처음에는 정말 어려웠는데, 한번 요청을 주고받는 걸 경험해보고 나니 어떤 식으로 API가 작동하고, 요청을 받아오는 지 알 수 있게 되어 뿌듯했다.

         

        -결제 요청 API 구현에만 어언 일주일이 걸렸는데(그 구조와 원리를 이해하는 데 시간이 많이 걸렸다.) 처음에는 막무가내로 다른 사람들이 어떤 식으로 코드를 작성했는지, 깃허브와 블로그를 찾아봤다. 하지만 각자 사용하는 라이브러리와 그 버전이 다르다보니, 따라 쓴다고 해도 생각처럼 잘 되지 않았다. 결국 내가 스스로 할 수 밖에 없었다. (...)

         

         매일 남아 대안으로 사용할 수 있는 여러 메서드나 클래스를 찾기도 하고, 토스 페이먼츠 API 문서를 여러번 읽거나 다른 API들의 로직 구조를 살펴보기도 하고, 몇날 며칠을 찾아봐도 잘 풀리지 않는 문제는 토스 페이먼츠 개발자 커뮤니티에 묻기도 했다. 그 덕분인지 결국 마지막에는 다른 분들의 도움+내 힘으로 API를 작동시킬 수 있었다. 결제 로직을 공부할 수 있어 뿌듯했던 기능!!

        728x90
        반응형

        '💡My project > 셸위 : 게임 친구 매칭 사이트' 카테고리의 다른 글

        [셸위:게임 친구 매칭 사이트] 카카오 페이 API - 결제 취소 기능  (5) 2024.09.25
        [셸위:게임 친구 매칭 사이트] 카카오 페이 API - 결제 기능  (0) 2024.09.25
        [셸위:게임 친구 매칭 사이트] 최종 정리  (2) 2024.09.25
        [셸위:게임 친구 매칭 사이트] 부일기획 멘토링(9.6)  (0) 2024.09.06
        [셸위:게임 친구 매칭 사이트] 드롭다운 메뉴 구현  (1) 2024.09.04
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바