[ 카카오페이 단건 결제 ]

2024. 5. 15. 18:39· BACK-END/└ 카카오페이 결제_단건결제

카카오페이 개발자 센터 링크 : 카카오페이 | 개발자센터 (kakaopay.com)

(현시각 기준)카카오페이가 제공하는 자료 정보를 바탕으로 진행..

 

 

일단!!

 

요청(Request)/응답(Response)!! 이 두 가지를 기억해야 한다. 

상위개념처럼 생각하고 있으면 개념잡기에 도움이 될 듯 하다..

 

 

 당연히 결제는 요청을 해야 응답을 해줄 수 있다.

따라서 요청 부분을 보자 

 

📎Request Syntax

POST /online/v1/payment/ready HTTP/1.1
Host: open-api.kakaopay.com
Authorization: SECRET_KEY ${SECRET_KEY}
Content-Type: application/json

 

    위 정보를 해석해보자면

    전송방식 : POST
    요청주소 : /online/v1/payment/ready
    통신규격 : HTTP/1.1
    Host: open-api.kakaopay.com


    Authorization: SECRET_KEY ${SECRET_KEY}
    Content-Type: application/json

 

 이 정보를 통해 헤더 정보와 우리가 요청 보낼 주소를 뽑아낼 수 있다.

    → https://open-api.kakaopay.com/online/v1/payment/ready [POST]

 

 요청을 보낼 주소에 결제 필요한 정보를 넘겨줘야 응답을 받을 수 있다. 

카카오에서 우리에게 이것만큼은 꼭 넘겨줘야 하는 정보라고 알려준 값들엔 Required 표시가 있다. 이를 바탕으로 값을 넘겨줘야 함. 

 

📎 Request Body Payload

 

 가맹점 번호는 아래와 같이 안내가 나오고 있다. 

 cid 값으로 TC0ONETIME 을 사용하면 됨.


 

테스트 해보자. (코드 설명은 주석에 달아두겠음😓)

 - 구매자 아이디 정보는 "testuser1"로 지정하여 실행하겠음. (로그인 정보까지 불러오면 또 한 바기지임..)

 

 

[ 카카오페이 서버에 결제 준비(ready) 요청을 보내보자! ]

   - KakaoPayTest01.java

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootTest
public class KakaoPayTest01 {

	@Test
	public void test() throws URISyntaxException {
		//카카오페이 서버에 결제 준비(ready) 요청을 보내보자!
		
		//요청 전송 도구 생성 - 서드파티(Third Party)로 통신 시 RestTemplate가 필요하다
		RestTemplate template = new RestTemplate();
		
		//주소 생성 - 요청 전송 주소
		URI uri = new URI("https://open-api.kakaopay.com/online/v1/payment/ready");
				
		//헤더 생성
		HttpHeaders header = new HttpHeaders();
		header.add("Authorization", "SECRET_KEY 사용자 키 값");
		header.add("Content-Type", "application/json");
				
		//바디 생성
		//JSON에서 변환하면 MultiValueMap과 Map이 달라서 인식이 안됨.
		//MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
		Map<String, String> body = new HashMap<>();
		body.put("cid", "TC0ONETIME");//가맹점 번호
		body.put("partner_order_id", UUID.randomUUID().toString()); //가맹점 주문번호, UUID (Universally Unique IDentifier) 범용 고유 식별자
		body.put("partner_user_id", "testuser1");//가맹점 회원 id,
		body.put("item_name", "아이스아메리카노 외 1건");//상품명, 최대 100자
		body.put("quantity", "1");//상품 수량
		body.put("total_amount", "100");//상품 총액
		body.put("tax_free_amount", "0");//상품 비과세 금액
		body.put("approval_url", "http://localhost:8080/success");//결제 성공 시 redirect url
		body.put("cancel_url", "http://localhost:8080/cancel");//결제 취소 시 redirect url
		body.put("fail_url", "http://localhost:8080/fail");//결제 실패 시 redirect url
		
		//통신요청
		HttpEntity entity = new HttpEntity(body, header);//헤더+바디
		
		//Map response = template.postForObject(uri, entity, 결과물의형태);
		Map response = template.postForObject(uri, entity, Map.class);
		
		//필요한 정보를 로깅하여 값을 확인해보자
		log.debug("partner_order_id = {}", body.get("partner_order_id"));
		log.debug("partner_user_id = {}", body.get("partner_user_id"));
		log.debug("거래번호 = {}", response.get("tid"));
		log.debug("주소 = {}", response.get("next_redirect_pc_url"));
	}
}

 

