웹 프로그래밍/아임포트 연동

Spring boot- 아임포트 카카오 정기결제 스케줄 예약(1)

bysnow 2021. 7. 2. 01:33
728x90
반응형
SMALL

 

 

 

우선 다음은 나름대로 생각했던 프로젝트 내에서 아임포트 API를 사용하여 정기결제를 구현하는 과정이다.

 

1) 사용자는 정기구독을 원하는 상품을 선택하여 결제창까지 도달한다.

 

2) 주문정보를 확인한 사용자는 정기결제 버튼을 클릭한다.

 

3) 버튼을 클릭하면 카카오 정기결제 페이지가 나타나고, 사용자는 QR코드 혹은 전화번호 인증을 통해 정기결제 정보를 등록한다.

 

4) 정기결제 등록 시 첫 결제가 이루어지며, 결제와  정기결제 정보 저장이 성공하면 관리자가 정한 만큼의 시간이 지날 때 마다 자동으로 결제가 이루어진다.

 

 

위와 같은 흐름으로 서비스를 구현하였다.

 

 

 

 

지난 포스팅에서 엑세스 토큰을 발급받는 과정에 대해 작성했다. 아임포트 서버로 getToken 요청을 올바르게 보내면 다음과 같은 형태의 응답을 받을 수 있다.

{
  "code": 0,
  "message": "string",
  "response": {
    "access_token": "string",
    "expired_at": 0,
    "now": 0
  }
}

 

 

위의 응답에서 우리가 필요한 부분은 오직 "string"에 해당하는 토큰 부분이다. 따라서 위의 문자열을 잘라 원하는 부분을 얻어내야 한다. 

 

다음 코드는 서비스를 구현하던 도중 거쳐야 했던 과정의 일부이다.

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.google.gson.Gson;
import com.kosta.KOSTA_3_final.model.subscribe.GetTokenVO;

import lombok.Setter;

@Service
public class RequestSubPayment {

	@Setter(onMethod_ = @Autowired)
	private ImportPay pay;

	public String requestSubPay() {

		String token = pay.getToken();
		Gson str = new Gson();
		token = token.substring(token.indexOf("response") + 10);
		token = token.substring(0, token.length() - 1);

		GetTokenVO vo = str.fromJson(token, GetTokenVO.class);

		String access_token = vo.getAccess_token();
		System.out.println(access_token);

		RestTemplate restTemplate = new RestTemplate();

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setBearerAuth(access_token);

		Map<String, Object> map = new HashMap<>();
		map.put("customer_uid", "24");
		map.put("merchant_uid", "162443471100");
		map.put("amount", "10000");
		map.put("name", "test05");

		Gson var = new Gson();
		String json = var.toJson(map);
		System.out.println(json);
		HttpEntity<String> entity = new HttpEntity<>(json, headers);
		
		return restTemplate.postForObject("https://api.iamport.kr/subscribe/payments/again", entity, String.class);

	}

}

 

 

@Setter를 통해 주입한 ImportPay 객체를 통해 ImportPay 클래스에서 정의한 getToken()메소드를 호출하고, 이를 통해아임포트 서버로부터 json형태의 응답을 받는다. 위의 GetTokenVO는 받은 응답에서 response 키에 해당하는 값인 access_token, now, expired_at의 값을 담는 VO이다. 

import lombok.Data;

@Data
public class GetTokenVO {
	private String access_token;
	private long now;
	private long expired_at;
	
	
	
}

 

 

우선, json 형태의 token 문자열을 자른 후, gson을 활용하여 json형태의 문자열을 GetToken의 형태로 저장한다. 그 후 GetTokenVO의 getter를 통해 우리에게 필요한 access_token만을 구한다. 그 후엔 payment/again API로 보내는 요청의 헤더에 방금 구한 access_token의 값을 포함한 후, body 부분에 API에서 요구하는 값들을 담아 전송한다.

 

위의 요청은 결제일을 예약하는 정기결제라기보다는 이미 등록된 사용자에게 한 번의 재결제 요청을 보내는 과정이다. 위의 요청을 수행하기 위해서는 우선 정기결제를 위해 필요한 빌링키가 발급된 상태여야 한다. 

