xoneto99
xoneto992y ago

[flutter][brandpay] 초기화 오류

안녕하세요. 환경, 앱: flutter 에서 inappwebview를 이용하여 브랜드 페이 UI를 띄우고자 함 브랜드페이: nextjs 를 구성하여 brandpay sdk를 이용하여 초기화함. 또한 cors 이슈를 피하기 위해 callback 함수를 nextjs 에서 구성 테스트 : 아이폰 12pro max에서 실시 brandpay server는 aws elastic beanstalk에 올렸고 도메인을 연결하였음. 이전에 이와 관련하여 상담을 받았었습니다. 그때 궁극적으론 localhost에서 request를 요청하여 그런것으로 잠정 결론을 내렸으나... 도메인을 구성하여 실제 서버를 운영하였음에도 불구하고 작동하지 않고 있습니다. 컴퓨터 브라우저로 해당 url에 접속하면 컴퓨터 브라우저에는 잘 뜹니다. callback 라우터가 잘 불러져서 code, token값을 잘 받았습니다. 그러나 스마트폰으로 실제 기기에서 테스트 할 경우, callback 불려지지 않고 있습니다. 혹시 해당 이슈를 알 수 있을까 합니다. brandpay를 보면 비여있는 객체로 전달됩니다.. callback으로 redirect가 되고 있지 않습니다.....
- Error: Query data cannot be undefined,
- A client-side exception has occurred, see here for more info: https://nextjs.org/docs/messages/client-side-exception-occurred
- TypeError: undefined is not an object (evaluating 'r.debug')
- Error: Query data cannot be undefined,
- A client-side exception has occurred, see here for more info: https://nextjs.org/docs/messages/client-side-exception-occurred
- TypeError: undefined is not an object (evaluating 'r.debug')
위와 같은 에러 메시지를 받고 있습니다. aws - elasticbeanstalk 에서 로그에 찍히지 않고 있음에 따라 redirect url로 들어오고 있지 않습니다. 해당 건에 대하여 작은 실마리라도 얻길바랍니다. .. 감사합니다. https://discord.com/channels/864296203746803753/1077126713722540112
22 Replies
토스페이먼츠 BOT
⏳ 잠시만 기다려주세요! 곧 답변드리겠습니다
오류 문의일 경우 아래 정보를 미리 전달해주시면, 빠른 답변에 도움이 됩니다.
- 주문번호(orderId) : - 문의 내용 :
(img를 함께 첨부해주시면 도움이됩니다)
* 계약관련 내용은 1544-7772로 문의주세요. * 주말/공휴일에는 답변이 늦을 수 있어요.
이실장
이실장2y ago
사용하신 mid(상점아이다) 모르시면 에러받은 customerkey 남겨주세요
xoneto99
xoneto99OP2y ago
63a32457307d4f4f7e839e02 입니다.
Kimoon Lee
Kimoon Lee2y ago
플러터 인앱 브라우저의 디버깅이 가능하시다면 해당 에러 이외에 다른 에러는 없는지 확인부탁드립니다. 에러 내용으로만 보면 Brand pay 관련 js 를 정상적으로 로딩하지 못한게 아닐까 싶은데요.
xoneto99
xoneto99OP2y ago
Error: 잘못된 요청입니다. 이런 에러가 반환되어 왔구요..
This method should not be called on the main thread as it may lead to UI unresponsiveness.
This method should not be called on the main thread as it may lead to UI unresponsiveness.
이런 시스템 에러가 뜨고 .. [assertion] Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}> [ProcessSuspension] 0x11c01c540 - ProcessAssertion::acquireSync Failed to acquire RBS assertion 'WebProcess Background Assertion' for process with PID=3890, error: Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit} [assertion] Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit}> [ProcessSuspension] 0x11c01c6c0 - ProcessAssertion::acquireSync Failed to acquire RBS assertion 'WebProcess Suspended Assertion' for process with PID=3890, error: Error Domain=RBSServiceErrorDomain Code=1 "target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit" UserInfo={NSLocalizedFailureReason=target is not running or doesn't have entitlement com.apple.runningboard.assertions.webkit} 이런 것??? 이뜨는데요.. 음... 그 외에 특별한 것은 잘 모르겠습니다. ㅠ 구글링도 많이 했지만... 이게 아이폰 문제인가 싶기도 하구요 ...
이실장
이실장2y ago
일단 저는 inappwebview 플러그인 말고, webview_flutter 로 사용해서 이상없이 잘 동작하고 있습니다. brandpay 객체 초기화를 웹서버에서 하시나요? 아니면 flutter dart code에서 하시나요
xoneto99
xoneto99OP2y ago
그럼 webview_flutter로 해보도록 할까 싶네요... 이유는 사실 잘 모르겠는데 webview_flutter로 할 경우 데이터를 주고 받기 위해 runJavascript를 실행하는데 이게 잘 안되서 inappwebview로 한걸로 기억하거든요.. 객체 초기화는 웹서버에서 합니다. ㅎ nextjs로 하였습니다. 하나 더 여쭤볼게요. 혹시 그러면 flutter_webview로 하실때 데이터 어떻게 주고 받나요 ?? 하시는 초기화 react 로 하시나요? nextjs로 하시나요 ? 아니면 제가 샘플 코드를 받아 볼 수 있을까요 ??
이실장
이실장2y ago
웹뷰(WebView)에서 외부 앱 열기 | 토스페이먼츠 개발자센터
브라우저가 아닌 모바일 웹뷰로 결제창을 띄울 때 카드사별 결제 수단을 인증하려면 외부 앱(3rd-party 앱)을 연동해야 합니다. 연동에 필요한 외부 앱 스킴(App URL Scheme)목록과 추가 로직을 살펴보세요.
xoneto99
xoneto99OP2y ago
주신 샘플코드는 역시 서버에서 초기화 하나요 ?
이실장
이실장2y ago
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Tosspayments Flutter Sample")),

body: WebView(
initialUrl: "#### 웹뷰 URL을 설정하세요 #####",
onPageStarted: (url) {},
onPageFinished: (url) {},
navigationDelegate: (request) async {
Uri uri = Uri.parse(request.url);
String finalUrl = request.url;


launchUrlString(finalUrl);

return NavigationDecision.prevent;
},
javascriptMode: JavascriptMode.unrestricted,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Tosspayments Flutter Sample")),

body: WebView(
initialUrl: "#### 웹뷰 URL을 설정하세요 #####",
onPageStarted: (url) {},
onPageFinished: (url) {},
navigationDelegate: (request) async {
Uri uri = Uri.parse(request.url);
String finalUrl = request.url;


launchUrlString(finalUrl);

return NavigationDecision.prevent;
},
javascriptMode: JavascriptMode.unrestricted,
),
);
}
xoneto99
xoneto99OP2y ago
그렇군요 서버에서 하나보군요 ..
이실장
이실장2y ago
웹뷰 영역에 저부분만 붙이면 될 것 같아요~ 브랜드페이는 methodchannel 사용할 필요가 없어서요
xoneto99
xoneto99OP2y ago
그래요 ?? channel을 사용 안하면.... user key data를 못주지 않나요 ?
const _prepare = useCallback(async () => {
try {
let brandpay = await loadBrandPay(
process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY!,
userId,
{
redirectUrl: process.env.NEXT_PUBLIC_TOSS_CALLBACK_URL,
ui: {
highlightColor: "#26C2E3",
buttonStyle: "full",
},
windowTarget: "iframe",
}
);
brandpayRef.current = brandpay;
await brandpay.addPaymentMethod("카드");
} catch (error: any) {
console.log("error======>", error);
}
}, [userId]);
const _prepare = useCallback(async () => {
try {
let brandpay = await loadBrandPay(
process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY!,
userId,
{
redirectUrl: process.env.NEXT_PUBLIC_TOSS_CALLBACK_URL,
ui: {
highlightColor: "#26C2E3",
buttonStyle: "full",
},
windowTarget: "iframe",
}
);
brandpayRef.current = brandpay;
await brandpay.addPaymentMethod("카드");
} catch (error: any) {
console.log("error======>", error);
}
}, [userId]);
제가 이런식으로 짰는데요, 보면
let brandpay = await loadBrandPay(
process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY!,
userId,
let brandpay = await loadBrandPay(
process.env.NEXT_PUBLIC_TOSS_CLIENT_KEY!,
userId,
이부분에 loadBrandPay할때 customerKey를 줘야해서 channal 사용해야 하지 않나요??
이실장
이실장2y ago
구현하신 내용에 대해서는 잘 몰라서요 위에 가이드 링크에서 methodchannel은 안드로이드 native 와 통신해서, intentURL처리하기 위해 사용된 부분이라 사용할 필요없다고 말씀드린거고 구현방식에 따라 사용하시는건 문제없습니다. 그리고 위에는 react코드인데, flutter method channel말씀드린거에요~
xoneto99
xoneto99OP2y ago
xoneto99
xoneto99OP2y ago
그러면 저기서 channal은 안드로이드 쪽이란 말씀이신건 이해를 하였습니다. 감사합니다. 그...음... 제가 아직 이해가 안되는 부분이.. 브랜드페이를 사용할경우 react로 초기화 할경우, 토스 가이드에서 javascript SDK를 사용하여 초기화 할경우 https://docs.tosspayments.com/reference/brandpay-sdk#ui-%EC%98%B5%EC%85%98-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0 여기 옵션설정하기 보면 초기화가 나오는데요,
var brandpay = BrandPay(clientKey, customerKey, {
redirectUrl: 'http://example.com',
ui: {
highlightColor: '#26C2E3',
buttonStyle: 'full',
labels: {
oneTouchPay: '내 상점 원터치결제',
},
},
windowTarget: 'iframe'
})
var brandpay = BrandPay(clientKey, customerKey, {
redirectUrl: 'http://example.com',
ui: {
highlightColor: '#26C2E3',
buttonStyle: 'full',
labels: {
oneTouchPay: '내 상점 원터치결제',
},
},
windowTarget: 'iframe'
})
이부분에 보면 customerKey가 나오는데요. 이부분에 customerKey를 서버에 전달하려면, flutter_webview에서 데이터를 전달해야 하는데요. 혹시 이부분도 구현이 가능하셨나요 ?
브랜드페이 JavaScript SDK | 토스페이먼츠 개발자센터
브랜드페이 JavaScript SDK를 추가하고 메서드를 사용하는 방법을 알아봅니다.
Ayaan이안
Ayaan이안2y ago
webview를 띄울 때 URL에 query string으로 쏘면 될 것같아 보입니다, e.g) blablablabla:3000/requestPayment?customerKey=blablablabla
이실장
이실장2y ago
네 @iam.ayaan 님이 제안해주신 방법으로 간단하게 가능하겠네요 ~
xoneto99
xoneto99OP2y ago
감사합니다. 그렇다면 그 방법으로 ...쿼리 스트링으로 날리도록하겠습니다. 긴 내용과 번잡스런 내용이였음에도 도와주셔서 모두 감사합니다.
토스페이먼츠 BOT
❤️ 기술문의 경험이 어떠셨나요?!
간단히 코멘트 남겨주세요! 제품 발전에 큰 힘이 됩니다.
xoneto99
xoneto99OP2y ago
누군가 해당 포스트를 보고 참고하시면 좋을 것 같아서 추가로 덧붙입니다. flutter 에서 webview_flutter 모듈을 사용하여 react , nextjs 에 runjavascript를 통해 데이터를 전송한다면 react 컴포넌트 내부 함수는 외부에서 콜을 할 수 없다고 합니다. 또한, flutter 로 개발하고, react 계열로 웹을 구성하여 Toss Payment UI 를 구성할 경우 보통 flutter 로 webview_flutter, inAppWebView 모듈들을 통해 구현하게 되는데, 제가 해 본바로는 이유는 알 수 없지만 inAppWebView는 UI를 화면에 띄워 주지 않습니다. 이유는 모릅니다... 또한 webview_flutter를 사용 할경우 UI 모듈은 잘 나오는데
var brandpay = BrandPay(clientKey, customerKey, {
redirectUrl: 'http://example.com',
ui: {
highlightColor: '#26C2E3',
buttonStyle: 'full',
labels: {
oneTouchPay: '내 상점 원터치결제',
},
},
windowTarget: 'iframe'
})
var brandpay = BrandPay(clientKey, customerKey, {
redirectUrl: 'http://example.com',
ui: {
highlightColor: '#26C2E3',
buttonStyle: 'full',
labels: {
oneTouchPay: '내 상점 원터치결제',
},
},
windowTarget: 'iframe'
})
와 같이 초기화 할때 보통 redirectUrl과 customerKey가 들어갑니다. redirectUrl은 env에 등록하면 되고.. customerKey가 flutter에서 react로 데이터 송신을 해야 합니다. 이때 runJavascritp를 사용하게 됩니다. 이 모듈은 위에 언급한 바와 같이 react 내부 함수 호출이 불가합니다. 따라서 많은 구글링 결과... CusomEvent를 addListner로 등록하여 실행하였습니다. 그리고 runJavaScript 실행은
controller.runJavaScript(
"window.dispatchEvent(new CustomEvent('customerEventHandler', { detail: { userId: '$userId' } }));",
);
controller.runJavaScript(
"window.dispatchEvent(new CustomEvent('customerEventHandler', { detail: { userId: '$userId' } }));",
);
이렇게 해서 데이터 전송을 하였습니다. 저같은 경우 nextjs로 하였는데요 redirect시에 cors 에러를 피하기 위해서 사용하였습니다. 그런데 이때에 nextjs를 기본적으로 사용하는 arrow function으로 구성하면 runJavscript 실행시 오류가 뜹니다.. 이도 구체적인 원인을 모르겠습니다. 구글링을 많이 했는데 명확한 증상은 없네요.. 그래서 찾다가 nextjs를 class components로 구성하여 작동 시켰더니 사용 가능했습니다. 저는 이렇게 구현하였습니다. 이도저도 안 될때는 그냥 query string 사용하려고 하였는데... id가 query string으로 전달되는게 좀 찜찜해서 ... 그냥 이렇게 구현하였습니다 . 구체적인 오류들을 정확히 알수 없어서 이렇다할 해결책을 명확히 제시는 못하겠구요... 저는 이렇게 구성하였습니다. 오류로 빡치는 상황들에 몰리신 분들에게 도움이 되고자 적었습니다. 이 문제로 제가 2주동안 매우 빡쳤었으므로 다른 분들은 편히 가시면 좋겠습니다. 또한 상담해주신 많은 분들께 감사함을 전합니다 . 감사합니다.
Ayaan이안
Ayaan이안2y ago
네 맞습니다. runjavascript는 react 소스가 호출된 이후에 실행되기 때문에 react 내부 함수 콜이 불가능합니다.

Did you find this page helpful?