콘솔 창에 찍힌 로그는 아래와 같다

[DEBUG] partner_order_id = e142b1f0-0636-4255-a6d6-fd0f8e2a9237 
[DEBUG] partner_user_id = testuser1
[DEBUG] 거래번호 = T61244e665886da9aa07 
[DEBUG] 주소 = https://online-pay.kakao.com/mockup/v1/83bad5383785b76e5fb908fe93bd5fc2fe60d5f9e7a247b40baf644d45bc767c/info

 

콘솔에 있느 주소로 접속 하면 QR 화면이 나온다 그 QR을 폰으로 접속하면 결제 화면이 뜬다!!

PC 화면 → 모바일 화면

 

결제하기를 누르면 PC 화면에서 다음 페이지로 넘어가는 주소가 뜬다 - 여기서 pg_token 값을 얻을 수 있다.

http://localhost:8080/success?pg_token=bf40ba18cf9067bc53c8

 

승인도 똑같이 진행하면 된다. (주소 확인 및 보내야 할 정보 확인)

 

📎 Request Syntax

POST /online/v1/payment/approve HTTP/1.1
Host: open-api.kakaopay.com
Authorization: SECRET_KEY ${SECRET_KEY}
Content-Type: application/json

 

📎 Request Body Payload

  승인을 위해 필요한 정보는 위와 같다.

 

이 필요한 정보를 요청 페이지에서 가져와야 함!!!!!!

 

따라서 위에서 찍은 로그 정보를 토대로 승인페이지에서 값을 삽입하여 결제 시 카카오톡으로 결제 완료 메시지가 날아온다. 확인 해보자 

 

필수적으로 필요한 5개의 변수에 대한 값을 여기저기서 모아와서 (로그, URL 등등) 값을 넣고 테스트 실행

 

[ 카카오페이 서버에 결제 승인(approve)을 해보자! ]

    - KakaoPayTest02.java

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootTest
public class KakaoPayTest02 {

	@Test
	public void test() throws URISyntaxException {
		//카카오페이 서버에 결제 승인(approve)을 해보자!
		
		//요청 전송 도구 생성 
		RestTemplate template = new RestTemplate();
		
		//주소 생성 - 요청 전송 주소
		URI uri = new URI("https://open-api.kakaopay.com/online/v1/payment/approve");
				
		//헤더 생성
		HttpHeaders header = new HttpHeaders();
		header.add("Authorization", "SECRET_KEY 사용자 비밀키 입력");
		header.add("Content-Type", "application/json");
				
		//바디 생성
		Map<String, String> body = new HashMap<>();
		body.put("cid", "TC0ONETIME");//가맹점 코드
		body.put("tid", "T61244e665886da9aa07");//결제 고유번호
		body.put("pg_token", "bf40ba18cf9067bc53c8");//결제승인 요청을 인증하는 토큰
		body.put("partner_order_id", "e142b1f0-0636-4255-a6d6-fd0f8e2a9237");//가맹점 주문번호
		body.put("partner_user_id", "testuser1");//가맹점 회원 id
		
		//통신요청
		HttpEntity entity = new HttpEntity(body, header);//헤더+바디
		
		Map response = template.postForObject(uri, entity, Map.class);
	}
}

 

테스트가 성공하고 카카오톡 결제 완료 알림 문자가 온다.

테스트 성공 / 카카오톡 결제 완료 톡

 

 


 

정말.. 이건 백엔드에서 코드가 실행되는지 확인한 것. 

근데 코드가 너무 지저분하니까 모듈화를 해주고, 제일 마지막에 사용자 화면에서 실행될 수 있도록 코드를 계속 업그레이드 해주면 된다.

 

 

 

자..

 

테스트 클래스 파일을 보며.. 잘 안바뀌는 정보나 고정된 정보들은 따로 빼주자.

 

관리자 key값과 cid가 고정된 값이라고 볼 수 있다. 따라서 이 값을 application.properties 파일에 저장해준다

   - application.properties.xml

# kakaopay setting
custom.pay.key=키값입력
custom.pay.cid=TC0ONETIME

 

값을 저장해주면 이제 그걸 불러와서 사용해야 함.

그 불러와서 사용할 수 있는 설정을 이제부터 수행하겠다

 

 

   - KakaoPayProperties.java

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;

import lombok.Data;

