안녕하세요. 자바로 토스 페이먼츠 연동 테스트 중 문의사항이 있어 연락드렸습니다.
API문서에 쓰여있는 것을 자바로 바꿔서 연동하고 있는데 응답이 404가 오는 것을 확인했습니다.
시크릿 키는 계정에 주어진 키를 사용했으며, 연동 예제인 노드 파일을 기반으로 구현했습니다.
혹시 확인 가능하실까요? 구현 코드는 아래에 적어보겠습니다.
public PaymentService() {
this.webClient = WebClient.builder()
.baseUrl("https://api.tosspayments.com")
.defaultHeader("Content-Type", "application/json")
.build();
}
public Mono<PaymentConfirmationResponseV2> confirmPayment(PaymentConfirmationRequest paymentConfirmationRequest)
throws UnsupportedEncodingException {
String authorizations = encodeSecretKey();
String idempotencyKey = UUID.randomUUID().toString();
return webClient.post()
.uri("/v1/payments/confirm")
.header(HttpHeaders.AUTHORIZATION, authorizations)
.header("Idempotency-Key", idempotencyKey)
.body(Mono.just(paymentConfirmationRequest), PaymentConfirmationRequest.class)
.retrieve()
.bodyToMono(PaymentConfirmationResponseV2.class)
.doOnNext(response -> {
System.out.println("응답 받음: " + response);
})
.doOnError(error -> {
System.out.println("에러 발생: " + error.getMessage());
error.printStackTrace();
});
}
private String encodeSecretKey() throws UnsupportedEncodingException {
Base64.Encoder encoder = Base64.getEncoder();
return "Basic " + Base64.getEncoder().encodeToString((secretKey + ":").getBytes());
}
위와 같이 보내면
404 Not Found from POST https://api.tosspayments.com/v1/payments/confirm
에러가 돌아옵니다. 혹시 어디가 잘못되었을까요?
25 Replies
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) :
- 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요.
* 주말/공휴일에는 답변이 늦을 수 있어요.
아 추가로
public class PaymentConfirmationRequest {
private String paymentKey;
private String orderId;
private int amount;
}
이렇게 구현되어 있습니다!
사용하신 주문번호 공유부탁드려요.
그런데 이상한 부분은 포스트맨으로
[POST] https://api.tosspayments.com/v1/payments/confirm
를 호출해보시면 404가 나올 수 없는데요.
코드 맨위에
https://api.tosspayments.com%22/ 이 부분이 잘못 된 것 같은데 주소 다시 확인 부탁드려요.
실제 승인 API가 어떻게 호출되었는지 로그를 찍어보시면 원인 찾으실 수 있을 것 같습니다.
앗 붙여넣기를 잘못 한 것 같습니다.
public PaymentService() {
this.webClient = WebClient.builder()
.baseUrl("https://api.tosspayments.com")
.defaultHeader("Content-Type", "application/json")
.build();
}
이렇게 되어있는데 한번 주문번호부터 다시 받아서 실행해보도록 하겠습니다.
따옴표가
public PaymentService() {
this.webClient = WebClient.builder()
.baseUrl("https://api.tosspayments.com")
.defaultHeader("Content-Type", "application/json")
.build();
}
이상하게 출력되네요
PaymentConfirmationRequest 에서 최종 생성된 requestJson 을 toString() 로 찍어서 알려주시면 됩니다
{
"paymentKey": "mvbBAMKdpoeqRGgYO1r5g4nwWxmdwo3QnN2Eyazx0596wLj4",
"orderId": "580e39ab-2181-4cce-9283-8c8a7a55118e",
"amount": 15000
}
이렇게 요청을 보냈는데 이번엔 400 Bad Request가 뜨네요
PaymentConfirmationRequest(paymentKey=mvbBAMKdpoeqRGgYO1r5g4nwWxmdwo3QnN2Eyazx0596wLj4, orderId=580e39ab-2181-4cce-9283-8c8a7a55118e, amount=15000)
clientkey와 secret 키를 다르게 넣으신것 같습니다.
두개가 같은 상점의 것이 맞는지 확인부탁드릴께요.
넵
가입한 계정의 상점 키를 동일하게 넣었습니다. 확인 완료했는데 이제 어느 부분을 확인하면 좋을까요?
다시 한 번 보내보겠습니다.
PaymentConfirmationRequest(paymentKey=d9ojO5qEvKma60RZblrqYgyowq4A25rwzYWBn14MXAPGg7pD, orderId=287a7b99-c5f6-4a41-912b-f576cea1b4c0, amount=15000)
이렇게 보냈는데 403이 뜹니다. 키 문제일까요?
이번에는 키문제가 아니고 전달 주신 값 문제네요
처음 결제요청은 25900 이었는데
승인 요청에 15000을 보내셨어요
넵 다시 해보겠습니다
{
"paymentKey": "01OAv2P6yqLlDJaYngro9mXmBQAK4v3ezGdRpXxKN7BQMEk4",
"orderId": "e2f068c5-830c-47d7-a0e4-42968a11815d",
"amount": 25900
}
이렇게 넣었습니다.
404 Not Found from POST https://api.tosspayments.com/v1/payments/confirm
라고 뜨네요! 키 문제일까요?
현재 프론트에서
orderId: makeUUID(),
orderName: payments.orderName,
customerName: user?.username,
successUrl:
${window.location.origin}/dashboard/payments/success
,
failUrl: ${window.location.origin}/dashboard/payments/fail
,
를 보내서 돌려받은 정보를 기반으로 백엔드로 포스트맨을 이용해 요청을 보내고 있습니다.Postman 에서 키를 보내신건가요?
키는 코드레벨에 들어있어서 : 를 추가해 인코딩하고 있습니다.
header 에 키를 base64로 인코딩 안하고 보내신것 같습니다.
포스트맨에서 보내실때도 인코딩하셔야 합니다.
@GetMapping("/confirm")
@Operation(summary = "결제 정보 인증")
public Mono<PaymentConfirmationResponseV2> confirmPayment(@RequestBody PaymentConfirmationRequest paymentConfirmationRequest) throws UnsupportedEncodingException {
return paymentService.confirmPayment(paymentConfirmationRequest);
}
이 부분으로 요청을 넣으면 정해진 엔드포인트로 인코딩된 키값이 넘어가도록 로직이 짜여있는데 잘못된 걸까요?
public PaymentService() {
this.webClient = WebClient.builder()
.baseUrl("https://api.tosspayments.com")
.defaultHeader("Content-Type", "application/json")
.build();
}
public Mono<PaymentConfirmationResponseV2> confirmPayment(PaymentConfirmationRequest paymentConfirmationRequest)
throws UnsupportedEncodingException {
System.out.println(paymentConfirmationRequest.toString());
String authorizations = encodeSecretKey();
String idempotencyKey = UUID.randomUUID().toString();
return webClient.post()
.uri("/v1/payments/confirm")
.header(HttpHeaders.AUTHORIZATION, authorizations)
.header("Idempotency-Key", idempotencyKey)
.body(Mono.just(paymentConfirmationRequest), PaymentConfirmationRequest.class)
.retrieve()
.bodyToMono(PaymentConfirmationResponseV2.class)
.doOnNext(response -> {
System.out.println("응답 받음: " + response);
})
.doOnError(error -> {
System.out.println("에러 발생: " + error.getMessage());
error.printStackTrace();
});
}
private String encodeSecretKey() throws UnsupportedEncodingException {
Base64.Encoder encoder = Base64.getEncoder();
return "Basic " + Base64.getEncoder().encodeToString((secretKey + ":").getBytes());
}
Basic dGVzdF9za19aT1J6ZE1hcU4zdzBCdmJwUEFnVjVBa1lYUUd3Og==
이렇게 인코딩 된 값이 실제로는 토스 엔드포인트로 넘어갑니다.
를 보내서 돌려받은 정보를 기반으로 백엔드로 포스트맨을 이용해 요청을 보내고 있습니다.이렇게 말씀해 주셨는데, 이때는 포스트맨으로 수동으로 보내신것 아닌가요? 13시 41분에 오류 난것을보면
content-type: application/json authorization: Bearer test_sk_ZORzdMaqN3w0BvbpPAgV5AkYXQGw user-agent: PostmanRuntime/7.32.3 accept: /
넵 해당 정보가
{
"paymentKey": "01OAv2P6yqLlDJaYngro9mXmBQAK4v3ezGdRpXxKN7BQMEk4",
"orderId": "e2f068c5-830c-47d7-a0e4-42968a11815d",
"amount": 25900
}
로 오는데, 포스트맨을 이용해 저희 서버로 요청을 보내고, 그 요청 안에서 키값을 이용해 인코딩을 해서 보내드립니다.
이렇게 요청 헤더가 들어왔습니다.
아 그때는 포스트맨으로 직ㅇ접 해보려고 했었어요!
기존에는 그렇게 하지 않고 방금 말씀드린 로직으로 진행했습니다.
그럼 다시 설명하신 로직으로 보내줘 보세요.
넵
paymentkey 부터 다시 받으셔야 합니다.
넵!
방금 새로 보냈습니다.
paymentkey 알려주세요.
냥과장님! 뭔진 모르지만 갑자기 해결되었습니다.
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.