반응형
외부 결제 API를 연동하라고 적혀 있어서
사용해본 적 없는 결제 API 중에 토스 결제 API를 써보기로 했다.
1. 토스 개발자센터에서 시크릿키 발급받기
https://developers.tosspayments.com/
토스페이먼츠 개발자센터
토스페이먼츠 결제 연동 문서, API, 키, 테스트 내역, 웹훅 등록 등 개발에 필요한 정보와 기능을 확인해 보세요. 결제 연동에 필요한 모든 개발자 도구를 제공해 드립니다.
developers.tosspayments.com

테스트키를 사용하면 실제 결제는 이뤄지지 않는다.

2.토스 결제 Entity
<java />
@Entity @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public class TossPayment extends BaseEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "payment_id", nullable = false, unique = true) private Long paymentId; @Column(nullable = false, unique = true) private String paymentKey; @Column(nullable = false) private String orderId; @Column(nullable = false) private String orderName; @Column(nullable = false, name="amount") private Long amount; @ManyToOne(cascade = CascadeType.PERSIST) @JoinColumn(name = "customer_id") private Customer customer; }
3. 응답 Response Dto
<java />
@Getter @Setter public class TossConfirmRequestDto { String orderId; Long amount; String paymentKey; }
<java />
/* * Record 클래스 * -Java 14부터 도입 * -필드별 getter가 자동으로 생성됨 * -모든 버변수를 인자로 하는 public 생성자를 자동으로 생성함. */ public record TossResponseDto ( String paymentKey, String orderId, Long amount ) { public static TossResponseDto from(TossPayment tossPayment) { return new TossResponseDto(tossPayment.getPaymentKey(), tossPayment.getOrderId(), tossPayment.getAmount()); } }
4. Controller
<java />
@Controller @RequiredArgsConstructor public class TossController { private final CustomerService customerService; private final TossService tossService; @GetMapping("/pay") public String pay(Principal principal, Model model) { Customer customer = customerService.getCustomerInfo(principal.getName()); model.addAttribute("customer", customer); return "/toss/checkout"; } @GetMapping("/success") public String success(HttpServletRequest request, Model model) { String paymentKey = request.getParameter("paymentKey"); String orderId = request.getParameter("orderId"); String amount = request.getParameter("amount"); model.addAttribute("paymentKey", paymentKey); model.addAttribute("orderId", orderId); model.addAttribute("amount", amount); return "/product/success"; } @GetMapping("/fail") public String fail(HttpServletRequest request, Model model) { String code = request.getParameter("code"); String message = request.getParameter("message"); String orderId = request.getParameter("orderId"); model.addAttribute("code", code); model.addAttribute("message", message); model.addAttribute("orderId", orderId); return "/product/fail"; } @RequestMapping(value = "/confirm") public ResponseEntity<TossResponseDto> confirmPayment(Principal principal, @Valid @RequestBody TossConfirmRequestDto requestDto) throws Exception { Customer customer = customerService.getCustomerInfo(principal.getName()); TossPayment tossPayment = tossService.confirm(requestDto); tossPayment.setAmount(requestDto.getAmount()); tossPayment.setCustomer(customer); tossService.save(tossPayment); return ResponseEntity.ok().body(TossResponseDto.from(tossPayment)); } }
5. 프론트단
getOrderTotal, chkAll
<html />
function getOrderTotal(){ var orderTotal = 0; $("input:checkbox[name=cartChkbox]:checked").each(function() { var cartProductId = $(this).val(); var price = $("#price_" + cartProductId).attr("data-price"); // 가격을 숫자로 처리 var count = $("#count_" + cartProductId).val(); // 수량을 숫자로 처리 orderTotal += price*count; }); $("#orderTotal").html(orderTotal+'원'); } function changeCount(obj){ var count = obj.value; var cartProductId = obj.id.split('_')[1]; var price = $("#price_" + cartProductId).data("price"); var total = count*price; $("#totalPrice_" + cartProductId).html(total+"원"); getOrderTotal(); } function chkAll(){ if($("#checkall").is(":checked")){ $("input:checkbox[name=cartChkbox]").prop("checked",true); }else{ $("input:checkbox[name=cartChkbox]").prop("checked",false); } getOrderTotal(); }
requestPayment
<html />
const clientKey = "test_클라이언트키"; //토스 결제 개발 연동 클라이언트키 const customerKey = generateRandomString(); const secretKey = "test_시크릿키"; const tossPayments = TossPayments(clientKey); const payment = tossPayments.payment({ customerKey }); async function requestPayment() { var nameList = ''; var checkbox = $("input:checkbox[name=cartChkbox]:checked"); checkbox.each(function(i) { var tr = checkbox.parent().parent().eq(i); var td = tr.children(); var name = td.eq(1).find("#productName").text(); nameList += ', ' + name; }); const productName = nameList.substring(1); const totalText = $("#orderTotal").text(); const total = totalText.substring(0, totalText.length -1); const orderId = generateRandomString(); console.log(orderId); await payment.requestPayment({ method: "CARD", // 카드 결제 amount: { currency: "KRW", value: parseInt(total), }, orderId: orderId, // 고유 주분번호 orderName: productName, successUrl: window.location.origin + "/success", // 결제 요청이 성공하면 리다이렉트되는 URL failUrl: window.location.origin + "/fail", // 결제 요청이 실패하면 리다이렉트되는 URL customerEmail: [[${customerEmail}]], customerName: [[${customerName}]], customerMobilePhone: null, // 카드 결제에 필요한 정보 card: { useEscrow: false, flowMode: "DEFAULT", // 통합결제창 여는 옵션 useCardPoint: false, useAppCardOnly: false, }, }); } function generateRandomString() { return window.btoa(Math.random()).slice(0, 20); }
결제 버튼
<html />
<h2 class="text-center"> 총 주문 금액 : <span id="orderTotal" class="text-danger">0원</span> </h2> <div class="text-center"> <button type="button" class="btn btn-primary btn-lg" onclick="requestPayment()">토스로 결제하기</button> </div>
체크박스 클릭 시 주문 금액 바뀜

토스 결제창 띄우기


반응형
'💻 my code archive > 🏷️JAVA & Spring(Boot)' 카테고리의 다른 글
Spring Boot 스프링부트 application.yml 설정값 가져오기 (0) | 2025.02.03 |
---|---|
스프링부트 Spring Boot + JPA 쇼핑몰 상품 목록, 장바구니 기능 구현 (0) | 2025.01.13 |
프로젝트 #1 스프링부트 SpringBoot 3x Swagger 적용법 (1) | 2024.04.20 |
SheetJS 테이블 내용 엑셀 다운로드, 스타일 적용 방법 (0) | 2023.08.18 |
[스프링부트 블로그 만들기] 댓글 기능, 댓글 목록, 삭제까지 구현하기 (0) | 2022.03.25 |