카트는 DB에 테이블을 만들지 않고 세션에 저장.
세션에 cart클래스 객체를 담아 저장할 예정.
새 클래스 생성.
- Cart -
@Data // get set메서드 toString 자동생성
@AllArgsConstructor // 모든 필드변수를 추가한 생성자 자동생성
public class Cart {
private int id; // id
private String name; // 이름
private String price; // 가격
private int quantitiy; // 수량
private String image; // 이미지
}
lombok
을 사용 시 @AllArgsConstructor
를 사용하면 필드변수를 모두 추가한 생성자를 만든 것과 동일함.
기본생성자는 @NoArgsConstructor
사용.
새 컨트롤러 클래스 생성
- CartController -
@Controller
@RequestMapping("/cart")
public class CartController {
@Autowired
private ProductRepository productRepo; // 상품을 카트에 담을것이므로 필요
/**
* 상품의 id를 입력받아 세션에 카트리스트를 저장
* @param id
* @param session
* @param model
* @return
* */
@GetMapping("/add/{id}") // 상품을 DB에서 가져와 세션의 카트에 담는 과정
@SuppressWarnings("unchecked") // 오브젝트 -> hashmap형변환 시 발생하는 warnning을 제거하기위해 추가
public String add(@PathVariable int id, HttpSession session, Model model) {
// 0. id로 상품의 정보를 DB에서 가져와 product객체에 저장
Product product = productRepo.getById(id);
// 1. 세션에 이미 만들어진 카트(장바구니)가 없을 경우 세션에 가져온 제품을 저장
if(session.getAttribute("cart") == null) { //
HashMap<Integer, Cart> cart = new HashMap<>(); // map을 통해 <id, 카트> 로 리스트를 만듦
cart.put(id, new Cart(id, product.getName(), product.getPrice(), 1, product.getImage())); // 새로저장하는 것이므로 무조건 1번으로 저장
session.setAttribute("cart", cart); // 세션에 카트객체를 새로 만들어 저장
} else { // 2. 세션에 이미 만들어진 카트가 있을 경우 ( (1)그 상품이 담겨있을 경우 (2)없을경우 )
// 세션에 저장될 땐 무조건 오브젝트 타입으로 저장되므로 hashmap타입으로 저장하려면 형변환을 거쳐야 함
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
if(cart.containsKey(id)) { // 2 (1).같은 상품id가 이미 카트에 있을 경우
int qty = cart.get(id).getQuantitiy(); // 카드객체를 불러와 그 객체의 수량을 get으로 검색해 해당상품이 현재 몇개 담겨있는지 체크
cart.put(id, new Cart(id, product.getName(), product.getPrice(), ++qty, product.getImage())); // 현재 카트의 수량에 +1 해준 후 업데이트
} else { // 2 (2). 같은 상품id가 이미 카트에 없을 경우
cart.put(id, new Cart(id, product.getName(), product.getPrice(), 1, product.getImage()));
session.setAttribute("cart", cart);
// 2 (1)은 있는 카트에 담긴 상품객체를 업데이트하므로 세션에 저장할필요없음, 2(2)의 경우 업데이트가 아닌 신규저장이므로 세션에 저장필요
}
}
return "";
}
}
세션에 카트를 저장하는 기능을 추가.
id를 통해 상품의 정보를 찾아 세션에 저장하므로 매개변수로 id, HttpSession이 필요.
모든 페이지에서 카트를 보여주기 위해 Common에 만들어줌.
- Common -
// 모든 컨트롤러에 적용(모든 페이지에 적용됨)
@ControllerAdvice
public class Common {
@Autowired
private PageRepository pageRepo;
@Autowired
private CategoryRepository categoryRepo;
// 모델에 추가
@ModelAttribute
public void sharedData(Model model, HttpSession session) {
// cpages에 모든 페이지들을 담아서 순서대로 전달
List<Page> cpages = pageRepo.findAllByOrderBySortingAsc();
List<Category> categories = categoryRepo.findAll();
// 현재 장바구니 상태 (없을때 false)
boolean cartActive = false;
if (session.getAttribute("cart") != null) { // 세션에 장바구니가 있을 경우
@SuppressWarnings("unchecked")
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
int size = 0; // 장바구니 상품 갯수
int total = 0; // 총 가격
for(Cart item : cart.values()) { // 장바구니 cart객체들을 반복하여 상품 갯수와 총 가격 계산
size += item.getQuantitiy();
total += item.getQuantitiy() * Integer.parseInt(item.getPrice());
}
model.addAttribute("csize", size); // view에 전달
model.addAttribute("ctotal", total); // view에 전달
cartActive = true; // 장바구니에 상품 담겨있음(false -> true)으로 변경
}
model.addAttribute("cpages", cpages);
model.addAttribute("ccategories", categories);
model.addAttribute("cartActive", cartActive); // 세션에 장바구니가 없으면 false 있으면 true
}
}
크게 cart에 상품이 있을때와 없을때로 나뉨.
상품이 있을 경우 cart객체를 반복문을 통해 상품갯수와 상품총액을 계산한다.
Cart객체를 만들때 price를 String 으로 선언하였으므로 총액계산 시 Integer형으로 형변환 필요.
view에 추가할 html파일 생성
- cart_partical.html -
<div class="bg-dark text-white p-3 mt-3" th:fragment="cart_partial">
<div class="cart cartActive" th:if="${cartActive}">
<p>장바구니에 <span th:text="${csize}"></span> 개 상품이 있습니다.</p>
<p>총 가격은 <span th:text="${ctotal}"></span> 원 입니다.</p>
<p>
<a href="/cart/view" class="btn btn-success">카트 보기</a>
<a href="/cart/clear" class="btn btn-danger float-right">비우기</a>
</p>
</div>
<div class="cart cartInactive" th:unless="${cartActive}">
<p>장바구니가 없습니다.</p>
</div>
</div>
view의 카테고리탭에 추가.
${cartActive}
가 true이면 담긴 상품의 총액${ctotal}
과 총 갯수${csize}
를 출력.
- categories -
<div class="col-3" th:fragment="categories">
<h3 class="display-4">Categories</h3>
<ul class="list-group">
<li class="list-group-item">
<a class="nav-link" th:href="@{/category/all}">All Products</a>
</li>
<li class="list-group-item" th:each="category : ${ccategories}">
<a class="nav-link" th:href="@{'/category/' + ${category.slug}}" th:text="${category.name}"></a>
</li>
</ul>
<div th:replace="/fragments/cart_partical"></div>
</div>
th:replace="/fragments/cart_partial"
로 위에서 만든 페이지를 추가하여 모든 페이지에서 사용할 수 있도록 해줌.
현재는 카트를 추가하지 않았으므로 장바구니가 없다고 출력되는게 정상.
확인이 완료되면 다시 컨트롤러로 돌아가 빠뜨린 내용을 보충.
- CartController -
@GetMapping("/add/{id}") // 상품을 DB에서 가져와 세션의 카트에 담는 과정
@SuppressWarnings("unchecked") // 오브젝트 -> hashmap형변환 시 발생하는 warnning을 제거하기위해 추가
public String add(@PathVariable int id, HttpSession session, Model model) {
// 0. id로 상품의 정보를 DB에서 가져와 product객체에 저장
Product product = productRepo.getById(id);
// 1. 세션에 이미 만들어진 카트(장바구니)가 없을 경우 세션에 가져온 제품을 저장
if(session.getAttribute("cart") == null) { //
HashMap<Integer, Cart> cart = new HashMap<>(); // map을 통해 <id, 카트> 로 리스트를 만듦
cart.put(id, new Cart(id, product.getName(), product.getPrice(), 1, product.getImage())); // 새로저장하는 것이므로 무조건 1번으로 저장
session.setAttribute("cart", cart); // 세션에 카트객체를 새로 만들어 저장
} else { // 2. 세션에 이미 만들어진 카트가 있을 경우 ( (1)그 상품이 담겨있을 경우 (2)없을경우 )
// 세션에 저장될 땐 무조건 오브젝트 타입으로 저장되므로 hashmap타입으로 저장하려면 형변환을 거쳐야 함
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
if(cart.containsKey(id)) { // 2 (1).같은 상품id가 이미 카트에 있을 경우
int qty = cart.get(id).getQuantitiy(); // 카드객체를 불러와 그 객체의 수량을 get으로 검색해 해당상품이 현재 몇개 담겨있는지 체크
cart.put(id, new Cart(id, product.getName(), product.getPrice(), ++qty, product.getImage())); // 현재 카트의 수량에 +1 해준 후 업데이트
} else { // 2 (2). 같은 상품id가 이미 카트에 없을 경우
cart.put(id, new Cart(id, product.getName(), product.getPrice(), 1, product.getImage()));
session.setAttribute("cart", cart);
// 2 (1)은 있는 카트에 담긴 상품객체를 업데이트하므로 세션에 저장할필요없음, 2(2)의 경우 업데이트가 아닌 신규저장이므로 세션에 저장필요
}
}
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
int size = 0; // 장바구니 상품 갯수
int total = 0; // 총 가격
for(Cart item : cart.values()) { // 장바구니 cart객체들을 반복하여 상품 갯수와 총 가격 계산
size += item.getQuantitiy();
total += item.getQuantitiy() * Integer.parseInt(item.getPrice());
}
model.addAttribute("size", size); // view에 전달
model.addAttribute("total", total); // view에 전달
return "cart_view";
}
상품갯수와 총액을 계산하는 코드를 추가.
계산코드는 Common에 작성한 것과 거의 같음.
- products.html -
<div style="position: relative">
<p>
<a class="btn btn-primary addToCart" th:attr="data-id=${product.id}" th:href="@{'/cart/add/' + ${product.id}}">장바구니 추가</a>
</p>
<div class="btn btn-sm btn-success hide productAdded">추가됨!</div>
</div>
...
<script>
// 장바구니추가버튼을 눌렀을 때 이벤트
$('a.addToCart').click(function (e) {
e.preventDefault(); // a태그의 주소이동을 중단
alert('장바구니 누름');
});
</script>
상품가격 아래 장바구니 추가버튼, 추가됨! 버튼을 만듦.
- style.css -
div.productAdded {
position: absolute;
bottom: 5px;
left: 10em;
}
.hide {
display: none;
}
추가됨 버튼을 장바구니 추가 버튼 옆으로 옮김.
.hide(추가됨버튼)
은 평소에 안보이도록 display: none
처리.
추가 버튼을 눌렀을 때 alert창이 뜨는지까지 확인.
- cart_view.html -
<p>장바구니에 <span th:text="${size}"></span> 개 상품이 있습니다.</p>
<p>총 가격은 <span th:text="${total}"></span> 원 입니다.</p>
<p>
<a href="/cart/view" class="btn btn-success">카트 보기</a>
<a href="/cart/clear" class="btn btn-danger float-right">비우기</a>
</p>
- products.html -
<script>
// 장바구니추가버튼을 눌렀을 때 이벤트
$('a.addToCart').click(function (e) {
e.preventDefault(); // a태그의 주소이동을 중단
// alert('장바구니 누름');
let $this = $(this);
console.log($this);
});
</script>
script를 추가하여 $this를 확인.
- products.html -
// 장바구니추가버튼을 눌렀을 때 이벤트
$('a.addToCart').click(function (e) {
e.preventDefault(); // a태그의 주소이동을 중단
// alert('장바구니 누름');
let $this = $(this);
let id = $this.attr('data-id'); // data-id속성에 담긴 product.id(위의 html코드 확인)를 가져와 id에 저장
let url = '/cart/add/' + id;
// Ajax GET주소는 url, 보내는 데이터{}는 없음, 결과데이텨는 data
$.get(url, {}, function (data) {
// console.log(data);
$('div.cart').html(data); // 장바구니 화면을 덮어쓰기
}).done(function () {
$this.parent().parent().find('div.productAdded').fadeIn(); // 시간을 들여 천천히 나타남
setTimeout(function () {
$this.parent().parent().find('div.productAdded').fadeOut(); // 1초에 걸쳐 사라짐
}, 1000);
});
});
장바구니 추가를 누르면 Ajax를 통해 전체 화면은 유지하되 cart_view.html이 부분적으로 덮어씌워짐.
fadeIn
과 fadeOut
은 장바구니 클릭 시 추가됨 버튼이 천천히 나타났다 사라지도록 한 것.
- cart.html -
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="/fragments/head :: head-front"> </head>
<body>
<nav th:replace="/fragments/nav :: nav-front"></nav>
<main role="main" class="container-fluid mt-5">
<div class="row">
<div th:replace="/fragments/categories :: categories"></div>
<div class="col"></div>
<div class="col-7">
<h2 class="display-4">장바구니</h2>
<table class="table">
<tr>
<th>상품</th>
<th>이미지</th>
<th>수량</th>
<th>가격</th>
<th>합계</th>
</tr>
<!-- item은 해시맵 cart의 한 개의 item임. 이때 key는 상품id, value는 cart객체이므로 item.value.name 상품이름임. -->
<tr th:each="item : ${cart}">
<td th:text="${item.value.name}"></td>
<td>
<img th:src="@{'/media/'+${item.value.image}}" style="height: 2em" />
</td>
<td>
<span th:text="${item.value.quantity}"></span>
<a th:href="@{'/cart/add/'+${item.value.id}}+'?cartPage=true'" class="btn btn-success btn-sm">+</a>
<a th:href="@{'/cart/subtract/'+${item.value.id}}" class="btn btn-primary btn-sm">-</a>
<a th:href="@{'/cart/remove/'+${item.value.id}}" class="btn btn-danger btn-sm">삭제</a>
</td>
<td th:text="${item.value.price} + ' 원'"></td>
<td th:with="totalPrice = ${item.value.price}*${item.value.quantity}" th:text="${totalPrice} + ' 원'"></td>
</tr>
<tr>
<th colspan="5" class="text-right pr-5" th:text="'총 합계 : ' + ${ctotal} + ' 원'"></th>
</tr>
<tr>
<td>
<a href="/cart/clear" class="btn btn-danger">비우기</a>
</td>
<td colspan="4" class="text-right">
<a href="#" class="btn btn-success checkout">체크아웃</a>
</td>
</tr>
</table>
</div>
<div class="col"></div>
</div>
</main>
<footer th:replace="/fragments/footer :: footer"></footer>
</body>
</html>
- CartController -
@GetMapping("/view")
public String view(HttpSession session, Model model) {
if(session.getAttribute("cart") == null) {
return "redirect:/"; //장바구니가 없을경우 홈페이지로 이동
}
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
model.addAttribute("cart", cart); // 장바구니가 있을경우 세션에서 가져와 cart객체에 담은 후 model을 통해 보내줌
model.addAttribute("noCartView", true); // 카테고리아래 카트뷰는 출력하지 않음
return "cart"; // cart.html 페이지로 리턴
}
@SuppressWarnings("unchecked")
는 클래스 가장 상단(Controller어노테이션과 같은 위치)에 올려버리면 메서드마다 추가하지 않아도 모두 적용됨. 에러 방지를 위해 추가.
- cart_partical.html -
<div class="bg-dark text-white p-3 mt-3" th:unless="${noCartView}" th:fragment="cart_partial">
${noCartView}
이 null일 경우에만 cart_partical를 출력
=> 장바구니 페이지에서는 cart_view가 보이지 않도록 처리.
- cart.html -
<th>
<td>
<a href="/cart/clear" class="btn btn-danger">비우기</a>
</td>
<td>
<a href="#" class="btn btn-success checkout">체크아웃</a>
</td>
</th>
닫는 table태그 바로 윗 행에 추가.
- CartController -
/**
* 상품의 id를 입력받아 세션에 카트리스트를 저장
* @param id
* @param session
* @param model
* @return
* */
@GetMapping("/add/{id}") // 상품을 DB에서 가져와 세션의 카트에 담는 과정
public String add(@PathVariable int id, HttpSession session, Model model,
@RequestParam(required = false) String cartPage) {
// 0. id로 상품의 정보를 DB에서 가져와 product객체에 저장
Product product = productRepo.getById(id);
// 1. 세션에 이미 만들어진 카트(장바구니)가 없을 경우 세션에 가져온 제품을 저장
if(session.getAttribute("cart") == null) { //
HashMap<Integer, Cart> cart = new HashMap<>(); // map을 통해 <id, 카트> 로 리스트를 만듦
cart.put(id, new Cart(id, product.getName(), product.getPrice(), 1, product.getImage())); // 새로저장하는 것이므로 무조건 1번으로 저장
session.setAttribute("cart", cart); // 세션에 카트객체를 새로 만들어 저장
} else { // 2. 세션에 이미 만들어진 카트가 있을 경우 ( (1)그 상품이 담겨있을 경우 (2)없을경우 )
// 세션에 저장될 땐 무조건 오브젝트 타입으로 저장되므로 hashmap타입으로 저장하려면 형변환을 거쳐야 함
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
if(cart.containsKey(id)) { // 2 (1).같은 상품id가 이미 카트에 있을 경우
int qty = cart.get(id).getQuantity(); // 카드객체를 불러와 그 객체의 수량을 get으로 검색해 해당상품이 현재 몇개 담겨있는지 체크
cart.put(id, new Cart(id, product.getName(), product.getPrice(), ++qty, product.getImage())); // 현재 카트의 수량에 +1 해준 후 업데이트
} else { // 2 (2). 같은 상품id가 이미 카트에 없을 경우
cart.put(id, new Cart(id, product.getName(), product.getPrice(), 1, product.getImage()));
session.setAttribute("cart", cart);
// 2 (1)은 있는 카트에 담긴 상품객체를 업데이트하므로 세션에 저장할필요없음, 2(2)의 경우 업데이트가 아닌 신규저장이므로 세션에 저장필요
}
}
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
int size = 0; // 장바구니 상품 갯수
int total = 0; // 총 가격
for(Cart item : cart.values()) { // 장바구니 cart객체들을 반복하여 상품 갯수와 총 가격 계산
size += item.getQuantity();
total += item.getQuantity() * Integer.parseInt(item.getPrice());
}
model.addAttribute("size", size); // view에 전달
model.addAttribute("total", total); // view에 전달
if(cartPage != null) { // cart.html 페이지에서 (+)버튼을 눌렀을 때 다시 카트페이지로 돌아감
return "redirect:/cart/view";
}
return "cart_view"; // cart_view.html에 size total을 넣어서 리턴
}
@RequestParam(required = false)
을 추가. 없어도 상관없으나 cartPage
파라메터에 값이 있으면 redirect:/cart/view
로 view페이지로 리턴하도록함.
=> view페이지로 리턴 시 +된 수량값이 계산되어 최종적으로 cart.html페이지로 이동하게 됨.
즉 눈으로 봤을때 카트페이지에서 +버튼을 누르면 같은 페이에 +된 값만 계산되어 갱신된것처럼 보임.
+버튼을 누르면 화면 그대로 수량, 가격, 총 금액만 갱신됨.
- CartController -
@GetMapping("/subtract/{id}")
public String add(@PathVariable int id, HttpSession session, Model model) {
// 세션에서 카트 호출해오기
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
// cart에서 현재 선택한 상품(id) 의 수량(getQuantity)을 가져옴
int qty = cart.get(id).getQuantity();
if(qty == 1) { // 상품이 1개일때 -1 -> cart에서 상품제거
cart.remove(id); // key값으로 해당 상품을 cart에서 제거
if(cart.size() == 0) {
session.removeAttribute("cart"); // 카트에 상품이 하나도 없으면 session에 있는 cart객체를 제거
}
} else {
cart.get(id).setQuantity(--qty); // 수량만 -1
}
return "redirect:/cart/view";
}
(-)버튼을 눌렀을 때 0개인 경우 cart의 해당 상품을 제거
cart에 있는 전체상품이 0개인 경우 세션의 cart객체를 제거
- CartController -
@GetMapping("/subtract/{id}")
public String subtract(@PathVariable int id, HttpSession session, Model model, HttpServletRequest httpServletRequest) {
// 세션에서 카트 호출해오기
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
// cart에서 현재 선택한 상품(id) 의 수량(getQuantity)을 가져옴
int qty = cart.get(id).getQuantity();
if(qty == 1) { // 상품이 1개일때 -1 -> cart에서 상품제거
cart.remove(id); // key값으로 해당 상품을 cart에서 제거
if(cart.size() == 0) {
session.removeAttribute("cart"); // 카트에 상품이 하나도 없으면 session에 있는 cart객체를 제거
}
} else {
cart.get(id).setQuantity(--qty); // 수량만 -1
}
String refererLink = httpServletRequest.getHeader("Referer"); // 요청된 이전 주소의 정보가 들어있음
return "redirect:" + refererLink;
}
HttpServletRequest를 통해 요청된 이전페이지의 정보를 사용했을때.
동작의 결과는 동일하나, 이렇게 작성할 경우 상대경로로 인해 이전페이지로 돌아가므로 카트페이지가 아닌 다른페이지에서도 사용할 수 있다.
- CartController -
@GetMapping("/remove/{id}")
public String remove(@PathVariable int id, HttpSession session, Model model, HttpServletRequest httpServletRequest) {
// 세션에서 카트 호출해오기
HashMap<Integer, Cart> cart = (HashMap<Integer, Cart>) session.getAttribute("cart");
cart.remove(id); // id로 삭제
if(cart.size() == 0) {
session.removeAttribute("cart"); // 카트에 상품이 하나도 없으면 session에 있는 cart객체를 제거
}
String refererLink = httpServletRequest.getHeader("Referer"); // 요청된 이전 주소의 정보가 들어있음
return "redirect:" + refererLink; // 다시 이전페이지로 이동
}
수량에 관계없이 삭제.
카트에 상품이 하나도 없을 경우 세션에서 cart객체를 삭제하는 부분은 동일함.
- CartController -
@GetMapping("/clear") // 카트 전체 삭제
public String clear(HttpSession session, HttpServletRequest httpServletRequest) {
session.removeAttribute("cart"); // 세션에 저장된 cart객체를 제거
String refererLink = httpServletRequest.getHeader("Referer"); // 요청된 이전 주소의 정보가 들어있음
return "redirect:" + refererLink; // 다시 이전페이지로 이동
}
아임포트 사용.
아임포트 사용법
- Cart.html -
footer아래에 추가
<script type="text/javascript" src="https://cdn.iamport.kr/js/iamport.payment-1.2.0.js"></script>
<script>
$(function () {
$('a.checkout').click(function (e) {
e.preventDefault();
$.get('/cart/clear', {}, function () {});
//$("form#paypalform").submit();
kakaoPay();
});
});
function kakaoPay() {
var IMP = window.IMP; // 생략 가능
IMP.init('가맹점번호'); // 예: imp00000000
IMP.request_pay(
{
pg: 'kakaopay',
//pay_method : 'card', //생략 가능
merchant_uid: 'order_no_0001', // 상점에서 관리하는 주문 번호
name: '주문명:결제테스트',
amount: 10,
buyer_email: 'iamport@siot.do',
buyer_name: '구매자이름',
buyer_tel: '010-1234-5678',
buyer_addr: '서울특별시 강남구 삼성동',
buyer_postcode: '123-456',
},
function (rsp) {
if (rsp.success) {
let msg = '결제가 완료되었습니다.';
msg += '고유ID : ' + rsp.imp_uid;
msg += '상점 거래ID : ' + rsp.merchant_uid;
msg += '결제 금액 : ' + rsp.paid_amount;
msg += '카드 승인번호 : ' + rsp.apply_num;
if (!alert(msg)) location.reload(); // msg창의 확인을 누르면 reload(새로고침)
} else {
let msg = '결제에 실패하였습니다.';
msg += '에러내용 : ' + rsp.error_msg;
alert(msg);
}
}
);
}
</script>
script의 가맹점번호
는 아임포트 홈페이지에서 발급받은 가맹점 식별코드를 사용(테스트코드x, 예- imp00000000)
관리자 콘솔 에서 로그인
테스트모드 on, 카카오페이 선택
홈페이지의 가맹점코드는 발급받은 번호가 아닌 테스트코드를 기입.
여기서 발급받은 번호를 넣고 결제진행 시 cid를 찾을 수 없다는 오류가 나며 결제가 안됨.
결제성공시 팝업창
아임포트 홈페이지에서 결제내역을 확인가능.
검색버튼 클릭 시 페이지 아래로 결제내역이 나타남.