결제는 되는거 같은데 결과 페이지에서
KakaopayStartResponseVO responseVO = template.postForObject(uri, entity, KakaopayStartResponseVO.class);
이부분에서 오류가 발생합니다.
결제후 결과를 받고싶은데 설정을 어떻게 해야합니까?
콘트롤러
@Controller
@Log4j
@RequestMapping("/pay")
public class KakaopayController {
@Autowired
private KakaoPayService service;
@GetMapping("/prepare")
public String prepare() {
return "pay/prepare";
}
@PostMapping("/prepare")
public String prepare(@ModelAttribute KakaopayStartVO startVO,HttpSession session) throws URISyntaxException {
startVO.setPartner_order_id(UUID.randomUUID().toString());
startVO.setPartner_user_id("hong");
KakaopayStartResponseVO responseVO = service.kakaopay(startVO);
//session에 데이터 추가
session.setAttribute("partnet_order_id", startVO.getPartner_order_id());
session.setAttribute("partnet_user_id", startVO.getPartner_user_id());
session.setAttribute("tid", responseVO.getTid());
log.info("rediredct::::"+responseVO.getNext_redirect_pc_url());
return "redirect:"+responseVO.getNext_redirect_pc_url();
}
//결제 성공시
@GetMapping("/success")
public String success(@RequestParam String pg_token,HttpSession session, Model model) throws URISyntaxException {
log.info("pg_token={"+pg_token+"}");
String partner_order_id = (String)session.getAttribute("partner_order_id");
String partner_user_id = (String)session.getAttribute("partner_user_id");
String tid = (String)session.getAttribute("tid");
KakaoPayFinishVO finishVO = service.approve(partner_order_id, partner_user_id, pg_token, tid);
model.addAttribute("finishVO", finishVO);
return "pay/success";
}
}
서비스
@Service
public class KakopayServiceImpl implements KakaoPayService{
//상단에 CID를 선언해 주고 그 값을 사용
public static final String CID = “TC0ONETIME”;
@Override
public KakaoPayFinishVO approve(String partner_order_id, String partner_user_id, String pg_token, String tid)
throws URISyntaxException {
//1.도구 생성
RestTemplate template = new RestTemplate();
//2.Header 생성
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "KakaoAK 7b9f3bd47c288b3967eb04f5b0f7957a");
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
//3.Body 생성
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("cid", CID);
body.add("partner_order_id", partner_order_id);
body.add("partner_user_id", partner_user_id);
body.add("tid", tid);
body.add("pg_token", pg_token);
//4.Header와 Body를 합성
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(body,headers);
//5.주소 정의
URI uri = new URI("https://kapi.kakao.com/v1/payment/approve");
//6.모든 준비가 완료되었으므로 template을 이용하여 요청을 전송
KakaoPayFinishVO finishVO = template.postForObject(uri, entity, KakaoPayFinishVO.class);
return finishVO;
}
@Override
public KakaopayStartResponseVO kakaopay(KakaopayStartVO startVO) throws URISyntaxException {
RestTemplate template = new RestTemplate();
//Header생성
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "KakaoAK 7b9f3bd47c288b3967eb04f5b0f7957a");
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
//Body생성
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("cid", "TC0ONETIME");
body.add("partner_order_id", startVO.getPartner_order_id());
body.add("partner_user_id", startVO.getPartner_user_id());
body.add("item_name", startVO.getItem_name());
body.add("quantity", String.valueOf(startVO.getQuantity()));
body.add("total_amount", String.valueOf(startVO.getTotal_amount()));
body.add("tax_free_amount", "0");
body.add("approval_url", "http://localhost:8080/pay/success");
body.add("cancel_url", "http://localhost:8080/pay/cancle");
body.add("fail_url", "http://localhost:8080/pay/fail");
//Header와 Body합치기
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(body,headers);
//주소정의
URI uri = new URI("https://kapi.kakao.com/v1/payment/ready");
//template을 이용하여 요청을 전송
KakaopayStartResponseVO responseVO = template.postForObject(uri, entity, KakaopayStartResponseVO.class);
return responseVO;
}
}
/카카오페이 '결제 요청’을 보내기 위한 VO
@Builder @Data @AllArgsConstructor @NoArgsConstructor
public class KakaopayStartVO {
private String partner_order_id; // 가맹점 주문번호 - 시퀀스 번호 생성 후 부여
private String partner_user_id; // 가맹점 회원 id - 회원 이메일로 불러오기
private String item_name;
private int quantity; // 수량 : 1로 설정해놓기
private int total_amount;
}
//최초의 결제요청에 대한 응답을 담을 VO
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public class KakaopayStartResponseVO {
private String tid;
private String next_redirect_app_url;
private String next_redirect_pc_url;
private String created_at;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class KakaoPayFinishVO {
private String aid;
private String tid;
private String cid;
private String sid;
private String partner_order_id;
private String partner_user_id;
private String payment_method_type;
private KakaopayFinishAmountVO amount;
private KakaopayFinishCardInfoVO card_info;
private String item_name;
private String item_code;
private int quantity;
private String created_at;
private String approved_at;
private String payload;
}
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public class KakaopayFinishAmountVO {
private int total;
private int tax_free;
private int vat;
private int point;
private int discount;
}
@Data @NoArgsConstructor @AllArgsConstructor @Builder
public class KakaopayFinishCardInfoVO {
private String purchase_corp;
private String purchase_corp_code;
private String issuer_corp;
private String issuer_corp_code;
private String kakaopay_purchase_corp;
private String kakaopay_purchase_corp_code;
private String kakaopay_issuer_corp;
private String kakaopay_issuer_corp_code;
private String bin;
private String card_type;
private String install_month;
private String approved_id;
private String card_mid;
private String interest_free_install;
private String card_item_code;
}
오류페이내용입니다.
HTTP 상태 500 – 내부 서버 오류
타입 예외 보고
메시지 Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request
설명 서버가, 해당 요청을 충족시키지 못하게 하는 예기치 않은 조건을 맞닥뜨렸습니다.
예외
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
근본 원인 (root cause)
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94)
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79)
org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:724)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:698)
org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:457)
com.study.kakaopy.KakopayServiceImpl.approve(KakopayServiceImpl.java:48)
com.study.kakaopy.KakaopayController.success(KakaopayController.java:60)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:564)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
비고 근본 원인(root cause)의 풀 스택 트레이스를, 서버 로그들에서 확인할 수 있습니다.