kokoko.kojima
kokoko.kojima2y ago

Flutter Webview에서 Javascript SDK 연동할 수 있는 방법이 있나요?

모바일 웹뷰 환경에서 javascript SDK를 활용해서 결제를 시도하면, "모바일 화면에서는 Promise 방식을 지원하지 않습니다." 에러가 표시됩니다. 아래는 flutter_webview 패키지를 사용하여 결제를 시도한 코드입니다.
// 카스텀 웹뷰 widget을 포함하는 widget
class TossPayment extends StatelessWidget {
final Widget? initialChild;
final String clientKey;
final PaymentData? data;
final callback;
final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;

TossPayment({
Key? key,
this.initialChild,
required this.clientKey,
required this.data,
required this.callback,
this.gestureRecognizers,
}) : super(key: key);

@override
Widget build(BuildContext context) {
var redirectUrl = UrlData.redirectUrl;
return TossPaymentsWebView(
type: ActionType.payment,
initialChild: this.initialChild,
gestureRecognizers: this.gestureRecognizers,
executeJS: (WebViewController controller) {
controller.runJavascript('''
var tossPayments = TossPayments("${this.clientKey}");
tossPayments.requestPayment("카드", ${jsonEncode(this.data?.toJson())})
''');
},
customPGAction: (WebViewController controller) {
return null;
},
useQueryData: (Map<String, String> data) {
this.callback(data);
},
isPaymentOver: (String url) {
if (url.startsWith(redirectUrl)) {
return true;
}

return false;
},
);
}
}
// 카스텀 웹뷰 widget을 포함하는 widget
class TossPayment extends StatelessWidget {
final Widget? initialChild;
final String clientKey;
final PaymentData? data;
final callback;
final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;

TossPayment({
Key? key,
this.initialChild,
required this.clientKey,
required this.data,
required this.callback,
this.gestureRecognizers,
}) : super(key: key);

@override
Widget build(BuildContext context) {
var redirectUrl = UrlData.redirectUrl;
return TossPaymentsWebView(
type: ActionType.payment,
initialChild: this.initialChild,
gestureRecognizers: this.gestureRecognizers,
executeJS: (WebViewController controller) {
controller.runJavascript('''
var tossPayments = TossPayments("${this.clientKey}");
tossPayments.requestPayment("카드", ${jsonEncode(this.data?.toJson())})
''');
},
customPGAction: (WebViewController controller) {
return null;
},
useQueryData: (Map<String, String> data) {
this.callback(data);
},
isPaymentOver: (String url) {
if (url.startsWith(redirectUrl)) {
return true;
}

return false;
},
);
}
}
8 Replies
토스페이먼츠 BOT
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) : - 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요. * 주말/공휴일에는 답변이 늦을 수 있어요.
kokoko.kojima
kokoko.kojima2y ago
// 커스텀 웹뷰
enum ActionType { auth, payment }

class TossPaymentsWebView extends StatefulWidget {
static final Color primaryColor = Color(0xff344e81);
static final String html = '''
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<script type="text/javascript" src="https://js.tosspayments.com/v1/payment"></script>
</head>
<body></body>
</html>
''';

final ActionType type;
final Widget? initialChild;
final ValueSetter<WebViewController> executeJS;
final ValueSetter<Map<String, String>> useQueryData;
final Function isPaymentOver;
final Function customPGAction;
final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;

TossPaymentsWebView({
required this.type,
this.initialChild,
required this.executeJS,
required this.useQueryData,
required this.isPaymentOver,
required this.customPGAction,
this.gestureRecognizers,
});

@override
_TossPaymentsWebViewState createState() => _TossPaymentsWebViewState();
}
// 커스텀 웹뷰
enum ActionType { auth, payment }

class TossPaymentsWebView extends StatefulWidget {
static final Color primaryColor = Color(0xff344e81);
static final String html = '''
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<script type="text/javascript" src="https://js.tosspayments.com/v1/payment"></script>
</head>
<body></body>
</html>
''';

final ActionType type;
final Widget? initialChild;
final ValueSetter<WebViewController> executeJS;
final ValueSetter<Map<String, String>> useQueryData;
final Function isPaymentOver;
final Function customPGAction;
final Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;

TossPaymentsWebView({
required this.type,
this.initialChild,
required this.executeJS,
required this.useQueryData,
required this.isPaymentOver,
required this.customPGAction,
this.gestureRecognizers,
});

@override
_TossPaymentsWebViewState createState() => _TossPaymentsWebViewState();
}
이실장
이실장2y ago
해당 오류는 requestPayments() 호출시 successUrl을 입력해주지 않아서 발생하는 오류입니다 successURL입력해보시겠어요
kokoko.kojima
kokoko.kojima2y ago
successURL에 null 이 들어간 것을 확인했습니다. 감사합니다.
이실장
이실장2y ago
카드결제 연동하시는거죠?
이실장
이실장2y ago
methodchannel 을 이용한 intent처리도 해주셔야 안드로이드에서 카드사 앱카드를 정상적으로 띄우실 수 있습니다. 아래 문서 참고해주세요 https://docs.tosspayments.com/guides/webview#%EC%83%98%ED%94%8C-%EC%86%8C%EC%8A%A4
웹뷰(WebView)에서 외부 앱 열기 | 토스페이먼츠 개발자센터
브라우저가 아닌 모바일 웹뷰로 결제창을 띄울 때 카드사별 결제 수단을 인증하려면 외부 앱(3rd-party 앱)을 연동해야 합니다. 연동에 필요한 외부 앱 스킴(App URL Scheme)목록과 추가 로직을 살펴보세요.
kokoko.kojima
kokoko.kojima2y ago
넵. 감사합니다.
토스페이먼츠 BOT
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.