궁극적인 목표는 알아서 정해진 기간마다 결제 요청을 보내는 서비스이므로 마저 구현하러 가보자.

 

 

 

 

<script>
	function kakaopay(){
		var IMP = window.IMP; // 생략가능
		IMP.init('imp41751598'); 
		IMP.request_pay({
			pay_method : 'card', // 결제창 호출단계에서의 pay_method는 아무런 역할을 하지 못하며, 구매자가 카카오페이 앱 내에서 신용카드 vs 카카오머니 중 실제 선택한 값으로 추후 정정됩니다.
			merchant_uid : new Date().getTime(),
			name : 'test05',
			amount : 2000, 
			customer_uid :customer_uid, //customer_uid 파라메터가 있어야 빌링키 발급이 정상적으로 이뤄집니다.
			buyer_email : 'iamport@siot.do',
			buyer_name : '아임포트',
			buyer_tel : '02-1234-1234'
		}, function(rsp) {
			if ( rsp.success ) {
				$.ajax({
					url:'/insertSubscribe', //DB에 구독정보 등록하는 부분..
					data:{
						package_id : $('#package_id').val(),
						customer_id : $('#customer_id').val()
					},
					success:function(result) {
						alert('정기결제 등록'+result);
					}
				});
				
			    alert($('#customer_id').val());
				$.ajax({
					url:'/payment1', //결제 상태를 확인하고 스케줄러를 호출하는 부분
					type : 'POST',
					data:{
						"customer_uid" : customer_uid,
						"price" :price, 
						"merchant_uid" : new Date().getTime()
					},
					success:function(result) {
						alert('다음 결제 예약');
					}
				});
			} else {
				alert('빌링키 발급 실패');
				}
			});
	}	

</script>

위는 결제 확인 페이지에서 정기결제하기 버튼을 눌렀을 때 수행되는 자바스크립드 코드이다. 빌링키가 정상적으로 발급되면, 즉 정기결제가 등록되고 최초 결제가 이루어지면 ajax를 통해 두 가지의 요청을 전송한다. 첫번째는 DB에 방금 생성된 구독 정보를 삽입하는 것이다. 그리고 두번째가 다음 결제 일정을 예약하는 것이다.

 

 

아임포트 docs에서 말하듯 node.js를 사용하여 나만의 서비스 서버를 구축하고, endpoint를 생성하면 내가 생성한 서버가 반복해서 아임포트 서버와 요청과 응답을 주고받을 수 있지만 node.js를 다루지 못하는 관계로 스프링부트의 스케줄러를 사용하여 스프링부트 서버가 살아있는 동안 결제 요청을 보내도록 구현하였다. 

 

 

 

Controller

 

	@PostMapping("/payment1")
	public @ResponseBody void getImportToken(@RequestParam Map<String, Object> map)
			throws JsonMappingException, JsonProcessingException {
		int customer_uid = Integer.parseInt((String) map.get("customer_uid"));
		int price = Integer.parseInt((String) map.get("price"));
		long merchant_uid =  Long.parseLong((String) map.get("merchant_uid"));

		if(getPayementStatus.paymentStatus(merchant_uid).equals("paid")) {
			scheduler.startScheduler(customer_uid,price);
		}
	}
	

 

위의 컨트롤러에서 필요한 모든 메소드들을 호출하여 사용한다. ajax로 전송한 json 데이터들을 받아 처리해야 하기 때문에 @ResponseBody를 사용하였다. ajax 요청에서 map 형태로 전달받은 parameter에서 value에 해당하는 값을 얻은 후, 해당 값들을 가지고 결제 예약 요청을 보낼 것이다.

 

https://tjdqlscjswp.tistory.com/78

 

아임포트 스프링 연동 코드 링크

예제 코드를 리뷰도 하고 공부하며 나눠서 올려보려 했는데 시간과 의지 부족으로 인해 일단 코드 링크를 올려둡니다.  https://github.com/tjdqlscjswp/IMPORT_EXAMPLE GitHub - tjdqlscjswp/IMPORT_EXAMPLEContribute to

tjdqlscjswp.tistory.com

 

 

 

 

 

728x90
반응형
LIST