제이
제이3y ago

결제 창 진행 CROS 문제

안녕하세요? 아마 방법이 없을 듯 한데 어떻게든 방법을 찾아 주시지 않을까 하여 문의 남깁니다. 간단하겐 CROS문제 입니다. 현재 사이트가 frameset에 감싸져 있고 이 상태에서 PG 호출 형태를 iframe 형태로 하고 있습니다. 창은 무난하게 뜨지만, 진행 과정에서 아래와 같은 문구가 발생하여 진행되지 않습니다. Unsafe attempt to initiate navigation for frame with origin 'https://test.com' from frame with URL 'https://api.tosspayments.com/proxy/pages/setup/test_ck_'. The frame attempting navigation is neither same-origin with the target, nor is it the target's parent or opener. Uncaught DOMException: Failed to set the 'href' property on 'Location': The current window does not have permission to navigate the target frame to 'https://test.com/success.asp'. 필수 정보는 제거 후 올린 것이지만 어떤 상태인지는 아실 거라 생각합니다. 여러가지 시도해본 결과 해결하는 방법으로는 감싸진 프레임 밖으로 URL을 노출 시켜 진행하는 방법이 있고 iframe 호출 대신 self로 호출하는 방법이 있습니다. 하지만 프레임에 감싸진 상태로 iframe 호출하는 방법이 있으면 좋겠어서 문의 드립니다. 위 두 가지 방법이 전부일까요? 도와주세요
33 Replies
토스페이먼츠 BOT
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) : - 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요. * 주말/공휴일에는 답변이 늦을 수 있어요.
이실장
이실장3y ago
카드 인증 완료후 successUrl로 이동하지 않고, Promise방식으로 응답받을 수 있도록 개선된 버전이 내일 배포예정입니다. Promise 방식을 사용하시게 되면, 문제가 없을 것으로 보입니다. 다만 Promise는 PC에서만 사용가능하기에 모바일/PC를 분기처리해주셔야합니다. (모바일에서는 카드사 창으로 redirect되기 때문에 Promise사용 불가(
제이
제이OP3y ago
역시!!!! 내일을 기대하겠습니다.
이실장
이실장3y ago
현재 <script src="https://js.tosspayments.com/v1/payment"></script>으로는 해당 기능 사용 가능합니다. npm 패키지 사용시 오늘 중 배포완료됩니다.
토스페이먼츠 BOT
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.
제이
제이OP3y ago
수고 많으셨습니다! <script src="https://js.tosspayments.com/v1"></script> 대신 <script src="https://js.tosspayments.com/v1/payment"></script>을 사용한다면 문제 없을까요? javascript 방식으로 successUrl 보내는 데신 Promise을 사용하는 방법의 가이드가 있을까요?
이실장
이실장3y ago
[예시]
tosspayments.requestPayment('카드', {
orderId: 202212121811,
amount: 100,
orderName: '테스트 주문',
customerName: '테스터',
}).then(result => {
console.log('success', result);
}).catch(error => {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
} else if (error.code === 'INVALID_CARD_COMPANY') {
// 유효하지 않은 카드 코드에 대한 에러 처리
}
});
tosspayments.requestPayment('카드', {
orderId: 202212121811,
amount: 100,
orderName: '테스트 주문',
customerName: '테스터',
}).then(result => {
console.log('success', result);
}).catch(error => {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
} else if (error.code === 'INVALID_CARD_COMPANY') {
// 유효하지 않은 카드 코드에 대한 에러 처리
}
});
- success/failUrl은 지정하지 말아주세요. - Promise방식 사용을 위해서는 아래 내용을 참고해주시면 됩니다. - 기존처럼 successUrl로 redirect되지 않습니다. (CORS 문제 ❌) - 동일한 페이지에서 Promise로 paymentKey 등을 받아 결제승인API를 호출해주시면 됩니다. - Promise사용을 위해서는 windowTarget:iframe을 사용해주셔야 합니다. (self 사용시 화면이 이동되기에, promise로 값을 받을 수 없습니다.) - Promise 기능은 PC에서만 사용 가능합니다.
Kimoon Lee
Kimoon Lee3y ago
또한가지는 promise 에서 paymentkey 를 받으신후 server2server 방식으로 결제 승인 API 를 호출하셔야 합니다. FE 에서 직접 API 를 호출하시게 되면 secretkey가 노출되어 보안 이슈가 발생합니다.
제이
제이OP3y ago
빠르게 대응해주셔서 고맙습니다. 다만, 설명을 잘 해주셨는데 잘 이해하지 못했습니다. Promise가 대략 아래처럼 사용하는 것은 알고 있으나 function getData() { return new Promise(function(resolve, reject) { $.get('url', function(response) { if (response) { resolve(response); } reject(new Error("Request is failed")); }); }); } getData().then(function(data) { console.log(data); }).catch(function(err) { console.error(err); }); Promise을 사용해본 적이 없어 정확하게 어떻게 해야 될지 감이 오지 않습니다. 혹시 별도의 sample도 제공해주시나요? Classic asp로 구현 중입니다. 도움 부탁 드리겠습니다!
Kimoon Lee
Kimoon Lee3y ago
그냥 결제창 호출을 이렇게 해주시면 됩니다. tosspayments.requestPayment('카드', { orderId: 202212121811, amount: 100, orderName: '테스트 주문', customerName: '테스터', }).then(result => { console.log('success', result); }).catch(error => { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } else if (error.code === 'INVALID_CARD_COMPANY') { // 유효하지 않은 카드 코드에 대한 에러 처리 } }); 지금 보내주신 코드는 승인 API 를 호출하시려는 것인가요? requestPayment 에서 then 이후에 result 객체를 보시면 successURL 로 보내드리는 paymentkey, orderid, amount 등을 가져오실수 있습니다. 이정보를 가지고 server2server 로 결제승인 API 를 호출해 주시면 됩니다.
Ayaan이안
Ayaan이안3y ago
첨언하자면, Promise 객체를 호출하는 방법은 두가지가 있습닏.
// 1. Then, Catch 문법
tosspayments.requestPayment('카드', {
orderId: 202212121811,
amount: 100,
orderName: '테스트 주문',
customerName: '테스터',
}).then(result => {
// 결제 성공시 승인 처리(server2server)
}).catch(error => {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
} else if (error.code === 'INVALID_CARD_COMPANY') {
// 유효하지 않은 카드 코드에 대한 에러 처리
} else {
// 기타 오류 처리
}
});

// 2. Await/Async 문법
try {
let paymentData = await tosspayments.requestPayment('카드', {
orderId: 202212121811,
amount: 100,
orderName: '테스트 주문',
customerName: '테스터',
})

// 결제 성공시 승인 처리(server2server)
} catch (error) {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
} else if (error.code === 'INVALID_CARD_COMPANY') {
// 유효하지 않은 카드 코드에 대한 에러 처리
} else {
// 기타 오류 처리
}
}
// 1. Then, Catch 문법
tosspayments.requestPayment('카드', {
orderId: 202212121811,
amount: 100,
orderName: '테스트 주문',
customerName: '테스터',
}).then(result => {
// 결제 성공시 승인 처리(server2server)
}).catch(error => {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
} else if (error.code === 'INVALID_CARD_COMPANY') {
// 유효하지 않은 카드 코드에 대한 에러 처리
} else {
// 기타 오류 처리
}
});