@Data
@Service
@ConfigurationProperties(prefix = "custom.pay")
public class KakaoPayProperties {
	private String key;//custom.pay.key
	private String cid;//custome.pay.cid
}

 

 

설정 완료!


 

 KakaoPayTest01.java 에서 우리가 바디에 넣어주는 값 중 계속 바뀌는 값과 고정 값을 분리해보자

 

 

- 바뀌지 않는 정보

body.put("cid", "TC0ONETIME");//가맹점 번호
body.put("quantity", "1");//상품 수량
body.put("tax_free_amount", "0");//상품 비과세 금액
body.put("approval_url", "http://localhost:8080/success");//결제 성공 시 redirect url
body.put("cancel_url", "http://localhost:8080/cancel");//결제 취소 시 redirect url
body.put("fail_url", "http://localhost:8080/fail");//결제 실패 시 redirect url

 

- 바뀌는 정보

body.put("partner_order_id", UUID.randomUUID().toString()); //가맹점 주문번호, UUID (Universally Unique IDentifier) 범용 고유 식별자

body.put("partner_user_id", "testuser1");//가맹점 회원 id,
body.put("item_name", "아이스아메리카노 외 1건");//상품명, 최대 100자

body.put("total_amount", "100");//상품 총액

 

이 바뀌는 정보를 매번 코드에 치는 것은 비효율적이므로 클래스를 만들어서 작업하면 좋을것 같아보임 따라서 VO를 만들자! (KakaoPayReadyRequestVO)

 

    - KakaoPayReadyRequestVO.java

//카카오페이 준비요청을 위한 VO
@Data 
@Builder @NoArgsConstructor @AllArgsConstructor //Builder 사용시 필요한 어노테이션
public class KakaoPayReadyRequestVO {
	private String partnerOrderId;
	private String partnerUserId;
	private String itemName;
	private int totalAmount;
}

   (+) 카멜케이스로 변수명을 작성하기 위해선 application.properties.xml 파일에 추가 설정이 필요하

mybatis.configuration.map-underscore-to-camel-case=true

 

  그런데, 결과에 대한 정보도 모듈화를 해줘야 한다. Map으로 받게 되면 무엇을 받았는지 알 수 없고, 우리가 필요한 정보만 빼내기 어렵기 때문이다. 

 

   - KakaoPayReadyResponseVO.java

//카카오페이 준비 요청이 완료되었을 때 카카오페이에서 보내주는 정보를 담을 VO
//(카카오페이가 보내주면 자동으로 생성되어야 함.(자동생성) - JSON 변환 설정을 추가(알아서 생성되도록 하기 위함))
@JsonIgnoreProperties(ignoreUnknown = true)//혹시 없는 항목은 넘어가줘...
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)//카멜케이스로 바꿔줘..
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class KakaoPayReadyResponseVO {
	private String tid;//결제 고유번호(20자)
	private String nextRedirectMobileUrl;//모바일 웹용 결제페이지 주소
	private String nextRedirectPcUrl;//PC용 결제페이지 주소
	private String createdAt;//결제 준비 요청 시각
}

  

 

위의 두 VO의 어노테이션이 다르다.

 

요청의 경우 우리가 필요한 변수들을 편하게 사용하기 위해 객체를 "내가" 만들었다면,

응답에 필요한 변수들은 카카오페이가 제공하는 문서에 적힌 변수 값들을 사용해야한다. 즉 카카오페이가 보내주면 자동으로 생성되어야 한다.

 

그러기 위해서 JSON 변환 설정을 추가 해준다. 

@JsonIgnoreProperties(ignoreUnknown = true) 

 : 카카오페이가 제공하고 있는 모든 변수 값을 사용하지 않고 있기 때문에 만약 없는 항목에 대한 내용은 넘어가달라고 선언하는 내용이다.

@JsonNaming(PRopertyNamingStrategies.SnakeCaseStrategy.class)

 : 카카오페이의 변수를 카멜케이스로 자동 변환을 요청하는 내용이다. 

 

 

이제 이 VO와 Configuration을 불러와 사용하는 테스트 코드를 작성해보자 (Test01내용을 수정!)

   -  KakaoPayTest03.java

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.client.RestTemplate;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootTest
public class KakaoPayTest03 {
	
	@Autowired
	private KakaoPayProperties kakaoPayProperties;

