춤추는망고
춤추는망고7mo ago

특정 상황에서 `@tosspayments/payment-sdk` 가 이상하게 동작합니다.

import { useEffect } from "react";

import { loadTossPayments } from "@tosspayments/payment-sdk";

import { PageProps } from "pages/_app";

const PaymentPage = ({ router }: PageProps) => {
if (!router.isReady) return;

const {
phase,
amount,
orderId,
orderName,
onSuccess,
onFailure,
paymentKey,
errorCode,
errorMessage,
} = router.query as PaymentPageQuery;

useEffect(() => {
switch (phase) {
case "init":
const { origin, pathname, search } = window.location;
const query = new URLSearchParams(search);
query.delete("orderId");
query.delete("amount");
loadTossPayments(process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY).then(({ requestPayment }) =>
requestPayment("카드", {
amount: Number(amount),
orderId,
orderName,
successUrl: origin + pathname.replace("init", "success") + "?" + query,
failUrl: origin + pathname.replace("init", "failure") + "?" + query,
}).catch((error) => {
console.error(error);
alert("결제를 취소합니다.");
window.history.go(-2);
}),
);
return;
case "success":
router.push({ pathname: onSuccess, query: { ...router.query, paymentId: paymentKey } });
return;
case "failure":
router.push({ pathname: onFailure, query: { ...router.query, errorCode, errorMessage } });
return;
}
}, []);

return null;
};
import { useEffect } from "react";

import { loadTossPayments } from "@tosspayments/payment-sdk";

import { PageProps } from "pages/_app";

