이번 포스팅에는 아이엠포트 테스트 결제 후 결제정보 저장. 화면이동, 결제 리스트 확인, 결제 취소(환불)를 다루겠습니다.
저번 아이엠포트 활용기 1과 같이 봐주시면 좋을 것 같아요 !
https://cobi-98.tistory.com/20
주문, 결제 정보 저장
@RequestMapping(value ="complete", method = RequestMethod.POST)
@ResponseBody
public int paymentComplete(String imp_uid, String merchant_uid,String totalPrice,HttpSession session
,@RequestBody OrderDTO orderDTO) throws Exception {
String token = payService.getToken();
// 결제 완료된 금액
String amount = payService.paymentInfo(orderDTO.getImp_uid(), token);
int res = 1;
if (orderDTO.getTotalPrice() != Long.parseLong(amount)) {
res = 0;
// 결제 취소
payService.payMentCancle(token, orderDTO.getImp_uid(), amount,"결제 금액 오류");
return res;
}
orderService.insert_pay(orderDTO);
return res;
}
payService.getToken - 아임포트 api 키와 secret 키로 토큰을 생성
payService.paymentInfo - 토큰을 활용해 결제 정보를 가져옴
토큰을 생성함으로써 결제 완료된 주문정보를 가져와 환불과 결제, 취소를 진행할 수 있었습니다.
payService.payMentCancle - 결제 완료된 금액과 실제 계산되어야 할 금액이 다를 경우 결제 취소
프론트(서버)에서 html을 조정할 경우 결제를 취소하게 만들었고,
백(String)에서도 결제 금액이 다르면 결제가 안되도록 구성한 모습입니다.
insert_pay - 넘어오는 데이터 정보들을 db로 저장 (주문 정보 저장)
으로 구성하였습니다.
순차적으로 sysout을 활용하여 토큰이 제대로 생성되는지 확인해보시고 토큰으로 결제 정보를 가져오는 방법을 활용하시는 게 좋을 것 같습니다.
그렇게 된다면 결제완료된 금액(amount)과 주문자정보(금액)를 비교하실 수 있습니다.
payService.java
@Service
public class PayService {
//---------------------환불, 결제 토큰생성
@Value("impKey")
private String impKey;
@Value("impSecretKey")
private String impSecret;
public String getToken() throws Exception {
HttpsURLConnection conn = null;
URL url = new URL("https://api.iamport.kr/users/getToken");
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
JsonObject json = new JsonObject();
json.addProperty("imp_key", impKey);
json.addProperty("imp_secret", impSecret);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
bw.write(json.toString());
bw.flush();
bw.close();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
Gson gson = new Gson();
String response = gson.fromJson(br.readLine(), Map.class).get("response").toString();
String token = gson.fromJson(response, Map.class).get("access_token").toString();
br.close();
conn.disconnect();
return token;
}
//결제 정보 불러오기
public String paymentInfo(String imp_uid, String access_token) throws IOException, ParseException {
HttpsURLConnection conn = null;
URL url = new URL("https://api.iamport.kr/payments/" + imp_uid);
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", access_token);
conn.setDoOutput(true);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
JSONParser parser = new JSONParser();
JSONObject p = (JSONObject) parser.parse(br.readLine());
String response = p.get("response").toString();
p = (JSONObject) parser.parse(response);
String amount = p.get("amount").toString();
return amount;
}
}
결제 후 화면이동
function createPayInfo(uid) {
// 결제정보 생성 및 테이블 저장 후 결제완료 페이지로 이동
$.ajax({
type: 'get',
url: '/order/pay_info',
data: {
'imp_uid': uid,
},
success: function(data) {
swal('결제 성공 !',"결제완료 페이지로 이동합니다.","success").then(function(){
// 결제완료 페이지로 이동
location.replace('/order/complete?payNum='+data);
})
},
error: function() {
swal('결제정보 저장 통신 실패');
}
});
}
Controller (order/pay_info)
@RequestMapping(value = "pay_info", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Long> payInfoPOST(Model model,HttpServletRequest request, HttpServletResponse response,
@RequestParam String imp_uid,HttpSession session) throws Exception {
IamportResponse<Payment> result = client.paymentByImpUid(imp_uid);
PayDTO payDTO = new PayDTO();
payDTO.setNum((Long) session.getAttribute("saveNum"));
payDTO.setOrderNum(Long.parseLong(result.getResponse().getMerchantUid()));
payDTO.setPayMethod(result.getResponse().getPayMethod());
payDTO.setPayName(result.getResponse().getName());
payDTO.setPayAmount(result.getResponse().getAmount().longValue());
orderService.insert_payinfo(payDTO);
payDTO = orderService.getLastPay(payDTO);
model.addAttribute("payDTO", payDTO);
return new ResponseEntity<Long>(payDTO.getPayNum(), HttpStatus.OK);
}
orderService.insert_payinfo
imp_uid 정보로 아이엠포트의 결제 정보를 가져올 수 있었습니다.그것으로 결제 정보 payDTO를 생성하였습니다.
payDTO와 orderDTO의 차이!
저는 결제 전에 결제로 바로 넘어가는 테이블이 있으면 안 된다고 생각하였고 주문정보를 만들고 나서 결제가 정말 이루어지면 그 정보를 담고 있는 결제정보 테이블이 있어야 한다고 생각했습니다. 그렇기에 orderDTO는 장바구니와 같은 개념을 가지고 있고, payDTO는 결제한 테이블로 구성했습니다.
- orderDTO는 주문 정보 테이블입니다.
- payDTO는 결제 정보 테이블입니다.
orderService.getLastPay - 방금 결제된 주문정보 가져오기 화면을 구성하기 위해
결제 리스트 확인
결제 취소(환불) (관리자)
payService.java
public void payMentCancle(String access_token, String imp_uid, String amount,String reason) throws IOException, ParseException {
System.out.println("imp_uid = " + imp_uid);
HttpsURLConnection conn = null;
URL url = new URL("https://api.iamport.kr/payments/cancel");
conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Authorization", access_token);
conn.setDoOutput(true);
JsonObject json = new JsonObject();
json.addProperty("reason", reason);
json.addProperty("imp_uid", imp_uid);
json.addProperty("amount", amount);
json.addProperty("checksum", amount);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
bw.write(json.toString());
bw.flush();
bw.close();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
}
adminService
public int orderCancle(OrderDTO orderList) throws Exception {
if(!orderList.getImp_uid().equals("")) {
String token = payService.getToken();
Long price = orderList.getTotalPrice();
Long refundPrice = price ;
payService.payMentCancle(token, orderList.getImp_uid(), refundPrice+"", "환불");
}
return adminDAO.orderCancle((orderList.getOrderNum()));
}
impUid값이 있다면 주문을 취소하는 구조입니다.
"환불" 같은 경우는 임의로 넣은 값이고 select 함수를 사용해 환불 사유를 선택하는 모달을 사용해서 넘기면 더 좋을 것 같습니다.
그러고 나서 controller에서 저장된 db까지 차례로 삭제하면 완벽하게 환불이 된 것과 같이 구성할 수 있었습니다.피드백, 리팩터링 할 부분이나 더 궁금한 사항을 남겨주시면 감사할 것 같습니다.
해당 프로젝트는 깃허브에서 확인하실 수 있습니다!
'Project > 국비프로젝트' 카테고리의 다른 글
[Java Spring] 결제 시스템 (Iamport api) 활용기 1 - 자격증 공부를 위한 사이트 자바스 개발 회고록 (4) | 2023.01.04 |
---|