	@Test
	public void test() throws URISyntaxException {
		//카카오페이 서버에 결제 준비(ready) 요청을 보내보자!
		
		//결제에 필요한 정보를 미리 생성 (여기서 생성한 후 밑에서 불러오기)
		KakaoPayReadyRequestVO requestVO = 
				KakaoPayReadyRequestVO.builder()
					.partnerOrderId(UUID.randomUUID().toString())
					.partnerUserId("testuser1")
					.itemName("어려워 죽겠네")
					.totalAmount(99000)
				.build();
		
		//요청 전송 도구 생성 
		RestTemplate template = new RestTemplate();
		
		//주소 생성 - 요청 전송 주소
		URI uri = new URI("https://open-api.kakaopay.com/online/v1/payment/ready");
				
		//헤더 생성
		HttpHeaders header = new HttpHeaders();
		header.add("Authorization", "SECRET_KEY "+kakaoPayProperties.getKey());//속성 값 불러오기
		header.add("Content-Type", "application/json");
				
		//바디 생성
		Map<String, String> body = new HashMap<>();
		body.put("cid", kakaoPayProperties.getCid());//속성 값 불러오기
		body.put("partner_order_id", requestVO.getPartnerOrderId()); //reqeustVO의 값을 불러와 삽입
		body.put("partner_user_id", requestVO.getPartnerUserId());
		body.put("item_name", requestVO.getItemName());
		body.put("quantity", "1");
		body.put("total_amount", String.valueOf(requestVO.getTotalAmount())); //문자열로 변환
		body.put("tax_free_amount", "0");
		body.put("approval_url", "http://localhost:8080/success");
		body.put("cancel_url", "http://localhost:8080/cancel");
		body.put("fail_url", "http://localhost:8080/fail");
		
		//통신요청
		HttpEntity entity = new HttpEntity(body, header);//헤더+바디
		
		// MAP이 아닌 VO로 받기
		KakaoPayReadyResponseVO responseVO = template.postForObject(uri, entity, KakaoPayReadyResponseVO.class);
		log.debug("partner_order_id = {}", requestVO.getPartnerOrderId());
		log.debug("partner_user_id = {}", requestVO.getPartnerUserId());
		log.debug("거래번호 = {}", responseVO.getTid());
		log.debug("주소 = {}", responseVO.getNextRedirectPcUrl());
	}
}

 


 

 

//요청 전송 도구 생성 
RestTemplate template = new RestTemplate();

//헤더 생성
HttpHeaders header = new HttpHeaders();
header.add("Authorization", "SECRET_KEY "+kakaoPayProperties.getKey());//속성 값 불러오기
header.add("Content-Type", "application/json");

 

그런데 //헤더 생성 부분은 언제나 고정된 값이다. 바뀌지 않으니 모듈화 해주면 좋겠죠?! 따라서 @Configuration에 등록해서 사용하자

 

일관된 도구를 사용하기 위한 절차라고 생각하면 좋겠다!!!

 

   - KakaoPayConfiguration.java

@Configuration
public class KakaoPayConfiguration {
	
	@Autowired
	private KakaoPayProperties kakaoPayProperties;
	
	@Bean
	public RestTemplate template() {
		return new RestTemplate();
	}
	
	@Bean
	public HttpHeaders header() {
		HttpHeaders header = new HttpHeaders();
		header.add("Authorization", "SECRET_KEY "+kakaoPayProperties.getKey());//속성 값 불러오기
		header.add("Content-Type", "application/json");
		return header;
	}
}

 

 이제 여기저기서 불러와서 사용할 수 있음!!


 

 이제 남은 부분에 대한 모듈화를 진행해보겠다. Service를 제공하는 부분이므로 서비스 클래스로 만들어 줄거다.

근데 이 때, 우리가 이미 Configuration에 고정된 애들은 지정을 해두었기에 이 부분을 제외하고 서비스화 시켜주면 된다. 

 

@Service
public class KakaoPayService {

	@Autowired
	private KakaoPayProperties kakaoPayProperties;
	
	@Autowired
	private RestTemplate template; //KakaoPapConfiguration에 있는거 가져와서 사용
	
	@Autowired
	private HttpHeaders header; //KakaoPapConfiguration에 있는거 가져와서 사용
	
