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

Flutter Web端flutter_inappwebview加载Stripe页面失败问题排查

问题排查:Flutter Web Release模式下flutter_inappwebview加载Stripe页面失败

问题现象

  • 使用flutter_inappwebview: 6.0.0-beta.22包实现App内WebView加载Stripe开户流程,Android模拟器上可正常加载,但Web Release模式(启动命令:flutter run -d chrome --release --web-hostname localhost --web-port 5000)下页面无法加载。
  • 控制台报错:
url is: https://connect.stripe.com/setup/c/acct_1MFXNcFwHPwkSrfO/jug2SEGbwzAq
NoSuchMethodError: method not found: 'toString' on null
js_primitives.dart:47     at a6J.aA (http://localhost:5000/main.dart.js?version=9:56217:6)
js_primitives.dart:47     at fY.Gq (http://localhost:5000/main.dart.js?version=9:82446:12)
js_primitives.dart:47     at fY.e0 (http://localhost:5000/main.dart.js?version=9:82409:6)
js_primitives.dart:47     at IQ.Cc (http://localhost:5000/main.dart.js?version=9:82306:3)
js_primitives.dart:47     at IQ.eK (http://localhost:5000/main.dart.js?version=9:82255:16)
js_primitives.dart:47     at IQ.e0 (http://localhost:5000/main.dart.js?version=9:82634:8)
js_primitives.dart:47     at Ai.Cc (http://localhost:5000/main.dart.js?version=9:82306:3)
js_primitives.dart:47     at Ai.eK (http://localhost:5000/main.dart.js?version=9:82255:16)
js_primitives.dart:47     at Ai.kE (http://localhost:5000/main.dart.js?version=9:82417:32)
js_primitives.dart:47     at Ai.wy (http://localhost:5000/main.dart.js?version=9:82382:6)
  • 点击报错中的js_primitives.dart:47链接时,显示:
Could not load content for org-dartlang-sdk:///lib/_internal/js_runtime/lib/js_primitives.dart (Fetch through target failed: Unsupported URL scheme; Fallback: HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME)
  • 初始化时打印的URL是正确的。

相关代码

页面Dart代码

import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:universal_platform/universal_platform.dart';
import 'package:url_launcher/url_launcher_string.dart';
import '../utilities.dart';

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

  @override
  State<StripeOnboardScreen> createState() => _StripeOnboardScreenState();
}

class _StripeOnboardScreenState extends State<StripeOnboardScreen> {
  dynamic backButton = UniversalPlatform.isWeb
      ? UniversalPlatform.isIOS
          ? CupertinoIcons.back
          : Icons.arrow_back
      : Icons.arrow_back;
  double fontSize = Utilities.fontSize;

  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;
InAppWebViewSettings settings = InAppWebViewSettings(
      javaScriptEnabled: true,
      javaScriptCanOpenWindowsAutomatically: true,
      useShouldOverrideUrlLoading: true,
      mediaPlaybackRequiresUserGesture: false,
      allowsInlineMediaPlayback: true,
      iframeAllow: "camera; microphone",
      iframeAllowFullscreen: true);
late PullToRefreshController pullToRefreshController;
  double progress = 0;
  // Create a webview controller to control the webview and get information
  // about its current state
  final urlController = TextEditingController();
  @override
  void initState() {
    super.initState();
    print('url is: ${widget.onboardUrl}');
    pullToRefreshController = (kIsWeb
        ? null
        : PullToRefreshController(
            settings: PullToRefreshSettings(
              color: Colors.blue,
            ),
          ))!;
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        elevation: 0,
        // Show a "Back" button in the app bar if the webview is displaying
        // a page other than the initial page
        leading: IconButton(
            icon: Icon(backButton),
            color: Colors.redAccent,
            onPressed: () {
              Navigator.pop(context);
            }),
      ),
      body: Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: InAppWebView(
          key: webViewKey,
          initialUrlRequest: URLRequest(
              url: WebUri(widget.onboardUrl, forceToStringRawValue: true)),
          initialSettings: settings,
          pullToRefreshController: pullToRefreshController,
          onWebViewCreated: (controller) {
            webViewController = controller;
          },
          onLoadStart: (controller, url) {
            setState(() {
              urlController.text = widget.onboardUrl;
            });
          },
          onPermissionRequest: (controller, request) async {
            return PermissionResponse(
                resources: request.resources,
                action: PermissionResponseAction.GRANT);
          },
          shouldOverrideUrlLoading: (controller, navigationAction) async {
            var uri = navigationAction.request.url!;

            if (![
              "http",
              "https",
              "file",
              "chrome",
              "data",
              "javascript",
              "about"
            ].contains(uri.scheme)) {
              await canLaunchUrlString(widget.onboardUrl)
                  ? await launchUrlString(widget.onboardUrl)
                  : throw 'Could not launch ${widget.onboardUrl}';
              // and cancel the request
              return NavigationActionPolicy.CANCEL;
            }
            return NavigationActionPolicy.ALLOW;
          },
          onConsoleMessage: (controller, consoleMessage) {
            print('consoleMessage is : $consoleMessage');
          },
        ),
      ),
    );
  }
}

index.html配置

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>fixit</title>

    <!--  <meta name="google-signin-client_id" content="YOUR_GOOGLE_SIGN_IN_OAUTH_CLIENT_ID.apps.googleusercontent.com">-->
    <meta name="google-signin-client_id"
          content="147151203258-clupo1g18oueig38uq8nts5mnkgug13e.apps.googleusercontent.com">
    <!--  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
    <script type="application/javascript" src="/assets/packages/flutter_inappwebview/assets/web/web_support.js" defer></script>
</head>
<!--<body>-->
<body id="app-container">
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-app.js"></script>

<!-- TODO: Add SDKs for Firebase products that you want to use
     https://firebase.google.com/docs/web/setup#available-libraries -->
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-messaging.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-storage.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.1/firebase-remote-config.js"></script>
<script>
    // Your web app's Firebase configuration
    var firebaseConfig = {
      apiKey: "xx",
          authDomain: "xx",
          databaseURL: "xx",
          projectId: "xx",
          storageBucket: "xx",
          messagingSenderId: "xx",
          appId: "xx",
          measurementId: "xx"
    };
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
<!--    firebase.analytics();-->

</script>
<script>
if ("serviceWorker" in navigator) {
  window.addEventListener("load", function () {
     //navigator.serviceWorker.register("/flutter_service_worker.js");
    navigator.serviceWorker.register("/firebase-messaging-sw.js");
  });
}

</script>
<script src="main.dart.js?version=9" type="application/javascript"></script>
</body>
</html>

Flutter环境信息

[✓] Flutter (Channel stable, 3.3.9, on macOS 12.5.1 21G83 darwin-arm, locale en-IT)
    • Flutter version 3.3.9 on channel stable at /Users/vincenzocalia/development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (3 weeks ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
    • Android SDK at /Users/vincenzocalia/Library/Android/sdk
    • Platform android-33, build-tools 32.1.0-rc1
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 13F100
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+0-b1504.28-7817840)

[✓] VS Code (version 1.73.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (3 available)
    • sdk gphone64 arm64 (mobile) • emulator-5554 • android-arm64  • Android 12 (API 31) (emulator)
    • macOS (desktop)             • macos         • darwin-arm64   • macOS 12.5.1 21G83 darwin-arm
    • Chrome (web)                • chrome        • web-javascript • Google Chrome 108.0.5359.124
                                                                                                                                                                                                                                              HTTP Host availability check is taking a long time...[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

排查与修复方案

1. 修复PullToRefreshController空指针问题

Web环境下PullToRefreshController不被支持,当前代码通过强制空断言!将null赋值给late类型的变量,导致后续调用toString时触发空指针错误。

修改代码:

// 将late改为可空类型
PullToRefreshController? pullToRefreshController;

@override
void initState() {
  super.initState();
  print('url is: ${widget.onboardUrl}');
  // 仅在非Web环境初始化控制器
  if (!kIsWeb) {
    pullToRefreshController = PullToRefreshController(
      settings: PullToRefreshSettings(
        color: Colors.blue,
      ),
    );
  }
}

同时保持InAppWebView中的pullToRefreshController: pullToRefreshController,不变。

2. 调整WebUri初始化方式

Web环境下使用WebUri(widget.onboardUrl, forceToStringRawValue: true)可能存在兼容性问题,改用标准的解析方式:

initialUrlRequest: URLRequest(
  url: WebUri.parse(widget.onboardUrl),
),

3. 修正shouldOverrideUrlLoading中的跳转逻辑

当前代码中,非指定scheme的URL会打开初始的Stripe链接,而非当前要跳转的目标URL,修改为:

shouldOverrideUrlLoading: (controller, navigationAction) async {
  var uri = navigationAction.request.url!;

  if (![
    "http",
    "https",
    "file",
    "chrome",
    "data",
    "javascript",
    "about"
  ].contains(uri.scheme)) {
    await canLaunchUrlString(uri.toString())
        ? await launchUrlString(uri.toString())
        : throw 'Could not launch ${uri.toString()}';
    return NavigationActionPolicy.CANCEL;
  }
  return NavigationActionPolicy.ALLOW;
},

4. 调整web_support.js加载顺序

确保web_support.js在main.dart.js之前加载,去掉defer属性,避免加载顺序问题:

<script type="application/javascript" src="/assets/packages/flutter_inappwebview/assets/web/web_support.js"></script>
<!-- 放在main.dart.js之前 -->
<script src="main.dart.js?version=9" type="application/javascript"></script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:10:28