IOS에서 자동결제창 호출 시 응답값 문의
안녕하세요. flutter로 자체 구축한 앱에서 IOS로 정기결제 빌링 호출(https://docs.tosspayments.com/sdk/v2/js#paymentrequestbillingauth) 시 응답값이 아래와 같이 오면서 정기결제 페이지가 뜨질 않습니다. key 값이 들어있어서 일부만 드립니다.
data:text/html;charset=utf-8,%20%20%20%20%20%20%20%20%20%20%3Chtml%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Chead%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctitle%3E%EA%B2%B0%EC%A0%9C%ED%95%98%EA%B8%B0%3C/title%3E%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmeta%20charset='utf-8'%20/%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%20src='https://js.tosspayments.com/v1/payment'%3E%3C/script%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C/head%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cbody%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%
해당 값을 decode 하니 tossPayments 화면 띄우는 html이 그대로 들어있습니다.
Android는 응답값이 아래와 같이 오면서 정상적으로 페이지가 뜹니다.
https://payment-gateway.tosspayments.com/billing/mobile?clientKey=<**>&isMobile=true&payload=%7B%22customerKey%22%3A%22az1701480618331uRwuQ%22%2C%22successUrl%22%3A%22com.qtechai.cncare%3A%2F%2Fsuccesurl%22%2C%22failUrl%22%3A%22com.qtechai.cncare%3A%2F%2Ffailurl%22%2C%22referer%22%3A%22*%22%2C%22payMethod%22%3A%22%EC%B9%B4%EB%93%9C%22%7D>id=a241003JJvWCeXRHQA15WIadpFaZX03PnfkNQVI
답변 부탁드립니다.
좋은 하루 되세요.
토스페이먼츠 JavaScript SDK | 토스페이먼츠 개발자센터
토스페이먼츠 JavaScript SDK를 추가하고 메서드를 사용하는 방법을 알아봅니다.
36 Replies
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) :
- 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요.
* 주말/공휴일에는 답변이 늦을 수 있어요.
안녕하세요 웹뷰에서 연동하고계신가요?
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.
네. 웹뷰로 연동하고 있습니다.
GitHub
GitHub - youjun-lee/flutter_webview_sample_app: flutter webview sample
flutter webview sample. Contribute to youjun-lee/flutter_webview_sample_app development by creating an account on GitHub.
웹뷰 띄우는건 문제 없습니다. 안드로이드에서 카드 정보 입력창 띄웠고요. 문제는 ios에서 동일하게 웹뷰를 띄웠을때 return 값이 최초 웹뷰 띄웠을때와 동일한 html 코드로 encoding 되어서 회신이 옵니다.
아래는 소스의 일부입니다.
body: state.status == ScreenStatus.loaded
? WebView(
initialUrl: Uri.dataFromString(
'''
<html>
<head>
<title>결제하기</title>
<meta charset='utf-8' />
<script src='https://js.tosspayments.com/v1/payment'></script>
</head>
<body>
<script>
var clientKey = '${F.tossClientKey}';
var tossPayments = TossPayments(clientKey); tossPayments .requestBillingAuth('카드', { customerKey: '${state.user?.tuyaUid}', successUrl: 'com.qtechai.cncare://succesurl', failUrl: 'com.qtechai.cncare://failurl', }) .catch(function (error) { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } }); </script> </body> </html> ''', mimeType: 'text/html', encoding: Encoding.getByName('utf-8'), ).toString(), javascriptMode: JavascriptMode.unrestricted, navigationDelegate: (NavigationRequest request) async { // com.qtechai.cncare://succesurl?customerKey=<...>&authKey=<...> var url = request.url; if (request.url .contains('com.qtechai.cncare://succesurl')) { context.read<TossWebViewCubit>().getResult(url); } return NavigationDecision.navigate; }, )
var tossPayments = TossPayments(clientKey); tossPayments .requestBillingAuth('카드', { customerKey: '${state.user?.tuyaUid}', successUrl: 'com.qtechai.cncare://succesurl', failUrl: 'com.qtechai.cncare://failurl', }) .catch(function (error) { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } }); </script> </body> </html> ''', mimeType: 'text/html', encoding: Encoding.getByName('utf-8'), ).toString(), javascriptMode: JavascriptMode.unrestricted, navigationDelegate: (NavigationRequest request) async { // com.qtechai.cncare://succesurl?customerKey=<...>&authKey=<...> var url = request.url; if (request.url .contains('com.qtechai.cncare://succesurl')) { context.read<TossWebViewCubit>().getResult(url); } return NavigationDecision.navigate; }, )
return 값이 최초 웹뷰 띄웠을때와 동일한 html 코드로 encoding 되어서 회신이 옵니다.말씀하시는 리턴값이 어떤걸까요?
return BaseScaffold(
onBack: () {
Navigator.pop(context);
},
body: state.status == ScreenStatus.loaded
? WebView(
initialUrl: Uri.dataFromString(
'''
<html>
<head>
<title>결제하기</title>
<meta charset='utf-8' />
<script src='https://js.tosspayments.com/v1/payment'></script>
</head>
<body>
<script>
var clientKey = '${F.tossClientKey}';
var tossPayments = TossPayments(clientKey); tossPayments .requestBillingAuth('카드', { customerKey: '${state.user?.tuyaUid}', successUrl: 'com.qtechai.cncare://succesurl', failUrl: 'com.qtechai.cncare://failurl', }) .catch(function (error) { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } }); </script> </body> </html> ''', mimeType: 'text/html', encoding: Encoding.getByName('utf-8'), ).toString(), javascriptMode: JavascriptMode.unrestricted, navigationDelegate: (NavigationRequest request) async { var url = request.url; if (request.url .contains('com.qtechai.cncare://succesurl')) { context.read<TossWebViewCubit>().getResult(url); } return NavigationDecision.navigate; }, ) : Container(), ); 위 소스에서 context.read<TossWebViewCubit>().getResult(url); 에서 읽은 값입니다.
var tossPayments = TossPayments(clientKey); tossPayments .requestBillingAuth('카드', { customerKey: '${state.user?.tuyaUid}', successUrl: 'com.qtechai.cncare://succesurl', failUrl: 'com.qtechai.cncare://failurl', }) .catch(function (error) { if (error.code === 'USER_CANCEL') { // 결제 고객이 결제창을 닫았을 때 에러 처리 } }); </script> </body> </html> ''', mimeType: 'text/html', encoding: Encoding.getByName('utf-8'), ).toString(), javascriptMode: JavascriptMode.unrestricted, navigationDelegate: (NavigationRequest request) async { var url = request.url; if (request.url .contains('com.qtechai.cncare://succesurl')) { context.read<TossWebViewCubit>().getResult(url); } return NavigationDecision.navigate; }, ) : Container(), ); 위 소스에서 context.read<TossWebViewCubit>().getResult(url); 에서 읽은 값입니다.
context.read<TossWebViewCubit>().getResult(url);
이거는 왜하는건가요?
그냥 requestBillingAuth 실행되면
저희 결제창 뜨는거아닌가요?
requestBillingAuth 실행하고 response 결과값을 가져오기 위함입니다.
문의내용은 위 소스로 호출 시 android는 정상적으로 결과가 회신되어 카드등록 페이지가 뜨는데 ios는 위 페이지 그대로 회신되어서 왜 차이가 있는지입니다.
두가지의 동작 방식이 다릅니다.
안드로이드는 URL 을 응답으로 받고 해당 URL 을 직접 띄우는 방식이고
IOS 는 해당 URL 의 html 을 직접 받는 방식으로 구현되어 있다고 알고 있습니다.
중간에 응답을 context.read<TossWebViewCubit>().getResult(url); 로 받지 마시고 저희 샘플에 있는대로 구현해 주시기 바랍니다.
저희 모듈에서 자체적으로 받아서 새로 웹뷰 열고 처리하도록 되어 있습니다.
equestBillingAuth 실행하고 response 결과값은 success 쪽으로 알아서 전달됩니다. 저렇게 받으실 필요가 없구요.
혹시 샘플 받을수 있을까요? 전에 이실장님이 주신건 단순 웹뷰 띄우는 flutter 샘플을 받아서요.
response 결과값을 가져오기 위함입니다.successUrl로 이동한 후를 말씀하시는건가요? 아니면 빌링결제창을 띄우고 싶으신건가요?
자동결제 카드등록 페이지이고 successUrl 이동 이후 아닐까요?
그리고 ios 의 경우 응답값이 최초 html 코드와 동일해서 자동결제 카드등록 페이지가 뜨질 않습니다.
그럼 context.read<TossWebViewCubit>().getResult(url); 이 값을 받아서 웹뷰에서 이동 시켜 주시는 건가요?
제가 정리해볼게요
넵넵
네. 값 받아서 그냥 바로 띄웁니다. 안드로이드의 경우엔 getResult 값이 자동결제 카드등록 페이지 html 코드가 와서 화면에 자동결제 페이지가 바로 로딩됩니다.
context.read<TossWebViewCubit>().getResult(url); 이게 . 왜필요한지 일단 알수가 없어요
tossPayments.requestBillingAuth이게 실행되면
자동으로 웹뷰가 전환되어야하는거 아닌가요?
일단 저희 샘플은 별도로 없는데, 과거 일반결제창 SDK가 비슷한 형식으로 만들어져 있어요
Dart packages
tosspayments_sdk_flutter package - All Versions
Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter and general Dart programs.
여기서 마지막 버전 다운로드 받은 .
ios는 결과값이 필요한 정보가 부족하다고 에러가 옵니다.
/lib/widget/payment_window_weibview
lib/tosspayments_sdk_flutter
2개한번 참고해봇에ㅛ
네. 일단 참고해서 다시 해보겠습니다. 감사합니다.
결과값이 부족할 수 밖에 없는게 원래 저희가 url을 직접 호출하는 방식이 저희스펙이 아니에요.
requestBillingAuth() method가 자동으로 redirect를 시켜줘야합니다.
url을 직접 받거나, html을 화면에 그려주는게 아니라
웹뷰위에서 requestBillingAuth() 스크립트를 실행시켜준다. 로 방향성을 잡으면 좋을 . 것같습니다.
일단 결제창 부터. 띄운후에 이어서 살펴보시죠
네. 근데 안드로이드는 정상적으로 되기 때문에 ios는 문제 없이 될거라고 생각했는데, ios만 에러 발생해서 문의 드렸던거고, 위 주신 링크 참고해서 다시 작업해 보도록 하겠습니다.
네 일단 flutter 웹뷰가 lib도 여러개이고 하다보니. android만 되는부분은 어떻게 설명드리기가 어렵네요 ㅠ
안녕하세요. 혹시 아래 패키지는 자동결제 구현에 참고가 안될까요. 주신 문서는 deprecated로 나와있어서요.
https://pub.dev/documentation/tosspayments_widget_sdk_flutter/latest/
tosspayments_widget_sdk_flutter - Dart API docs
tosspayments_widget_sdk_flutter API docs, for the Dart programming language.
네 결제위젯은 자동결제 사용하시면 안됩니다.
이거 사용 바랍니다.
현재 버전이 위 링크로 구현된거 확인했습니다. tosspayments webview 사용중이고 위에 언급드린대로 안드로이드는 정상 동작합니다. 제가 잘못 말씀드린듯 한데 2번째 스크린샷에 return NavigationDecision.navigate 여기서 안드로이드는 정상적으로 자동결제 카드추가 페이지가 로딩됩니다. 말씀하신것 처럼 getResult 없애고 ios 를 다시 테스트 해도 동일하게 html code가 그대로 webview에 뜨면서 정보가 부족하다고 나옵니다. 웹뷰에 로딩되는 값은 data:text/html;charset=utf-8,~~ 이 값이 뜹니다.
webview lib는 어떤거쓰시나요?
tosspayments_sdk_flutter 에서 제공하는 webview 사용하고 있습니다.
아무튼 이건 flutter/webview등의 동작문제여서
저희도 도움을드리기가 어렵네요
toss에서 제공하는 sdk의 webview를 이용해서 ios에서 정상 카드추가 화면 뜨는지 자체적으로 확인 되시는건가요?
혹시 requestBillingAuth말고
requestPayment도 동일하게 아이폰에서 안되시나요?
해보고 메시지 드리겠습니다.
일반결제는 아이폰에서 정상적으로 페이지 떴씁니다.