ragyun.
ragyun.3w ago

brandpay.requestPayment

<script setup lang="ts">
import { loadTossPayments } from "@tosspayments/tosspayments-sdk"
const tossPayments = await loadTossPayments(tossBrandPayClientKey);
const brandpay = tossPayments.brandpay({
customerKey: mbId.value,
redirectUrl: window.location.origin + "/bridge/toss/brand-pay-auth", // 흐름상 auth가 맞음
});

onMounted(() => {
brandpay.requestPayment({
amount: {
currency: 'KRW',
value: req_price,
},
orderId: od_id,
orderName: product_name,
successUrl: window.location.origin + '/bridge/toss/brand-pay-success',
failUrl: window.location.origin + '/bridge/toss/brand-pay-fail',
customerEmail: email.value,
customerName: name.value,
// methodId: , // 결제수단의 ID - [https://docs.tosspayments.com/reference/brandpay#secretkey로-결제수단-조회]의 카드 정보
})
})
</script>
<script setup lang="ts">
import { loadTossPayments } from "@tosspayments/tosspayments-sdk"
const tossPayments = await loadTossPayments(tossBrandPayClientKey);
const brandpay = tossPayments.brandpay({
customerKey: mbId.value,
redirectUrl: window.location.origin + "/bridge/toss/brand-pay-auth", // 흐름상 auth가 맞음
});

onMounted(() => {
brandpay.requestPayment({
amount: {
currency: 'KRW',
value: req_price,
},
orderId: od_id,
orderName: product_name,
successUrl: window.location.origin + '/bridge/toss/brand-pay-success',
failUrl: window.location.origin + '/bridge/toss/brand-pay-fail',
customerEmail: email.value,
customerName: name.value,
// methodId: , // 결제수단의 ID - [https://docs.tosspayments.com/reference/brandpay#secretkey로-결제수단-조회]의 카드 정보
})
})
</script>
redirectUrl, successUrl, failUrl 해당 url위치의 페이지는 생성해 두었습니다. 처음 요청시에는 카드정보를 입력하는 창이 나왔었습니다. 그 후 카드정보를 입력했습니다. 그 뒤에 사진과 같은 타임아웃으로 오류가 나타나고 있고, 재 요청시에 카드정보창은 나오지 않고 해당 화면으로 이동합니다.
No description
71 Replies
토스페이먼츠 BOT
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) : - 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요. * 주말/공휴일에는 답변이 늦을 수 있어요.
이실장
이실장3w ago
redirectUrl에서 accessToken발급하는 api는 구현하셨을까요
ragyun.
ragyun.OP3w ago
redirectUrl에서 accessToken발급하는 api는 구현이 빠져있었습니다. 감사합니다. redirectUrl에서 accessToken발급하는 api는 구현을 하고 난 뒤 customerToken이 존재하지 않습니다. 라는 에러로 바뀌고 successUrl, failUrl 부분으로 넘어가지 못하고 있습니다. 토스페이먼츠 개발자센터에서 customerToken으로 검색했을 때 문서가 나오지 않아서 문의합니다.
No description
유부장
유부장3w ago
이건 accessToken 발급이 정상 구현되어 있지 않을때 보통 발생해요. 1) 상점관리자 - 개발자센터에서 브랜드페이 쪽에 redirectUrl 등록은 되어 있나요? 2) 결제요청하는 사이트 프로토콜 / 도메인과 redirectUrl 의 프로토콜 / 도메인은 동일 한가요?
ragyun.
ragyun.OP3w ago
const brandpay = tossPayments.brandpay({
customerKey: mbId.value,
redirectUrl: window.location.origin + "/bridge/toss/brand-pay-auth",
});
const brandpay = tossPayments.brandpay({
customerKey: mbId.value,
redirectUrl: window.location.origin + "/bridge/toss/brand-pay-auth",
});
로컬이라 http 프로토콜입니다. http://localhost:3000/ 으로 동일하게 요청했습니다.
No description
No description
유부장
유부장3w ago
처음 문의주실때는 이렇게 문의 주셨는데 redirectUrl: window.location.origin + "/bridge/toss/brand-pay-redirect" 로컬에서는 다르게 사용하고 있으신거 맞지요?
ragyun.
ragyun.OP3w ago
로컬도 brand-pay-auth로 변경했습니다. /bridge/toss/brand-pay-auth.vue 는 호출되면 저희 서버로 put요청을 바로 보내도록 구현했는데, 저희 서버에 요청된 내용이 없습니다. brand-pay-auth 페이지가 호출이 잘 되었는지를 확인할 수 있는 방법이 저희 서버에 요청이 오는 것 외에 다른 방법이 있을까요?
유부장
유부장3w ago
아 brand-pay-auth 에서 바로 호출되도록 구현하신게 아니라, 다른 루트에서 API 호출하도록 중간 프록시로 운영하시는 건가요? access log 라던가, 해당 루트에서의 동작 로그를 보셔야 할것 같아요.
ragyun.
ragyun.OP3w ago
로그를 넣었습니다.
유부장
유부장3w ago
중간 단계가 있으시면 해당 중간단계에서의 누락이 있으신지를 보세요 저희가 볼수 없는 부분이네요
ragyun.
ragyun.OP3w ago
brand-pay-auth는 프론트서버이고, brand-pay-auth페이지에서 백엔드서버로 호출했습니다
유부장
유부장3w ago
네, 제가 잘 이해한것 같으니 해당 서버에서 누락되는것 없는지를 봐주셔야 할것 같아요.
ragyun.
ragyun.OP3w ago
brandpay.requestPayment를 호출하는 페이지에서https://api.tosspayments.com/v1/brandpay/authorizations/customer-token?atms=17&customerKey=1f7252fb-2ec0-11ef-abab-000e1e9ab310 해당 요청을 30번 넘게 호출하고 마지막 요청에서 429 Too Many Requests에러를 받습니다
No description
Kimoon Lee
Kimoon Lee3w ago
window.location.origin + "/bridge/toss/brand-pay-auth", 이 위치를 호출하면 다른곳으로 redirect 해서 처리하시는건 아닌지 확인부탁드립니다.
ragyun.
ragyun.OP3w ago
window.location.origin + "/bridge/toss/brand-pay-auth" 이 위치를 호출하면 백엔드서버로 요청하지만, 다른 화면으로 넘어가는 부분은 없습니다.
<script setup lang="ts">
const { public: { apiBase } } = useRuntimeConfig();

