토이프로젝트에서 결제 기능을 카카오페이로 구현하고자 했다.
카카오페이 온라인 결제는 단건 결제뿐만 아니라 정기결제 등등이 있는데, 단건결제가 현재 서비스에 적합하다고 판단해 단건결제를 구현했다.
카카오페이 API는 다음과 같이 온라인 결제에 대한 공식 문서를 제공한다.
{
"cid": "TC0ONETIME",
"partner_order_id": "2",
"partner_user_id": "family1",
"item_name": "스위트케어 간병 결제 (간병 메이트 변철수)",
"quantity": 1,
"total_amount": 6034320,
"tax_free_amount": 0,
"approval_url": "",
"cancel_url": "",
"fail_url": ""
}
하지만 그러면 안 되는데, 왜냐하면 이미 HTTP 요청이 내부 API 서버에 수신되도록 프록시 설정을 해 두었기 때문이다.
또한 보안상의 이유로 외부 API에 직접 요청을 보내는 것은 권장되지 않는다. 클라이언트에서 직접 외부 API에 요청을 보내는 경우, 보안 문제나 CORS(Cross-Origin Resource Sharing) 문제 등이 발생할 수 있다.
대신 클라이언트는 내부 API 서버를 호출하고, 내부 API 서버가 외부 API 서버 (이 경우에는 카카오페이 API 서버)와 통신하도록 구성할 수 있다.
카카오페이 API 공식 문서에서는 다음과 같이 설명하고 있다.
결제준비(ready)
카카오페이 결제를 시작하기 위해 결제정보를 카카오페이 서버에 전달하고 결제 고유번호(TID)와 URL을 응답받는 단계입니다.
Secret key를 헤더에 담아 파라미터 값들과 함께 POST로 요청합니다.
요청이 성공하면 응답 바디에 JSON 객체로 다음 단계 진행을 위한 값들을 받습니다.
서버(Server)는 tid를 저장하고, 클라이언트는 사용자 환경에 맞는 URL로 리다이렉트(redirect)합니다.
그래서 내부 API 서버에 결제용 도메인을 만들고 클라이언트에서 body에 결제 정보를 담아 요청을 보냈다.
그리고 받아온 요청을 DTO에 담고, 헤더에 필요 정보를 담아서 외부 API에 요청을 보내는 코드를 작성했다.
@RestController
@RequestMapping(path = "/api/v1/payment")
@CrossOrigin()
public class PaymentController {
@Autowired
KakaopayResponseDTO kakaopayResponseDTO;
@PostMapping("/kakaopay")
public KakaopayResponseDTO submitPayment(@RequestBody KakaopayRequestDTO kakaopayRequestDTO) {
RestTemplate restTemplate = new RestTemplate();
String url = "https://open-api.kakaopay.com/online/v1/payment/ready";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "SECRET_KEY " + "your secret key");
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<KakaopayRequestDTO> requestEntity = new HttpEntity<>(kakaopayRequestDTO, headers);
ResponseEntity<KakaopayResponseDTO> responseEntity = restTemplate.postForEntity(url, requestEntity, KakaopayResponseDTO.class);
KakaopayResponseDTO responseDTO = responseEntity.getBody();
System.out.println("Response: " + responseDTO);
return responseDTO;
}
}
이때 Spring Security가 설정되어 있다면 "/open-api.kakaopay.com/**" 을 허용 url로 설정해야 한다.
이 과정에서 필요한 Secret key(dev)는 여기서 발급받을 수 있다.
정상적으로 호출되면 response 메시지를 받을 수 있다.
오류는 다음과 같이 표시되므로, 맞춰서 오류를 수정하면 된다.
400 Bad Request: "{"error_code":-400,"error_message":"API 호출값 중 유효하지 않은 값이 존재합니다. (등록된 도메인(플랫폼 > Web > 사이트도메인)이 존재하지 않아 도메인 검증이 불가능합니다.)"}"
참고로 위 오류는 다음 페이지에서 로컬호스트 (또는 서비스 url) 주소를 등록하면 해결된다.
'개발 프로젝트 > 스위트케어' 카테고리의 다른 글
alert를 모달 알림창으로 변경하기 (0) | 2024.01.29 |
---|---|
모달에서 검색 실행하면 새로고침되는 문제 해결하기 (1) | 2024.01.24 |
스프링 API 서버와 Next.js에서 axiosInstance 사용하기 (0) | 2024.01.22 |
한 페이지에서 useModal 커스텀 훅 두 번 호출하기 (0) | 2024.01.17 |
불변성 개념을 적용해 상태 관리 문제 해결하기 (0) | 2024.01.08 |