김다은
김다은4w ago

결제 승인 API CORS 에러 문의

결제 요청 -> 인증 -> 마지막 승인 단계에서, POST https://api.tosspayments.com/v1/payments/confirm 를 호출하는 API 서버에 요청할 때 CORS 에러가 발생합니다. 요청 헤더 Origin: http://localhost:3001, 응답 헤더 Access-Control-Allow-Origin: http://localhost:3001 모두 정상적으로 설정되어 있으며 서버의 출처는 http://localhost:8093입니다. 이렇게 로컬에서 프론트, 백 모두 실행하는 경우에만 발생하는 문제로, 개발 서버(EC2)에 올려 실행하는 경우에는 동일한 오류 재연되지 않습니다. 개발 서버에서는 nginx 프록시 서버를 두어 프론트, 백엔드 모두 동일한 포트로 요청이 들어오도록 설정되어 있는데 이것과 관련이 있을까요?? 왜 CORS 정책을 허용하는 헤더를 설정했음에도 CORS 오류가 나는지 궁급합니다. 또한, 토스 결제 API 요청 시 추가로 설정해줘야 하는 부분이 있을까요??
No description
7 Replies
토스페이먼츠 BOT
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) : - 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요. * 주말/공휴일에는 답변이 늦을 수 있어요.
Ayaan
Ayaan4w ago
Access-Control-Allow-Credentials값이 true, true로 올바르지 않게 오고있다는 오류이네요 true 한번만 적히도록 해주세요
김차장
김차장4w ago
승인요청이 브라우저에서 수행되는 구조일까요? apiKey 가 노출될 수 있기때문에 브라우저에서 승인요청이 진행되면 안됩니다. 결제창이후에 orderId, amount, paymentKey 를 postman 이나 curl 같은 프로그램을 사용해서 승인요청시에도 에러가 발생하는지 확인부탁드려요
Ayaan
Ayaan4w ago
그건 아닌것 같아요 로그를 보니, localhost:8983으로 요청이 나가고있어서요. localhost:8983의 ACAC 헤더에 문제가 있는거 같네요
Kimoon Lee
Kimoon Lee4w ago
Ayaan 님 말씀처럼 작성하신 페이지에서 다른 포트로 Ajax 요청을 할수 없도록 헤더 설정이 되어 있는 것 같습니다. 답변 드린 내용 참고해서 수정해 주시면 됩니다.
토스페이먼츠 BOT
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.
김다은
김다은4w ago
혹시 동일한 오류 발생하는 다른 분들을 위해 남깁니다.
@FeignClient(value = "tossPaymentClient", url = "https://api.tosspayments.com", configuration = TossPaymentClientConfig.class)
public interface TossPaymentClient {

@PostMapping("/v1/payments/confirm")
ResponseEntity<PaymentResponse> confirmPayment(@RequestHeader("Idempotency-Key") String idempotencyKey, @RequestBody PaymentRequest request);
}
@FeignClient(value = "tossPaymentClient", url = "https://api.tosspayments.com", configuration = TossPaymentClientConfig.class)
public interface TossPaymentClient {

@PostMapping("/v1/payments/confirm")
ResponseEntity<PaymentResponse> confirmPayment(@RequestHeader("Idempotency-Key") String idempotencyKey, @RequestBody PaymentRequest request);
}
@Tag(name = "결제 승인 API")
@RequiredArgsConstructor
@RequestMapping("/portal/v2/apis/payments")
@RestController
public class PaymentController {

private final TossPaymentClient tossPaymentClient;

@PostMapping("/confirm")
public ResponseEntity<PaymentResponse> confirmPayment(@RequestBody PaymentRequest request, HttpServletResponse response) {
return tossPaymentClient.confirmPayment(request.getPaymentKey(), request).getBody();
}
}
@Tag(name = "결제 승인 API")
@RequiredArgsConstructor
@RequestMapping("/portal/v2/apis/payments")
@RestController
public class PaymentController {

private final TossPaymentClient tossPaymentClient;

@PostMapping("/confirm")
public ResponseEntity<PaymentResponse> confirmPayment(@RequestBody PaymentRequest request, HttpServletResponse response) {
return tossPaymentClient.confirmPayment(request.getPaymentKey(), request).getBody();
}
}
위와 같이 토스 결제 승인 API 호출 시 feign client를 사용하고 있습니다. 이때 응답으로 떨어진 ResponseEntity 객체를 컨트롤러에서 그대로 반환하고 있었습니다. POST https://api.tosspayments.com/v1/payments/confirm 해당 API를 포스트맨으로 실행했을 때 위 스크린샷과 같이 동일한 헤더가 여러번 중복되어 전달되고 있어 CORS 오류가 발생했던 것입니다.
java
return ResponseEntity.ok(tossPaymentClient.confirmPayment(request.getPaymentKey(), request).getBody());
java
return ResponseEntity.ok(tossPaymentClient.confirmPayment(request.getPaymentKey(), request).getBody());
위와 같이 body 값만 따로 추출하여 응답으로 전달하도록 수정하면 오류 발생하지 않습니다. 감사합니다. + 추가로 저렇게 응답 헤더가 여러번 중복되는 이유가 따로 있을 까요?? (ex. 브라우저로부터의 직접적인 승인 요청을 막기 위해)
No description