definePageMeta({
layout: "authentication",
});
const router = useRouter();
const route = useRoute();

const code = route.query.code;
const customerKey = route.query.customerKey;

onMounted(async () => {
console.log(code, customerKey);
const { data, status, error } = await useFetch(
`${apiBase}/api/v1/user/goods/auth`,
{
method: "put",
headers: { "Content-Type": "application/json" },
body: {
code: code,
customer_key: customerKey,
},
}
);
});
</script>
<script setup lang="ts">
const { public: { apiBase } } = useRuntimeConfig();

definePageMeta({
layout: "authentication",
});
const router = useRouter();
const route = useRoute();

const code = route.query.code;
const customerKey = route.query.customerKey;

onMounted(async () => {
console.log(code, customerKey);
const { data, status, error } = await useFetch(
`${apiBase}/api/v1/user/goods/auth`,
{
method: "put",
headers: { "Content-Type": "application/json" },
body: {
code: code,
customer_key: customerKey,
},
}
);
});
</script>
window.location.origin + "/bridge/toss/brand-pay-auth"의 화면구성은 없이 해당 코드처럼 되어 있습니다.
Kimoon Lee
Kimoon Lee3w ago
저희 쪽에서 window.location.origin + "/bridge/toss/brand-pay-auth" 으로 redirect 를 해드린이후에 토큰 발급 API 호출된 내역이 없습니다. window.location.origin + "/bridge/toss/brand-pay-auth" 에서 저희가 보낸 값을 잘 받으셨는지 확인해 보셔야 할것 같아요.
ragyun.
ragyun.OP3w ago
brand-pay-request 페이지에서 sdk통해 brandpay.requestPayment를 호출하면 화면이 토스에서 제공해주는 화면으로 이동하는데, 그 후에는 brand-pay-auth로 화면 이동이 없습니다. 그래서 window.location.origin + "/bridge/toss/brand-pay-auth" 에서 보내주는 값을 확인하는 로그가 작동하지 않습니다.
No description
Kimoon Lee
Kimoon Lee3w ago
이화면 뜰때 네트워크 탭에서 timeout 발생하는 요청이 있는지 확인해 주실수 있나요?
ragyun.
ragyun.OP3w ago
네트워크에서 타임아웃이 발생하는 요청은 없고 https://api.tosspayments.com/v1/brandpay/authorizations/customer-token?atms=16&customerKey=1f7252fb-2ec0-11ef-abab-000e1e9ab310 해당 요청에서 429 Too Many Requests를 받습니다. 콘솔에서는 해당 오류가 2번 나옵니다. _app-0d50b42af6d76916.js:96 Uncaught (in promise) rB: [BRIDGE] Request Timeout. id: _gEfos_A6JLp8BF6dNfpf, type: TOSSPAYMENTS__REQUEST_RESPONSE, body: {"step":"TOSSPAYMENTS__REQUEST","requestName":"GET_PARAMETER","payload":{"name":"customerToken"}} rB: [BRIDGE] Request Timeout. id: _gEfos_A6JLp8BF6dNfpf, type: TOSSPAYMENTS__REQUEST_RESPONSE, body: {"step":"TOSSPAYMENTS__REQUEST","requestName":"GET_PARAMETER","payload":{"name":"customerToken"}}
Kimoon Lee
Kimoon Lee3w ago
에러 발생하는 상황에 har 파일 받아서 공유 부탁드립니다.
Kimoon Lee
Kimoon Lee3w ago
tosspublic on Notion
📘 HAR 파일 저장 가이드 | Notion
웹 페이지의 네트워크 활동을 기록하려면, 브라우저의 개발자 도구(DevTools) 의 네트워크(Network) 탭을 사용하여 .har 파일을 저장할 수 있습니다.
이실장
이실장3w ago
파일은 확인하고 삭제했습니다.
이실장
이실장3w ago
@ragyun. 저희가 redirectUrl을 호출했는데요. http://localhost:3000/bridge/toss/brand-pay-auth?code=exMgkW36yYnjz2EAEp8GbR5o&customerKey=1f7252fb-2ec0-11ef-abab-000e1e9ab310 호출후에 token발급(https://docs.tosspayments.com/reference/brandpay#access-token-발급)을 기다리면서 계속PENDING을 돌고 있씁니다. 그런데 끝내 token발급요청이 안와서 pending돌다가 too many request로 429에러가 내려간거에요
브랜드페이 API | 토스페이먼츠 개발자센터
브랜드페이에서 제공하는 API 엔드포인트(Endpoint)와 객체 정보, 파라미터, 요청 및 응답 예제를 살펴보세요.
ragyun.
ragyun.OP3w ago
http://localhost:3000/bridge/toss/brand-pay-auth?code=exMgkW36yYnjz2EAEp8GbR5o&customerKey=1f7252fb-2ec0-11ef-abab-000e1e9ab310 페이지를 임의로 호출하면 저희 서버에 요청이 전달되고 토스로 access-token-발급요청을 보내고 있습니다. 하지만 sdk로 brandpay.requestPayment를 호출 한 이후에는 http://localhost:3000/bridge/toss/brand-pay-auth페이지를 통한 저희 서버로의 응답이 없습니다. 임의로 페이지를 여는 경우에는 해당 요청이 정상적으로 들어오고 있습니다.
Kimoon Lee
Kimoon Lee3w ago
http://localhost:3000/bridge/toss/brand-pay-auth?code=exMgkW36yYnjz2EAEp8GbR5o&customerKey=1f7252fb-2ec0-11ef-abab-000e1e9ab310 이걸 호출하면 페이지 이동 없이 바로 해당 페이지에서 access-token-발급 요청을 하시는 거죠? http://localhost:3000/bridge/toss/brand-pay-auth 의 접근로그를 확인해 보실수 있을까요?
ragyun.
ragyun.OP3w ago
brand-pay-auth 에서 네트워크 오류입니다. 저희 시큐리티는 통과하고, access-token-발급때 나온 에러 메세지 입니다. 네
Kimoon Lee
Kimoon Lee3w ago
보내주신 har 파일에 http://localhost:3000/bridge/toss/brand-pay-auth 이걸 호출한 로그가 없는데요. http://localhost:8080/api/v1/user/goods/auth 이거는 언제 호출하시는 건가요?
ragyun.
ragyun.OP3w ago
http://localhost:3000/bridge/toss/brand-pay-auth 이 페이지로 들어오면, 백엔드서버로 http://localhost:8080/api/v1/user/goods/auth 요청을 보냅니다
Kimoon Lee
Kimoon Lee3w ago
그럼 http://localhost:8080/api/v1/user/goods/auth 에서 토큰 발행 요청한 로그는 확인되시나요?
ragyun.
ragyun.OP3w ago
아니요 sdk로 호출한 경우 http://localhost:8080/api/v1/user/goods/auth 서버를 접근하는 요청이 없습니다 그래서 http://localhost:3000/bridge/toss/brand-pay-auth 이곳으로 접근을 하는지 확인이 안되고 있습니다
ragyun.
ragyun.OP3w ago
네 비슷합니다.(nuxt3 useFetch 사용중)
Kimoon Lee
Kimoon Lee3w ago
그러면 저희가 iframe 내에서 http://localhost:3000/bridge/toss/brand-pay-auth 이걸 호출했을거라 CORS 에 걸렸을거 같습니다. 혹시 동일 포트로 사용 가능하신가요?
ragyun.
ragyun.OP3w ago
그럼 프론트서버에서 access-token-발급을 호출해야 할까요? 동일 포트로 하려면 프론트에서 해야합니다
Kimoon Lee
Kimoon Lee3w ago
프론트에서 서버사이드 스크립트를 이용해서 호출해 주셔야 합니다.
ragyun.
ragyun.OP3w ago
네 이해했습니다.
Kimoon Lee
Kimoon Lee3w ago
AJAX 로 보내면 secretkey 가 FE 에 노출되어서 안되구요.
ragyun.
ragyun.OP3w ago
그럼 어떻게 하나요?
Kimoon Lee
Kimoon Lee3w ago
http://localhost:3000/bridge/toss/brand-pay-auth 에서 서버 사이드로 호출하셔야 합니다.
ragyun.
ragyun.OP3w ago
ci 고객의 연계정보는 무엇을 넣어주면 되나요?
No description
Kimoon Lee
Kimoon Lee3w ago
고객의 CI 가 있다면 보내주시면 되고 없다면 null 로 보내시면 됩니다.
ragyun.
ragyun.OP3w ago
토스페이먼츠에서 어디 객체를 보면 ci 값을 알 수 있나요?
Kimoon Lee
Kimoon Lee3w ago
저희가 드리는 값이 아니에요.
ragyun.
ragyun.OP3w ago
http://localhost:3000/bridge/toss/brand-pay-auth 페이지로 접근하면 먼저 저희 백엔드서버로 고객의 토스페이먼츠 토큰이 있는지 확인합니다.(http://localhost:8080/api/v1/user/goods/auth) 그 후 https://api.tosspayments.com/v1/brandpay/authorizations/access-token 를 요청하도록 수정했습니다. 그래도 429 에러로 떨어집니다 customerKey를 넣으면 되는 것인지 아니라면 무엇을 넣어야 하는지 알려주시면 감사합니다
Kimoon Lee
Kimoon Lee3w ago
저희가 http://localhost:3000/bridge/toss/brand-pay-auth 로 보내드릴때 customerkey 를 보내드립니다. 지금 에러는 customerkey 를 안보내주셔서 발생한 에러네요.
ragyun.
ragyun.OP3w ago
페이로드에 보시면 customerKey를 보내고 있습니다.
Kimoon Lee
Kimoon Lee3w ago
지금은 authorization: Bearer dGVzd 이렇게 Bearer 로 보내고 계십니다. Basic 으로 보내주세요.
ragyun.
ragyun.OP3w ago
Basic으로 수정하고 오류가 달라져서 sdk로 호출했지만 429 Too Many Requests로 떨어집니다 ㅠ
Kimoon Lee
Kimoon Lee3w ago
uI 새로 열어서 해주세요. code 값이 expired 되었습니다. 그리고 https://api.tosspayments.com/v1/brandpay/authorizations/access-token 에서 에러 받으셨을때 응답 body 를 보시면 무슨 에러인지 보입니다.
ragyun.
ragyun.OP3w ago
방금 보낸 har는 페이지를 임의로 열어서 본거에요
Kimoon Lee
Kimoon Lee3w ago
네 그러신것 같아서요. 임의로 열어서 하지 마시고 UI 열어서 해주세요. 이렇게 에러 보이실거에요
Kimoon Lee
Kimoon Lee3w ago
No description
ragyun.
ragyun.OP3w ago
sdk로는 제가 네트워크에서 보이지 않습니다
Kimoon Lee
Kimoon Lee3w ago
그럼 이제 UI 열어서 해보시기 바랍니다. http://localhost:8080/api/v1/user/goods/auth 로 호출 들어가는지 로그 확인해 보시구요.
ragyun.
ragyun.OP3w ago
이 네트워크 정보가 sdk에서 brandpay.requestPayment를 열어서 볼 수 있는 네트워크입니다
ragyun.
ragyun.OP3w ago
호출이 오지 않습니다... 저도 오면 응답 부분 확인해서 에러코드 확인 가능합니다...
Kimoon Lee
Kimoon Lee3w ago
저희가 호출한건 보이네요.
Kimoon Lee
Kimoon Lee3w ago
No description
Kimoon Lee
Kimoon Lee3w ago
No description
Kimoon Lee
Kimoon Lee3w ago
여기가 CORS 때문에 호출이 안된것으로 보입니다. 이부분을 해결해 주셔야 해요. JS 콘솔에 보면 관련 에러 있으실겁니다.
ragyun.
ragyun.OP3w ago
네 확인 감사합니다
토스페이먼츠 BOT
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.
ragyun.
ragyun.OP2w ago
/bridge/toss/brand-pay-auth 에서 백엔드 서버로 보내고 있던 요청을 제거하고 아래 코드와 같이 access-token api 불러도 반응이 이전과 같습니다.
const route = useRoute();
const code = route.query.code;
const customerKey = route.query.customerKey;
onMounted(async () => {
const grantType = 'AuthorizationCode';
const refreshToken = '';

const { data: auth } = await useFetch(
console.log(code, customerKey);
`${tossBaseUrl}/v1/brandpay/authorizations/access-token`,
{
method: "POST",
headers: {
authorization: "Basic " + tossBrandPaySecretBase64,
"Content-Type": "application/json"
},
body: {
code: code,
customerKey: customerKey,
grantType: grantType,
// refreshToken: refreshToken,
}
}
)
});
const route = useRoute();
const code = route.query.code;
const customerKey = route.query.customerKey;
onMounted(async () => {
const grantType = 'AuthorizationCode';
const refreshToken = '';

const { data: auth } = await useFetch(
console.log(code, customerKey);
`${tossBaseUrl}/v1/brandpay/authorizations/access-token`,
{
method: "POST",
headers: {
authorization: "Basic " + tossBrandPaySecretBase64,
"Content-Type": "application/json"
},
body: {
code: code,
customerKey: customerKey,
grantType: grantType,
// refreshToken: refreshToken,
}
}
)
});
sdk에서 redirectUrl로 저희 서버에 보낼 때 cros가 나타나는 것인가요? 다른 분들이 이런 에러로 문의할 때엔 어떻게 처리가 되었는지도 궁금합니다.
ragyun.
ragyun.OP2w ago
/bridge/toss/brand-pay-auth 를 호출한 결과가 200으로 보입니다. 또한 console.log(code, customerKey); 로그도 보이지 않고 있습니다.
Kimoon Lee
Kimoon Lee2w ago
/bridge/toss/brand-pay-auth 를 호출한 결과가 200 이라면 말씀하신 코드가 정상적으로 실행되지 않은겁니다. 왜 실행이 안되었는지는 저희가 알수가 없는데요. 지금 호출 응답이 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"> <title>니짐내짐 LOCAL</title> <script type="text/javascript" src="https://buttons.github.io/buttons.js" async> 이렇게 나오는데 원하신 내용이 맞으신가요?
ragyun.
ragyun.OP2w ago
vue페이지가 아니라 /server/api/brand-pay-auth.ts를 만들고 http://localhost:3000/api/brand-pay-auth 를 보도록 수정하니 됩니다.
ragyun.
ragyun.OP2w ago
그래서 토큰을 발급받아 저장까지 성공적인데, https://api.tosspayments.com/v1/brandpay/authorizations/customer-token?atms=209&customerKey=289ac81b-2ec0-11ef-abab-000e1e9ab310 이 호출을 계속해서 부르고 결제창이 나오지 않는 현상이 나타나고 있습니다.
ragyun.
ragyun.OP2w ago
// 3. Toss API 호출
const response:iResAccessToken = await $fetch(`${tossBaseUrl}/v1/brandpay/authorizations/access-token`, {
method: 'POST',
headers: {
authorization: "Basic " + tossBrandPaySecretBase64,
"Content-Type": "application/json"
},
body: {
code: code,
customerKey: customerKey,
grantType: grantType,
refreshToken: refreshToken,
},
});