// 2. Await/Async 문법
try {
let paymentData = await tosspayments.requestPayment('카드', {
orderId: 202212121811,
amount: 100,
orderName: '테스트 주문',
customerName: '테스터',
})

// 결제 성공시 승인 처리(server2server)
} catch (error) {
if (error.code === 'USER_CANCEL') {
// 결제 고객이 결제창을 닫았을 때 에러 처리
} else if (error.code === 'INVALID_CARD_COMPANY') {
// 유효하지 않은 카드 코드에 대한 에러 처리
} else {
// 기타 오류 처리
}
}
두 방법 중에 원하시는 방법으로 넣으시면 되는데, await 문법은 상위함수가 async 함수여야 합니다., 저는 승인처리 s2s부분에서 axios를 이용해 서버로 paymentData 정보를 요청하고, 서버가 그 값으로 토스페이먼츠에 호출하도록 구성했습니다.
제이
제이OP3y ago
고수분들이 있어 든든합니다. 한 가지 더 문제가 발생하였습니다. 카드를 제외한 가상계좌 등은 500 에러가 발생됩니다. 아래와 같은 소스를 통해 호출을 시도했지만 500 에러가 발생되어 validHours 이런 것도 넣어 봤지만 역시 500 에러가 발생되었습니다. 혹시 카드와 하는 방법이 다른가요? 어떤 부분이 잘못되었을까요? tossPayments.requestPayment('가상계좌', { orderId: '123456', amount: '1', orderName: 'test', customerName: 'tester', validHours : '168', cashReceipt : { type : '소득공제' }, }).then(result => { console.log('success', result); }).catch(error => { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } else if (error.code === 'INVALID_CARD_COMPANY') { // 유효하지 않은 카드 코드에 대한 에러 처리 } });
유부장
유부장3y ago
500 에러는 어느 단계에서 발생하는 걸까요? 주문번호 알려주시겠어요?
제이
제이OP3y ago
창 호출 시 발생됩니다. 개발자 도구에는 Failed to load resource: the server responded with a status of 500 () 되어 있고 결제창에는 서버 내부 오류!!로 되어 있습니다. 주문번호는 toss2022121601입니다. 그리고 paymentKey, orderId, amount외는 받아오지 못하나요? orderName, customerName는 받아오지 못하는 것으로 확인됩니다.
유부장
유부장3y ago
로그상으로는 promise 응답은 정상 이었던 것으로 보여지는데, 혹시 아직도 발생하고 있을까요? 승인시에 필요한 값만 드리는 것이어서 다른 값은 응답되지 않아요.
제이
제이OP3y ago
네 지금도 마찬가지입니다. 주문 번호는 위와 같은 toss2022121601입니다. 개발자 도구 에러 페이지로 접속하면 {"code":"NOT_FOUND_HTTP_METHOD","message":"허용되지 않은 HTTP 메서드 접근입니다."} 이런 문구가 뜹니다.
No description
Ayaan이안
Ayaan이안3y ago
오류페이지 직접 접속하면 당연히 405가 발생합니다.
Kimoon Lee
Kimoon Lee3y ago
저희 로그 확인해 보면 결제승인 API가 호출되지 않았습니다. 결제 승인 API 를어떻게 보내신것인지 확인 부탁드립니다 그리고 orderName, customerName는 promise로 받으셨으므로 원래 만드신 주문서 페이지에서 직접 가져오시면 됩니다 저희는 paymentKey, orderId, amount 이렇게 3가지만 원래 successURL 로 보내드리고 있고 promise도 동일합니다.
제이
제이OP3y ago
소스 일부를 그대로 가져 왔습니다. ----------------------------------------------------------------------------------- tossPayments.requestPayment(method, { orderId: 'toss2022121601', amount: 1, orderName: '테스트', customerName: '테스트', }).then(result => { // console.log('success', result); }).catch(error => { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } else if (error.code === 'INVALID_CARD_COMPANY') { // 유효하지 않은 카드 코드에 대한 에러 처리 } }); ----------------------------------------------------------------------------------- 위에 method는 계좌이체입니다. 카드 일 경우는 문제 없이 작동됩니다. 하지만 계좌이체 뿐만 아니라 카드가 아니면 모두 아래와 같이 500 에러가 발생됩니다. Failed to load resource: the server responded with a status of 500 () 도움 부탁드립니다.
Kimoon Lee
Kimoon Lee3y ago
지금 amount 를 1로 보내고 계신것 같은데 맞으실까요? 그리고 저희 쪽에 승인 API 호출 로그가 없습니다. 성공하셨다는 카드 결제건 주문번호 확인 부탁드립니다.
제이
제이OP3y ago
네 1로 보냈습니다. orderId는 toss2022121601로 보냈습니다. 카드는 방금 amount는 2 orderId는 toss2022121602로 보냈습니다.
Kimoon Lee
Kimoon Lee3y ago
toss2022121602 이건 결제가 잘되셨나요? 둘다 동일하게 결제창 뜨고 완료된후 저희쪽으로 결제 승인 API 가 호출되지 않았습니다. 어떤부분을 호출했을때 Failed to load resource: the server responded with a status of 500 ()가 발생하는지 확인 부탁드립니다.
제이
제이OP3y ago
카드는 정상적으로 결제 창이 호출되어 카드를 선택 할 수 있습니다. 삼성 페이로 테스트하였고 정상 진행되었습니다. 가상계좌는 결제 창이 위 첨부 파일처럼 서버 내부 오류!!가 써져 있는 하얀 창만 호출됩니다.
Kimoon Lee
Kimoon Lee3y ago
아 그런말씀이셨군요. 이제 이해 했습니다. 연동하시려는 결제수단이 어떤게 있으신가요? 지금 내부에서 확인해 봐야 겠지만 promise 방식은 카드결제만 적용된것으로 보입니다.
제이
제이OP3y ago
제가 설명이 부족했나 봅니다. 아직 카드만 되는 것이였군요... 카드, 계좌이체, 가상계좌, 상품권, 간편 결제(삼성페이 등)을 연동하려고 했습니다.
Kimoon Lee
Kimoon Lee3y ago
간편 결제(삼성페이 등) 이건 카드로 포함되서 사용가능하실겁니다.
제이
제이OP3y ago
네 맞습니다. 삼성페이 테스트는 성공했습니다.
Kimoon Lee
Kimoon Lee3y ago
타 결제건들은 작업이 조금 필요해서 시간이 조금 걸릴것 같습니다. 참고해 주세요..
제이
제이OP3y ago
네 도움을 주셔서 고맙습니다. 즐거운 주말 보내시길 바랍니다.
Kimoon Lee
Kimoon Lee3y ago
지금 수정해서 배포 되었습니다. 확인 부탁드릴께요..
제이
제이OP3y ago
안녕하세요 주말 잘 보내셨나요? 사실 포기? 조금은 기다려 볼까?했는데 토스는 역시 포기하지 않고 바로 해주셨네요! 우선 카드, 가상계좌등 결제 창이 잘 뜨는 것이 확인되었습니다. 아래와 같은 코드로 짜보려고 하는데 문제가 있을까요? 혹시 문제가 있다면 보안 점이 있을까요? tossPayments.requestPayment(method, { orderId: '123456', amount: 1, orderName: '테스트1', customerName: '테스트1', }) .then(result => { url = 'ss', data = { 'paymentKey': result.paymentKey, 'orderId': result.orderId, 'amount': result.amount } $.ajax({ url: url, type: 'POST', data: data, dataType: 'html', success: function(result){
} }); }).catch(error => { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 alert('취소하셨습니다.'); } else if (error.code === 'INVALID_CARD_COMPANY') { // 유효하지 않은 카드 코드에 대한 에러 처리 alert('오류가 발생되었습니다.'); } });
today.lastday
today.lastday3y ago
위와 같은 방식으로 처리하셔도 문제는 없을 것 같아요. 다만 성공시 승인 API 호출해야하는데 이 부분은 front에서 직접 승인 API 호출하지마시고 내부 API만들어서 호출하시면 됩니다. secretKey 유출 이슈.
제이
제이OP3y ago
확인해주셔서 고맙습니다. 날씨 추운데 감기 조심하시길 바랍니다.

Did you find this page helpful?