Flutter集成MPGs时出现sessionStorage访问权限拒绝错误求助
MPGs支付表单加载时sessionStorage权限错误问题排查
问题背景
使用Mastercard Payment Gateway Services(MPGs)对接支付功能:
- 已获取支付服务方提供的HTML代码
- 通过API
https://mcb.gateway.mastercard.com/api/rest/version/75/merchant/{merchant-id}/session成功获取session ID - HTML代码能正常读取session ID,但WebView加载后,点击支付按钮显示表单时触发sessionStorage权限错误
错误日志
I/flutter (17252): JavaScript Console: Uncaught SecurityError: Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document. I/flutter (17252): JavaScript Console: Possible Unhandled Promise Rejection: SecurityError: Failed to read the 'sessionStorage' property from 'Window': Access is denied for this document.
原因分析
核心问题是WebView加载本地HTML时的源(Origin)缺失:
- 当前使用
loadData加载HTML内容,WebView默认会将该页面的源设为null或about:blank - sessionStorage是基于同源策略的存储API,浏览器会拒绝无有效源的文档访问sessionStorage
- MPGs的
checkout.min.js脚本依赖sessionStorage存储会话数据,因此触发安全错误
解决方案
最直接的修复方式是使用loadDataWithBaseURL替代loadData,指定与MPGs脚本同源的Base URL,让WebView为HTML页面赋予合法的源,从而允许访问sessionStorage。
修改后的代码示例
InAppWebView( initialUrlRequest: URLRequest( url: Uri.parse(''), ), initialOptions: InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( cacheEnabled: true, useShouldOverrideUrlLoading: true, javaScriptEnabled: true, javaScriptCanOpenWindowsAutomatically: true, mediaPlaybackRequiresUserGesture: false, ), android: AndroidInAppWebViewOptions( useHybridComposition: true, domStorageEnabled: true, ), ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, )), androidOnPermissionRequest: (controller, origin, resources) async { return PermissionRequestResponse( resources: resources, action: PermissionRequestResponseAction.GRANT, ); }, onWebViewCreated: (controller) async { webView = controller; await webView?.loadDataWithBaseURL( baseUrl: 'https://mcb.gateway.mastercard.com', // 关键:指定同源Base URL data: ''' <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://mcb.gateway.mastercard.com/static/checkout/checkout.min.js" data-error="errorCallback" data-cancel="cancelCallback"></script> <script type="text/javascript"> function errorCallback(error) { console.log(JSON.stringify(error)); } function cancelCallback() { console.log('Payment cancelled'); } Checkout.configure({ session: { id: '${state.id}' } }); </script> </head> <body> ... <div id="embed-target"> </div> <input type="button" value="Pay with Embedded Page" onclick="Checkout.showEmbeddedPage('#embed-target');" /> <input type="button" value="Pay with Payment Page" onclick="Checkout.showPaymentPage();" /> ... </body> </html> ''', mimeType: 'text/html', ); }, onLoadError: (controller, url, code, message) { print('Error loading $url: $code, $message'); }, onLoadStop: (controller, url) {}, onConsoleMessage: (controller, consoleMessage) { final logMessage = consoleMessage.message; print('JavaScript Console: $logMessage'); }, );
额外说明
- 确保
baseUrl与MPGs脚本的域名完全一致(即https://mcb.gateway.mastercard.com),避免跨域问题 - 已有的
domStorageEnabled: true配置是必要的,但仅开启这个无法解决源缺失的核心问题
内容的提问来源于stack exchange,提问作者NehruJr
相关产品推荐
相关产品推荐