// 4. 엑세스 토큰 저장
console.log('response', response);
// 3. Toss API 호출
const response:iResAccessToken = await $fetch(`${tossBaseUrl}/v1/brandpay/authorizations/access-token`, {
method: 'POST',
headers: {
authorization: "Basic " + tossBrandPaySecretBase64,
"Content-Type": "application/json"
},
body: {
code: code,
customerKey: customerKey,
grantType: grantType,
refreshToken: refreshToken,
},
});

// 4. 엑세스 토큰 저장
console.log('response', response);
엑세스 토큰을 조회하는 로그도 잘 보이고 있습니다. 그래도 /v1/brandpay/authorizations/customer-token을 계속해서 PENDING을 보내주고 있습니다
Kimoon Lee
Kimoon Lee2w ago
토큰 요청하시는 키가 ngym82qs3y 이상점의 키로 요청하시는 것 같아요. 키를 cp_ 로 시작하는 MID 의 키로 변경해서 해보세요.
ragyun.
ragyun.OP2w ago
customerKey를 새로운 키로 하면 본인인증창이 나오고 successUrl로 반환이 됩니다. 하지만 본인인증을 마친 customerKey로 다시 결제창 호출 시 /v1/brandpay/authorizations/customer-token을 계속해서 PENDING상태로 나옵니다. 결제 승인 시 mid cp_ngymz55dhx 의 api key를 사용중이고 paymentKey=tcp_n20250430081316HcT31, amount=400, odId=20250430081212538139 의 결제 승인 결과 FORBIDDEN_REQUEST[허용되지 않은 요청입니다.] 에러가 나타나고 있는 것도 같이 확인해주시면 감사합니다 이건 /v1/brandpay/authorizations/access-token 호출 시 grantType을 기존 토큰의 RefreshToken로 할 때 나타나고 있는 현상이였습니다. 무조건 AuthorizationCode으로 요청하니 잘 넘어가집니다. 결제승인 시 허용되지 않은 요청입니다. 부분을 확인해주시면 감사합니다. base64에서 오타가 있던거 같습니다. 잘 되네요 확인감사합니다
이실장
이실장2w ago
감사합니다.

Did you find this page helpful?