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

Flutter集成Pi Network JavaScript SDK遇require.js匹配错误求助

解决Flutter Web集成Pi Network JS SDK时的require.js匹配错误

我在为Pi Network黑客松开发Flutter Web应用,需要集成Pi官方提供的JS SDK,但直接用js.context.callMethod("eval")加载require.js模块时,遇到了以下错误:

Error: Mismatched anonymous define() module: function() { return CanvasKitInit; }

错误原因

Flutter Web默认使用CanvasKit渲染引擎,它内部通过AMD规范的define()定义了匿名模块。而用require.js加载Pi SDK时,require.js会扫描页面中所有的define模块,导致与CanvasKit的匿名模块冲突,触发匹配错误。

解决方案

放弃使用require.js加载SDK,改用直接注入script标签的方式加载Pi SDK,直接访问全局的Pi对象。

方法1:提前在web/index.html中加载SDK

修改web/index.html,在<body>标签内(Flutter脚本之前)添加Pi SDK的script引用:

<body>
  <!-- 添加Pi SDK引用 -->
  <script src="https://sdk.minepi.com/pi-sdk.js"></script>
  
  <script>
    var serviceWorkerVersion = null;
    var scriptLoaded = false;
    function loadMainDartJs() {
      if (scriptLoaded) {
        return;
      }
      scriptLoaded = true;
      var scriptTag = document.createElement('script');
      scriptTag.src = 'main.dart.js';
      scriptTag.type = 'application/javascript';
      document.body.append(scriptTag);
    }
  </script>
  <!-- 其他Flutter默认代码 -->
</body>

然后修改Dart代码,直接调用全局Pi对象:

import 'dart:js' as js;

class Test2 extends StatelessWidget {
  const Test2({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: TextButton(
          child: const Text("click"),
          onPressed: () {
            // 获取全局Pi对象
            final pi = js.context['Pi'];
            if (pi == null) {
              print("Pi SDK未加载完成,请检查网络或加载顺序");
              return;
            }

            // 初始化SDK
            pi.callMethod('init', [js.JsObject.jsify({'version': '2.0'})]);

            // 定义认证需要的回调
            void onIncompletePaymentFound(js.JsObject payment) {
              // 处理未完成支付逻辑
              print('发现未完成支付:${payment.toString()}');
            }

            // 发起认证
            pi.callMethod('authenticate', [
              ['payments'],
              js.allowInterop(onIncompletePaymentFound)
            ]).then((authResult) {
              print('认证成功!可以发起支付了');
            }).catchError((error) {
              print('认证失败:$error');
            });
          },
        ),
      ),
    );
  }
}

方法2:在Dart中动态注入script标签

如果不想修改index.html,可以在Dart代码中动态创建script标签加载SDK:

import 'dart:js' as js;
import 'package:flutter/material.dart';

void loadPiSdk(VoidCallback onLoaded) {
  final script = js.context['document'].callMethod('createElement', ['script']);
  script['src'] = 'https://sdk.minepi.com/pi-sdk.js';
  script['onload'] = js.allowInterop(onLoaded);
  script['async'] = true;
  // 将script插入到head中
  js.context['document'].callMethod('getElementsByTagName', ['head'])[0]
      .callMethod('appendChild', [script]);
}

// 在StatefulWidget的initState中调用加载
class Test2 extends StatefulWidget {
  const Test2({super.key});

  @override
  State<Test2> createState() => _Test2State();
}

class _Test2State extends State<Test2> {
  bool _piLoaded = false;

  @override
  void initState() {
    super.initState();
    loadPiSdk(() {
      setState(() {
        _piLoaded = true;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: _piLoaded
            ? TextButton(
                child: const Text("click"),
                onPressed: () {
                  // 认证逻辑与方法1一致
                  final pi = js.context['Pi'];
                  pi.callMethod('init', [js.JsObject.jsify({'version': '2.0'})]);
                  void onIncompletePaymentFound(js.JsObject payment) {
                    print('发现未完成支付:${payment.toString()}');
                  }
                  pi.callMethod('authenticate', [
                    ['payments'],
                    js.allowInterop(onIncompletePaymentFound)
                  ]).then((_) {
                    print('认证成功!');
                  }).catchError((e) => print('认证失败:$e'));
                },
              )
            : const CircularProgressIndicator(),
      ),
    );
  }
}

关键注意点

  • 必须使用js.allowInterop()包装Dart回调函数,否则JS无法正确调用Dart方法。
  • 确保SDK加载完成后再调用Pi的API,避免出现Pi is undefined的错误。
  • 如果你是开发Flutter移动端(而非Web),这种JS集成方式不适用,移动端需要考虑WebView嵌套等方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:10:44