	//준비요청 메소드
	public KakaoPayReadyResponseVO ready(KakaoPayReadyRequestVO requestVO) throws URISyntaxException {
		//주소 생성 - 요청 전송 주소
		URI uri = new URI("https://open-api.kakaopay.com/online/v1/payment/ready");
	
		//바디 생성
		Map<String, String> body = new HashMap<>();
		body.put("cid", kakaoPayProperties.getCid());//속성 값 불러오기
		body.put("partner_order_id", requestVO.getPartnerOrderId()); //reqeustVO의 값을 불러와 삽입
		body.put("partner_user_id", requestVO.getPartnerUserId());
		body.put("item_name", requestVO.getItemName());
		body.put("quantity", "1");
		body.put("total_amount", String.valueOf(requestVO.getTotalAmount())); //문자열로 변환
		body.put("tax_free_amount", "0");
		body.put("approval_url", "http://localhost:8080/success");
		body.put("cancel_url", "http://localhost:8080/cancel");
		body.put("fail_url", "http://localhost:8080/fail");
		
		//통신요청
		HttpEntity entity = new HttpEntity(body, header);//헤더+바디
		
		return template.postForObject(uri, entity, KakaoPayReadyResponseVO.class);
	}
	
	//승인요청 메소드
	
	
}

 

자, 이제 테스트를 진행해보자

 

   - KakaoPayTest04.java

@Slf4j
@SpringBootTest
public class KakaoPayTest04 {

	@Autowired
	private KakaoPayService kakaoPayService;
	
	@Test
	public void test() throws URISyntaxException {
		//결제에 필요한 정보를 미리 생성 (여기서 생성한 후 밑에서 불러오기)
		KakaoPayReadyRequestVO requestVO = 
				KakaoPayReadyRequestVO.builder()
					.partnerOrderId(UUID.randomUUID().toString())
					.partnerUserId("testuser1")
					.itemName("어려워 죽겠네")
					.totalAmount(99000)
				.build();
		
		KakaoPayReadyResponseVO responseVO = kakaoPayService.ready(requestVO);
	
		log.debug("requestVO = {}", requestVO);
		log.debug("responseVO = {}", responseVO);
	}
}

 

 

요청 부분의 코드가 훨씬 간결해진 것을 알 수 있다!!!!!!!!!!!!!


 

같은 방법으로 승인 부분에 대한 것도 모듈화를 진행해보자 

   - KakaoPayApproveRequestVO.java

//카카오페이 승인요청을 보내기 위한 정보를 담는 VO(내가 만들어서 사용)
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class KakaoPayApproveRequestVO {
	private String tid;
	private String partnerOrderId;
	private String partnerUserId;
	private String pgToken;
}

 

 

이제 KakaoPayApproveResponseVO를 만들 차례다. 그런데, 응답의 경우 필요한 변수가 개많음 진심!!!!!!!

문서를 보면서 설명해보겠다

 

📎Response Body Payload

 보면 amount와 card_info의 데이터 타입이 Amount, CardInfo로 하이퍼링크 되어있다. 들어가보자

 

각각의 데이터타입에 맞춰 필요한 정보들이 한 바가지다.. 

그래서 이걸 또 VO로 만들어 줘야함. 

 

amount, card_info에 필요한 정보 VO 만들고 응답에 필요한 VO 만드는 순서로 진행 하겠다. 

 

   -  KakaoPayAmountVO.java

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class KakaoPayAmountVO {
	private int total;//전체 결제 금액
	private int taxFree;//비과세 금액
	private int vat;//부가세 금액
	private int point;//사용할 포인트 금액
	private int discount;//할인 금액
	private int greenDeposit;//컵 보증금
}

 

    - KakaoPayCardInfoVO.java

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class KakaoPayCardInfoVO {
	private String kakaopayPurchaseCorp;//카카오페이 매입사명
	private String kakaopayPurchaseCorpCode;//카카오페이 매입사 코드
	private String kakaopayIssuerCorp;//카카오페이 발급사명
	private String kakaopayIssuerCorpCode;//카카오페이 발급사 코드
	private String bin;//카드 BIN
	private String cardType;//카드 유형
	private String installMonth;//할부 개월 수
	private String approvedId;//카드사 승인번호
	private String cardMid;//카드사 가맹점 번호
	private String interestFreeInstall;//무이자할부 여부(Y/N)
	private String installmentType;//할부 유형(2024/02/01~)
	private String cardItemCode;//카드 상품 코드
}

 

   - KakaoPayApproveResponseVO.java

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class KakaoPayApproveResponseVO {
	private String aid;//요청 고유 번호(승인/취소가 구분된 결제번호)
	private String tid;//결제 고유 번호(승인/취소가 동일한 결제번호)
	private String cid;//가맹점 코드
	private String sid;//정기 결제용 ID
	private String partnerOrderId;//가맹점 주문번호
	private String partnerUserId;//가맹점 회원ID
	private String paymentMethodType;//결제 수단(CARD/MONEY)
	private KakaoPayAmountVO amount;//결제 금액 정보
	private KakaoPayCardInfoVO cardInfo;//결제 상세 정보(카드일 경우)
	private String itemName;//상품 이름(최대 100자)
	private String itemCode;//상품 코드(최대 100자)
	private int quantity;//상품 수량
	private String createdAt;//결제 준비 요청 시각
	private String approvedAt;//결제 승인 시각
	private String payload;//결제 승인 요청에 대한 추가 파라미터 정보
}

 

 

