You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS端flutter_inappwebview集成RazorPay支付时新窗口无法弹出

iOS端flutter_inappwebview无法弹出RazorPay支付窗口的解决方法

问题背景

通过Web URL集成RazorPay支付功能,因需求限制未使用官方razorpay_plugin,采用flutter_inappwebview实现WebView。Android端测试模式下可正常弹出支付窗口并展示成功/失败选项,但iOS端无法弹出新窗口加载支付URL。

已在Info.plist中添加ATS配置:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsLocalNetworking</key>
        <true/>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSAllowsArbitraryLoadsInWebContent</key>
        <true/>
    </dict>

相关实现代码:

class SomeScreen extends StatefulWidget {
  final String url;
  const SomeScreen({Key? key, required this.url}) : super(key: key);

  @override
  _SomeScreenState createState() => _SomeScreenState();
}

class _SomeScreenState extends State<SomeScreen> {
  InAppWebViewController? _webViewController;
  InAppWebViewController? _webViewPopupController;
  late String url;
  final options = InAppWebViewGroupOptions(
    crossPlatform: InAppWebViewOptions(
        javaScriptCanOpenWindowsAutomatically: true,
        javaScriptEnabled: true,
        useOnDownloadStart: true,
        useOnLoadResource: true,
        preferredContentMode: UserPreferredContentMode.MOBILE,
        useShouldOverrideUrlLoading: true,
        mediaPlaybackRequiresUserGesture: true,
        allowFileAccessFromFileURLs: true,
        allowUniversalAccessFromFileURLs: true),
    android: AndroidInAppWebViewOptions(
      supportMultipleWindows: true,
    ),
    ios: IOSInAppWebViewOptions(
      allowsAirPlayForMediaPlayback: true,
      suppressesIncrementalRendering: true,
      ignoresViewportScaleLimits: true,
      selectionGranularity: IOSWKSelectionGranularity.DYNAMIC,
      isPagingEnabled: true,
      enableViewportScale: true,
      sharedCookiesEnabled: true,
      automaticallyAdjustsScrollIndicatorInsets: true,
      useOnNavigationResponse: true,
      allowsInlineMediaPlayback: true,
    ),
  );

  @override
  void initState() {
    super.initState();
    url = widget.url;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          child: InAppWebView(
            initialUrlRequest: URLRequest(url: Uri.parse(widget.url)),
            initialOptions: options,
            onWebViewCreated: (InAppWebViewController controller) {
              _webViewController = controller;
            },
            iosOnNavigationResponse: (controller, response) async {
              return IOSNavigationResponseAction.ALLOW;
            },

            onLoadStart: (controller, Uri? uri) {
              print("Load Started: $uri");
            },
            onCreateWindow: (controller, createWindowRequest) async {
              showDialog(
                context: context,
                builder: (context) {
                  return AlertDialog(
                    content: SizedBox(
                      width: MediaQuery.of(context).size.width,
                      height: 400,
                      child: InAppWebView(
                        // Setting the windowId property is important here!
                        windowId: createWindowRequest.windowId,
                        initialOptions: options,
                        onWebViewCreated: (InAppWebViewController controller) {
                          _webViewPopupController = controller;
                        },

                        onLoadStart:
                            (InAppWebViewController controller, Uri? url) {
                          print("onLoadStart popup $url");
                        },
                        onLoadStop:
                            (InAppWebViewController controller, Uri? url) {
                          print("onLoadStop popup $url");
                          
                        },
                      ),
                    ),
                  );
                },
              );

              return true;
            },
          ),
        ),
      ),
    );
  }

}

解决方法

1. 开启iOS多窗口支持

在IOSInAppWebViewOptions中明确添加多窗口支持配置,确保JavaScript可以自动打开新窗口:

ios: IOSInAppWebViewOptions(
  // 保留原有配置项
  allowsAirPlayForMediaPlayback: true,
  suppressesIncrementalRendering: true,
  ignoresViewportScaleLimits: true,
  selectionGranularity: IOSWKSelectionGranularity.DYNAMIC,
  isPagingEnabled: true,
  enableViewportScale: true,
  sharedCookiesEnabled: true,
  automaticallyAdjustsScrollIndicatorInsets: true,
  useOnNavigationResponse: true,
  allowsInlineMediaPlayback: true,
  // 新增以下两项关键配置
  supportsMultipleWindows: true,
  javaScriptCanOpenWindowsAutomatically: true,
),

2. 优化弹窗创建逻辑

调整弹窗的展示时机与布局,确保WebView正确绑定窗口ID,同时添加支付结果的回调处理:

onCreateWindow: (controller, createWindowRequest) async {
  // 延迟弹窗展示,确保WebView初始化完成
  await Future.delayed(const Duration(milliseconds: 100));
  
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (context) {
      return AlertDialog(
        insetPadding: const EdgeInsets.symmetric(horizontal: 10),
        contentPadding: EdgeInsets.zero,
        content: SizedBox(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height * 0.7,
          child: InAppWebView(
            windowId: createWindowRequest.windowId,
            initialOptions: InAppWebViewGroupOptions(
              crossPlatform: InAppWebViewOptions(
                javaScriptEnabled: true,
                javaScriptCanOpenWindowsAutomatically: true,
                useShouldOverrideUrlLoading: true,
              ),
              ios: IOSInAppWebViewOptions(
                supportsMultipleWindows: true,
              ),
            ),
            onWebViewCreated: (InAppWebViewController popupController) {
              _webViewPopupController = popupController;
            },
            onLoadStop: (controller, url) async {
              print("弹窗加载完成: $url");
              // 检测支付结果URL,关闭弹窗并处理逻辑
              if (url != null && (url.toString().contains('success') || url.toString().contains('failure'))) {
                Navigator.pop(context);
                // 这里可以添加支付结果的后续处理,比如通知原页面更新状态
              }
            },
          ),
        ),
      );
    },
  );
  return true;
},

3. 补充Info.plist配置

添加RazorPay的URL Scheme支持,确保可以正常唤起相关链接:

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>razorpay</string>
</array>

4. 日志调试

在关键回调中添加详细日志,确认弹窗触发与URL加载情况:

onCreateWindow: (controller, createWindowRequest) async {
  print("触发弹窗创建,请求URL: ${createWindowRequest.request.url}");
  // 弹窗代码...
},

内容的提问来源于stack exchange,提问作者Agnel Selvan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 14:24:18