const PaymentPage = ({ router }: PageProps) => {
if (!router.isReady) return;

const {
phase,
amount,
orderId,
orderName,
onSuccess,
onFailure,
paymentKey,
errorCode,
errorMessage,
} = router.query as PaymentPageQuery;

useEffect(() => {
switch (phase) {
case "init":
const { origin, pathname, search } = window.location;
const query = new URLSearchParams(search);
query.delete("orderId");
query.delete("amount");
loadTossPayments(process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY).then(({ requestPayment }) =>
requestPayment("카드", {
amount: Number(amount),
orderId,
orderName,
successUrl: origin + pathname.replace("init", "success") + "?" + query,
failUrl: origin + pathname.replace("init", "failure") + "?" + query,
}).catch((error) => {
console.error(error);
alert("결제를 취소합니다.");
window.history.go(-2);
}),
);
return;
case "success":
router.push({ pathname: onSuccess, query: { ...router.query, paymentId: paymentKey } });
return;
case "failure":
router.push({ pathname: onFailure, query: { ...router.query, errorCode, errorMessage } });
return;
}
}, []);

return null;
};
고객이 결제 페이지에 진입하자마자 "결제를 취소합니다" 문구가 표시된 dialog 를 보게 된다고 합니다. amount 도 양수이고, order_id 와 order_name의 길이/구성 제한도 지켰고, success_url 과 failure_url 도 정상입니다. 제가 직접 브라우저(Windows, MacOS, iOS, Android), 앱(flutter 웹뷰 iOS/Android) 으로 테스트할 때에도 전혀 문제가 없었습니다. 혹시 브라우저 버젼에 따라, requestPayment() 메서드 실행 자체에 실패하는 경우도 있나요?
16 Replies
토스페이먼츠 BOT
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) : - 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요. * 주말/공휴일에는 답변이 늦을 수 있어요.
춤추는망고
춤추는망고OP7mo ago
문제 발생 고객의 user agent 입니다. Mozilla/5.0 (Linux; Android 10; SM-G965N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/126.0.6478.134 Mobile Safari/537.36 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
유부장
유부장7mo ago
결제를 취소합니다는 아래 부분 구현해두신 것 때문인것 같아요 catch((error) => { console.error(error); alert("결제를 취소합니다."); window.history.go(-2);
춤추는망고
춤추는망고OP7mo ago
네, 맞아요. '결제를 취소합니다' 메시지가 표시되는건 저 부분 때문인데, 다른 환경에서는 전부 정상 동작하는데 특정 상황에서만 저 구문이 동작하는 상황이거든요.. 고객이 직접 취소를 누르거나 일반결제에 실패하는 경우를 제외하고, requestPayment() 실행 중에 예외가 발생하는 경우가 있는지 알고 싶어서요. 저희 고객센터로 문의가 왔는데, 결제 페이지에 들어가자 마자 저 경고 문구가 표시된다고 하시더라구요;
유부장
유부장7mo ago
저기에서 구현 한 대로, 해당 단계에서 erro catch 가 되는 모든 상황이 해당 됩니다. 그 모든 상황 설명은 어려울것 같아요 상황 발생한 주문번호 주시면, 무슨 케이스 였는지는 봐드릴 수 있을것 같아요.
춤추는망고
춤추는망고OP7mo ago
sdk 호출 시에 사용한 order ID 공유드리면 될까요??
유부장
유부장7mo ago
네네
춤추는망고
춤추는망고OP7mo ago
시도를 조금 많이 하셔서..;; 이 중에 하나로 확인해주시면 될 거 같아요.
'client-advice-11999-1092-1721213540517'
'client-advice-11999-938-1721348697433'
'client-advice-11999-938-1721363310145'
'client-advice-11999-938-1721213423244'
'client-advice-11999-938-1721362514344'
'client-advice-11999-938-1721363341779'
'client-advice-11999-938-1721213092254'
'client-advice-11999-938-1721213453698'
'client-advice-11999-1092-1721348837741'
'client-advice-11999-938-1721349064815'
'client-advice-11999-194-1721213772850'
'client-advice-11999-938-1721362316765'
'client-advice-11999-938-1721362274497'
'client-advice-11999-938-1721213083684'
'client-advice-11999-194-1721349112783'
'client-advice-11999-938-1721363320075'
'client-advice-11999-194-1721213738607'
'client-advice-11999-1092-1721348844407'
'client-advice-11999-194-1721348855713'
'client-advice-11999-938-1721213099117'
'client-advice-11999-938-1721213523918'
'client-advice-11999-938-1721348707281'
'client-advice-11999-194-1721213743503'
'client-advice-11999-1317-1721213534451'
'client-advice-11999-1092-1721348832423'
'client-advice-11999-938-1721213437353'
'client-advice-11999-938-1721213202234'
'client-advice-11999-1227-1721213545783'
'client-advice-11999-938-1721213441943'
'client-advice-11999-938-1721362332638'
'client-advice-11999-938-1721213432478'
'client-advice-11999-938-1721213527380'
'client-advice-11999-1092-1721213540517'
'client-advice-11999-938-1721348697433'
'client-advice-11999-938-1721363310145'
'client-advice-11999-938-1721213423244'
'client-advice-11999-938-1721362514344'
'client-advice-11999-938-1721363341779'
'client-advice-11999-938-1721213092254'
'client-advice-11999-938-1721213453698'
'client-advice-11999-1092-1721348837741'
'client-advice-11999-938-1721349064815'
'client-advice-11999-194-1721213772850'
'client-advice-11999-938-1721362316765'
'client-advice-11999-938-1721362274497'
'client-advice-11999-938-1721213083684'
'client-advice-11999-194-1721349112783'
'client-advice-11999-938-1721363320075'
'client-advice-11999-194-1721213738607'
'client-advice-11999-1092-1721348844407'
'client-advice-11999-194-1721348855713'
'client-advice-11999-938-1721213099117'
'client-advice-11999-938-1721213523918'
'client-advice-11999-938-1721348707281'
'client-advice-11999-194-1721213743503'
'client-advice-11999-1317-1721213534451'
'client-advice-11999-1092-1721348832423'
'client-advice-11999-938-1721213437353'
'client-advice-11999-938-1721213202234'
'client-advice-11999-1227-1721213545783'
'client-advice-11999-938-1721213441943'
'client-advice-11999-938-1721362332638'
'client-advice-11999-938-1721213432478'
'client-advice-11999-938-1721213527380'
유부장
유부장7mo ago
"특정 사용자" 에요?
춤추는망고
춤추는망고OP7mo ago
네 해당 사용자가 결제 시도를 여러 번 했고, 모두 같은 현상이 발생한 경우에요..
유부장
유부장7mo ago
결제요청할때 successUrl, failUrl 에 파람 붙여서 보내는 것 같은데, title 을 줄여서 보낼 수 있나요? 이분이 상담 title 내용이 좀 많이 기신것 같은데요 title content
춤추는망고
춤추는망고OP7mo ago
아아.. params 내용이 너무 길어서 그런건가요?
유부장
유부장7mo ago
내용이 너무 길면 저희 서버 쪽 처리에도 이슈가 있어서요. 긴 내용은 되도록 세션이나 내부 DB 에서 처리하시고 successUrl 등 에 붙이는 쿼리 파람은 꼭 필요한 내용만 보내주시면 좋을것 같아요 .
춤추는망고
춤추는망고OP7mo ago
아아.. 모바일 앱(웹뷰)에서 결제 페이지를 경유하면 기존 사용자 입력이 유실되어서 params 로 넣어서 보낸 거였는데.. 다른 방법을 찾아보겠슴다.. 감사합니다!
토스페이먼츠 BOT
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.

Did you find this page helpful?