안녕하세요. paymentMethodWidget.destroy() 관련질문입니다.
서비스 상 widget 에 필요한 결제방법을 셋팅하여 variantKey 로 호출할 예정입니다.
그러다보니 위젯 초기화를 해야하는데요. 관련 정보가 그냥 await paymentMethodWidget.destroy(); 를 호출하세요. 인데 어디서 호출해야할지 모르겠습니다.
사용하고자 하는 방법 (https://docs.tosspayments.com/guides/v2/payment-widget/integration 에 있는 예제 기준입니다.
예제에서 await Promise.all 부분만 await widgets.renderPaymentMethods 로 변경하여 호출하였습니다.
또한 클릭시 렌더링 할 목적으로 main() 은 클릭시 호출하게만 셋팅했습니다.
[결제1] 클릭 시
selector: "#payment-method" 에 variantKey: "DEFAULT" 를 출력
[결제2] 클릭 시
해당 위젯을 destroy 시키고 varianKey : "Card" 에 해당하는 위젯을 출력
[결제3] 클릭 시
위젯을 destroy 시킴
입니다.
await paymentMethodWidget.destroy(); 해당 부분을 어디에 적용해야할까요?
연동하기 | 토스페이먼츠 개발자센터
토스페이먼츠의 간편한 결제 연동 과정을 한눈에 볼 수 있습니다. 각 단계별 설명과 함께 달라지는 UI와 코드를 확인해보세요.
12 Replies
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) :
- 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요.
* 주말/공휴일에는 답변이 늦을 수 있어요.
테스트중인 소스는
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<script src="https://js.tosspayments.com/v2/standard"></script>
</head>
<body>
<!-- 할인 쿠폰 -->
<div>
<input type="checkbox" id="coupon-box" />
</div>
<!-- 결제 UI -->
<div id="payment-method"></div>
<!-- 이용약관 UI -->
<div id="agreement"></div>
<!-- 결제하기 버튼 -->
<button class="button" id="payment-button1" style="margin-top: 30px" onclick="main('a')">결제1</button>
<button class="button" id="payment-button2" style="margin-top: 30px" onclick="main('b')">결제2</button>
<button class="button" id="payment-button3" style="margin-top: 30px" onclick="main('c')">결제3</button>
<button class="button" id="payment-button" style="margin-top: 30px">결제하기</button>
<script>
async function main(types) {
const button = document.getElementById("payment-button");
//const coupon = document.getElementById("coupon-box");
// ------ 결제위젯 초기화 ------
const clientKey = "test_gck_docs_Ovk5rk1EwkEbP0W43n07xlzm";
const tossPayments = TossPayments(clientKey);
// 회원 결제
const customerKey = "yweedGtWvQsHZAngB0FZO";
const widgets = tossPayments.widgets({
customerKey,
});
// 비회원 결제
// const widgets = tossPayments.widgets({ customerKey: TossPayments.ANONYMOUS });
// ------ 주문의 결제 금액 설정 ------
await widgets.setAmount({
currency: "KRW",
value: 50000,
});
switch (types) {
case "a" :
varKey = 'DEFAULT';
break;
case "b" :
varKey = 'DEFAULT';
break;
case "c" :
varKey = 'DEFAULT';
break;
default :
varKey = 'DEFAULT';
break;
}
await Promise.all([
// ------ 결제 UI 렌더링 ------
widgets.renderPaymentMethods({
selector: "#payment-method",
variantKey: varKey,
}),
// ------ 이용약관 UI 렌더링 ------
//widgets.renderAgreement({ selector: "#agreement", variantKey: "AGREEMENT" }),
]);
// ------ '결제하기' 버튼 누르면 결제창 띄우기 ------
button.addEventListener("click", async function () {
await widgets.requestPayment({
orderId: "lxBb47kc8Xbyq8k8ikuDQ",
orderName: "토스 티셔츠 외 2건",
successUrl: window.location.origin + "/success.html",
failUrl: window.location.origin + "/fail.html",
customerEmail: "customer123@gmail.com",
customerName: "김토스",
customerMobilePhone: "01012341234",
});
});
}
</script>
</body>
</html>
위젯 초기화 -> tossPayments.widgets 함수입니다.
연동 잘하신거 같아요.
만약 renderPaymentMethods 이후에 types가 바뀐다면,
바뀌는 즉시에 destroy 호출을 하시고. 다시 renderPaymentMethods를 하시면 돼요.
중요한 점은 위젯 초기화 (tossPayments.widgets)가 여러번 호출되거나 destory 없이 renderPaymentMethods가 여려반 호출되면 안됩니다.
main('a'), b, c 형식으로 호출하면 안되고
네 그건 딱 한번은 되는데
이후부터는 하면 절대 안됩니다
그럼 위의 소스처럼 구현하려고 하면 어떤식의 방법이 좋을까요? render 쪽을 외부로 빼서 따로 호출해야할까요? 아니면 위젯이 있는지 판단해서
내부에서 destroy 와 render 호출하는게 맞을까요?
그건 연동하시기 나름이에요
토스에 혹시 위젯이 렌더링 되어있는지 확인하는 함수나 명령어 제공되는게 있을까요?
renderPaymentMethods를 변수로 저장하셔야 하는데
이 값이 렌더되면 안에 객체가 있구요
렌더 이전 혹은 destroy 이후면 undefined입니다
좀 꼬이고 있긴 한데 알려주신 방법으로 진행해보도록 하겠습니다 🙂 답변 감사드립니다
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.
그리고 혹시 소스 분리를 해서 현재 페이지 로딩시에
var paymentMethodWidget;
const button = document.getElementById("payment-button");
//const coupon = document.getElementById("coupon-box");
// ------ 결제위젯 초기화 ------
//const clientKey = "test_gck_docs_Ovk5rk1EwkEbP0W43n07xlzm";
const clientKey = "test_gck_Z61JOxRQVEB5M2aZlxLwrW0X9bAq";
const tossPayments = TossPayments(clientKey);
// 회원 결제
const customerKey = "yweedGtWvQsHZAngB0FZO";
const widgets = tossPayments.widgets({
customerKey,
});
위젯 로딩시켜둔 상태에서
async function main(types) {
console.log(paymentMethodWidget);
if (typeof paymentMethodWidget == 'undefined') {
console.log('O');
} else {
console.log('X');
await paymentMethodWidget.destroy();
}
형식으로 destroy 를 시키고 있는데요. 로딩은 정상적으로 되고 있는데
button.addEventListener("click", async function () {
시에 "uncaught (in promise) r: 이미 다른 요청을 수행하고 있어요." 라는 메세지가 나온 후에
호출은 정상적으로 되는것 같습니다. 혹시 저 메세지는 무시해도 되는지
아닙니다. 제가 실수한거네요 ^^;
button.addEventListener 로 로딩시로 변경하고 소스 수정했습니다 🙂