반응형

카카오페이를 사용하여 결제 시스템을 구현하기 위해서는 카카오페이 API를 활용하여 결제 요청부터 완료까지의 과정을 단계별로 설계하고 구현해야 합니다. 아래는 이를 구현하는 상세한 단계와 예제 코드입니다.


1. 카카오페이 API의 기본 구조

1-1. 주요 API

  1. 결제 준비(Ready): 결제 프로세스를 시작하기 위한 API입니다.
  2. 결제 승인(Approve): 사용자가 결제를 완료한 후, 결제 정보를 확인하고 승인합니다.
  3. 결제 취소(Cancel): 결제 취소 요청 시 사용됩니다.
  4. 결제 조회(Order Lookup): 특정 결제 건의 정보를 조회합니다.

1-2. 카카오페이 API 연동의 사전 준비

  1. 카카오 개발자센터에서 애플리케이션 생성.
  2. REST API 키 발급.
  3. 결제 API를 테스트할 수 있는 테스트 환경 설정.
  4. Webhook URL 설정(옵션, 결제 성공 시 콜백 처리용).

2. 결제 구현 흐름

  1. 결제 준비 요청
    서버에서 결제 정보를 준비하고 카카오페이 API에 요청합니다. 성공 시 결제 페이지 URL을 반환받습니다.
  2. 결제 페이지로 리다이렉트
    반환된 URL을 클라이언트에서 호출하여 사용자가 결제 화면으로 이동합니다.
  3. 결제 승인 요청
    결제가 성공적으로 완료되면 승인 요청을 통해 결제를 확정합니다.
  4. 결제 완료 후 처리
    결제 정보를 저장하고 사용자에게 결과를 알립니다.

3. 구현 방법

3-1. 서버 연동 코드 (Spring 기반)

필수 의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

3-2. 결제 준비 단계

Controller

@RestController
@RequestMapping("/kakaopay")
public class KakaoPayController {

    @Autowired
    private KakaoPayService kakaoPayService;

    @PostMapping("/ready")
    public ResponseEntity<?> readyToPay(@RequestBody PaymentRequest request) {
        KakaoPayResponse response = kakaoPayService.kakaoPayReady(request);
        return ResponseEntity.ok(response);
    }
}

Service

@Service
public class KakaoPayService {

    private static final String KAKAO_API_KEY = "YOUR_KAKAO_REST_API_KEY";
    private static final String KAKAO_READY_URL = "https://kapi.kakao.com/v1/payment/ready";

    public KakaoPayResponse kakaoPayReady(PaymentRequest request) {
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(KAKAO_READY_URL);

            // 헤더 설정
            httpPost.setHeader("Authorization", "KakaoAK " + KAKAO_API_KEY);
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

            // 요청 데이터 설정
            List params = new ArrayList<>();
            params.add(new BasicNameValuePair("cid", "TC0ONETIME")); // 테스트용 CID
            params.add(new BasicNameValuePair("partner_order_id", "12345")); // 주문 번호
            params.add(new BasicNameValuePair("partner_user_id", "user123")); // 사용자 ID
            params.add(new BasicNameValuePair("item_name", request.getItemName())); // 상품 이름
            params.add(new BasicNameValuePair("quantity", String.valueOf(request.getQuantity()))); // 상품 수량
            params.add(new BasicNameValuePair("total_amount", String.valueOf(request.getTotalAmount()))); // 총 금액
            params.add(new BasicNameValuePair("tax_free_amount", "0")); // 비과세 금액
            params.add(new BasicNameValuePair("approval_url", "http://yourdomain.com/kakaopay/success")); // 성공 URL
            params.add(new BasicNameValuePair("cancel_url", "http://yourdomain.com/kakaopay/cancel")); // 취소 URL
            params.add(new BasicNameValuePair("fail_url", "http://yourdomain.com/kakaopay/fail")); // 실패 URL

            httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

            // 요청 실행 및 응답 처리
            HttpResponse response = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");

            // 응답 JSON 파싱
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(responseBody, KakaoPayResponse.class);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("카카오페이 결제 준비 중 오류 발생");
        }
    }
}

Response 객체

@Data
public class KakaoPayResponse {
    private String tid; // 결제 고유 번호
    private String next_redirect_pc_url; // PC 결제 URL
    private String next_redirect_mobile_url; // 모바일 결제 URL
    private String created_at;
}

3-3. 결제 승인 단계

Service

@Service
public class KakaoPayService {

    private static final String KAKAO_APPROVE_URL = "https://kapi.kakao.com/v1/payment/approve";

    public KakaoPayResponse kakaoPayApprove(String tid, String pgToken) {
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(KAKAO_APPROVE_URL);

            httpPost.setHeader("Authorization", "KakaoAK " + KAKAO_API_KEY);
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

            List params = new ArrayList<>();
            params.add(new BasicNameValuePair("cid", "TC0ONETIME"));
            params.add(new BasicNameValuePair("tid", tid));
            params.add(new BasicNameValuePair("partner_order_id", "12345"));
            params.add(new BasicNameValuePair("partner_user_id", "user123"));
            params.add(new BasicNameValuePair("pg_token", pgToken));

            httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));

            HttpResponse response = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");

            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.readValue(responseBody, KakaoPayResponse.class);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("카카오페이 결제 승인 중 오류 발생");
        }
    }
}

3-4. 결제 완료 후 처리

  1. DB에 결제 내역 저장.
  2. 사용자에게 결제 결과 알림 전송(SMS, 이메일 등).

4. 보안 강화

  1. REST API 키 보호: 민감 정보는 서버 환경 변수나 암호화된 저장소에 보관.
  2. HTTPS 사용: 모든 요청은 HTTPS를 통해 전송.
  3. Webhook 검증: 카카오페이에서 전달되는 콜백 데이터를 반드시 검증.

결론

카카오페이 결제 시스템은 REST API 기반으로 동작하며, 결제 준비, 승인, 취소 등의 단계를 명확히 구현해야 합니다. 위 코드를 참조하여 사용자 친화적인 결제 시스템을 구축할 수 있습니다.

반응형

+ Recent posts