자, 길고긴 VO 만들기가 끝났다.

 

이제 KakaoPayService의 승인요청 메소드를 만들자.

 

    - KakaoPayService.java

@Service
public class KakaoPayService {

	@Autowired
	private KakaoPayProperties kakaoPayProperties;
	
	@Autowired
	private RestTemplate template;
	
	@Autowired
	private HttpHeaders header;
	
	//준비요청 메소드
	public KakaoPayReadyResponseVO ready(KakaoPayReadyRequestVO requestVO) throws URISyntaxException {
		//주소 생성 - 요청 전송 주소
		URI uri = new URI("https://open-api.kakaopay.com/online/v1/payment/ready");
	
		//바디 생성
		Map<String, String> body = new HashMap<>();
		body.put("cid", kakaoPayProperties.getCid());//속성 값 불러오기
		body.put("partner_order_id", requestVO.getPartnerOrderId()); //reqeustVO의 값을 불러와 삽입
		body.put("partner_user_id", requestVO.getPartnerUserId());
		body.put("item_name", requestVO.getItemName());
		body.put("quantity", "1");
		body.put("total_amount", String.valueOf(requestVO.getTotalAmount())); //문자열로 변환
		body.put("tax_free_amount", "0");
		body.put("approval_url", "http://localhost:8080/success");
		body.put("cancel_url", "http://localhost:8080/cancel");
		body.put("fail_url", "http://localhost:8080/fail");
		
		//통신요청
		HttpEntity entity = new HttpEntity(body, header);//헤더+바디
		
		return template.postForObject(uri, entity, KakaoPayReadyResponseVO.class);
	}
	
	//승인요청 메소드
	public KakaoPayApproveResponseVO approve(KakaoPayApproveRequestVO requestVO) throws URISyntaxException {
		//주소 생성 - 요청 전송 주소
		URI uri = new URI("https://open-api.kakaopay.com/online/v1/payment/approve");
		
		//바디 생성
		Map<String, String> body = new HashMap<>();
		body.put("cid", kakaoPayProperties.getCid());
		body.put("tid", requestVO.getTid());
		body.put("pg_token", requestVO.getPgToken());
		body.put("partner_order_id", requestVO.getPartnerOrderId());
		body.put("partner_user_id", requestVO.getPartnerUserId());
		
		//통신요청
		HttpEntity entity = new HttpEntity(body, header);//헤더+바디
		
		return template.postForObject(uri, entity, KakaoPayApproveResponseVO.class);
	}
	
}

 

 

그럼 이제 승인에 대한 테스트를 진행하자

 

코드는 아래와 같고, 정보를 앞서 했던 테스트 방식과 동일하게 값들을 찾아와 넣어준 후 실행하면 된다.

@Slf4j
@SpringBootTest
public class KakaoPayTest05 throws URISyntaxException {
	
	@Autowired
	private KakaoPayService kakaoPayService;
	
	@Test
	public void test() {
		//데이터 준비 - KakaoPayApproveRequestVO
		KakaoPayApproveRequestVO requestVO = 
				KakaoPayApproveRequestVO.builder()
					.tid()
					.partnerOrderId()
					.partnerUserId()
					.pgToken()
				.build();
		
		//처리
		KakaoPayApproveResponseVO responseVO = kakaoPayService.approve(requestVO);
		
		//결과 출력 - KakaoPayApproveResponseVO
		log.debug("responseVO = {}", responseVO);
	}
}

 

 

테스트는 똑같으니 생략하겠다..

 

어쨋든 궁극적으로 우리가 가져가야할 코드는 KakaoPayTest04/ KakaoPayTest05 코드이다. 

 


 

544. 단건 결제 - 무식한 결제 부분 부터 정리하기

 

 

 

 

 

 

 

개인 공부 기록용입니다:)

728x90