Flutter集成LeanCloud服务插件lean_sdk_flutter的使用

Flutter集成LeanCloud服务插件lean_sdk_flutter的使用

在本教程中,我们将介绍如何在Flutter应用中集成LeanCloud服务,并使用lean_sdk_flutter插件。我们将通过一个完整的示例来演示如何连接银行账户、创建支付源、重新连接银行账户以及完成支付。

环境配置

首先,确保你已经在项目中添加了lean_sdk_flutter插件。你可以通过以下两种方式之一来安装该插件:

使用命令行安装

打开终端并运行以下命令:

flutter pub add lean_sdk_flutter

手动添加到pubspec.yaml

在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  lean_sdk_flutter: ^3.0.6

然后执行以下命令以更新依赖项:

flutter pub get

示例代码

以下是完整的示例代码,展示了如何在Flutter应用中使用lean_sdk_flutter插件。

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:go_router/go_router.dart';
import 'package:lean_sdk_flutter/lean_sdk_flutter.dart';

void main() {
  runApp(const MyApp());
}

/// 路由配置。
final GoRouter _router = GoRouter(
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return const HomeScreen();
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'app/flutter/connect/success',
          builder: (BuildContext context, GoRouterState state) {
            return const SuccessScreen();
          },
        ),
        GoRoute(
          path: 'app/flutter/connect/fail',
          builder: (BuildContext context, GoRouterState state) {
            return const FailScreen();
          },
        ),
      ],
    ),
  ],
);

/// 主应用。
class MyApp extends StatelessWidget {
  /// 构造函数。
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
    );
  }
}

/// 主屏幕
class HomeScreen extends StatefulWidget {
  /// 构造函数。
  const HomeScreen({super.key});

  [@override](/user/override)
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final TextEditingController _appTokenController = TextEditingController();
  String appToken = "";

  // 连接
  final TextEditingController _connectCustomerIDController = TextEditingController();
  String connectCustomerID = "";
  final TextEditingController _connectBankIdentifierController = TextEditingController();
  String connectBankIdentifier = "";
  final TextEditingController _connectPaymentDestinationIDController = TextEditingController();
  String connectPaymentDestinationID = "";

  // 重新连接
  final TextEditingController _reconnectIDController = TextEditingController();
  String reconnectID = "";

  // 创建受益人
  final TextEditingController _customerIDController = TextEditingController();
  String customerID = "";
  final TextEditingController _paymentSourceIDController = TextEditingController();
  String paymentSourceID = "";
  final TextEditingController _paymentDestinationIDController = TextEditingController();
  String paymentDestinationID = "";

  // 支付
  bool isShowBalances = false;
  final TextEditingController _accountIdController = TextEditingController();
  String accountId = "";
  final TextEditingController _paymentIntentIDController = TextEditingController();
  String paymentIntentID = "";

  [@override](/user/override)
  Widget build(BuildContext context) {
    var permissions = [
      LeanPermissions.identity,
      LeanPermissions.transactions,
      LeanPermissions.balance,
      LeanPermissions.accounts,
      LeanPermissions.payments
    ];
    var isSandbox = true;
    var environment = 'staging';

    _connect() {
      showDialog(
        context: context,
        builder: (BuildContext context) => Center(
          child: Padding(
            padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
            child: Lean.connect(
              showLogs: true,
              env: environment,
              accessToken: "",
              appToken: appToken,
              isSandbox: isSandbox,
              customerId: connectCustomerID,
              bankIdentifier: connectBankIdentifier,
              paymentDestinationId: connectPaymentDestinationID,
              permissions: permissions,
              failRedirectUrl: "https://cdn.leantech.me/app/flutter/connect/success",
              successRedirectUrl: "https://cdn.leantech.me/app/flutter/connect/fail",
              customization: const {
                "button_text_color": "white",
                "theme_color": "red",
                "button_border_radius": "10",
                "overlay_color": "pink",
              },
              callback: (LeanResponse resp) {
                if (kDebugMode) {
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text("Callback: ${resp.message}"),
                  ));
                }
                Navigator.pop(context);
              },
              actionCancelled: () => Navigator.pop(context),
            ),
          ),
        ),
      );
    }

    _reconnect() {
      showDialog(
        context: context,
        builder: (context) {
          return Padding(
            padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
            child: Lean.reconnect(
              env: environment,
              appToken: appToken,
              reconnectId: reconnectID,
              isSandbox: isSandbox,
              showLogs: true,
              accessToken: "",
              callback: (LeanResponse resp) {
                if (kDebugMode) {
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text("Callback: ${resp.message}"),
                  ));
                }
                Navigator.pop(context);
              },
              actionCancelled: () => Navigator.pop(context),
            ),
          );
        },
      );
    }

    _createPaymentSource() {
      showDialog(
        context: context,
        builder: (BuildContext context) => Center(
          child: Padding(
            padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
            child: SizedBox(
              height: MediaQuery.of(context).size.height * 0.8,
              child: Lean.createPaymentSource(
                env: environment,
                appToken: appToken,
                customerId: customerID,
                paymentSourceId: paymentSourceID,
                paymentDestinationId: paymentDestinationID,
                isSandbox: isSandbox,
                showLogs: true,
                accessToken: "",
                callback: (LeanResponse resp) {
                  if (kDebugMode) {
                    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                      content: Text("Callback: ${resp.message}"),
                    ));
                  }
                  Navigator.pop(context);
                },
                actionCancelled: () => Navigator.pop(context),
              ),
            ),
          ),
        ),
      );
    }

    _pay() {
      showDialog(
        context: context,
        builder: (context) {
          return Padding(
            padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
            child: Lean.pay(
              env: environment,
              appToken: appToken,
              accountId: accountId,
              paymentIntentId: paymentIntentID,
              showBalances: isShowBalances,
              isSandbox: isSandbox,
              showLogs: true,
              accessToken: "",
              callback: (LeanResponse resp) {
                if (kDebugMode) {
                  ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                    content: Text("Callback: ${resp.message}"),
                  ));
                }
                Navigator.pop(context);
              },
              actionCancelled: () => Navigator.pop(context),
            ),
          );
        },
      );
    }

    return SafeArea(
        child: Scaffold(
            backgroundColor: Colors.white,
            body: SingleChildScrollView(
              child: Column(
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Image.asset('assets/images/lean.png', width: 100, height: 100),
                    ],
                  ),
                  Container(
                    margin: const EdgeInsets.all(10.0),
                    padding: const EdgeInsets.only(bottom: 20),
                    decoration: BoxDecoration(
                      color: Colors.grey[200],
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.3),
                          spreadRadius: 2,
                          blurRadius: 2,
                        ),
                      ],
                    ),
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                            child: TextFormField(
                              key: Key('appToken'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '应用令牌',
                              ),
                              controller: _appTokenController,
                              onChanged: (value) {
                                setState(() {
                                  appToken = value;
                                });
                              },
                            ),
                          ),
                        ]),
                  ),
                  Container(
                    margin: const EdgeInsets.all(10.0),
                    padding: const EdgeInsets.only(bottom: 20),
                    decoration: BoxDecoration(
                      color: Colors.grey[200],
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.3),
                          spreadRadius: 2,
                          blurRadius: 2,
                        ),
                      ],
                    ),
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                            child: TextFormField(
                              key: Key('connectCustomerId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '客户ID',
                              ),
                              controller: _connectCustomerIDController,
                              onChanged: (value) {
                                setState(() {
                                  connectCustomerID = value;
                                });
                              },
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                            child: TextFormField(
                              key: Key('connectBankIdentifier'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '银行标识符',
                              ),
                              controller: _connectBankIdentifierController,
                              onChanged: (value) {
                                setState(() {
                                  connectBankIdentifier = value;
                                });
                              },
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.only(bottom: 14, left: 8, right: 8),
                            child: TextFormField(
                              key: Key('connectPaymentDestinationId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '支付目的地ID',
                              ),
                              controller: _connectPaymentDestinationIDController,
                              onChanged: (value) {
                                setState(() {
                                  connectPaymentDestinationID = value;
                                });
                              },
                            ),
                          ),
                          ElevatedButton(
                            onPressed: () => _connect(),
                            style: _buttonStyle(),
                            child: const Text('连接'),
                          ),
                        ]),
                  ),
                  Container(
                    margin: const EdgeInsets.all(10.0),
                    padding: const EdgeInsets.only(bottom: 20),
                    decoration: BoxDecoration(
                      color: Colors.grey[200],
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.3),
                          spreadRadius: 2,
                          blurRadius: 2,
                        ),
                      ],
                    ),
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Padding(
                            padding: const EdgeInsets.only(bottom: 14, left: 8, right: 8),
                            child: TextFormField(
                              key: Key('reconnectId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '重新连接ID',
                              ),
                              controller: _reconnectIDController,
                              onChanged: (value) {
                                setState(() {
                                  reconnectID = value;
                                });
                              },
                            ),
                          ),
                          ElevatedButton(
                            onPressed: () => _reconnect(),
                            style: _buttonStyle(),
                            child: const Text('重新连接'),
                          ),
                        ]),
                  ),
                  Container(
                    margin: const EdgeInsets.all(10.0),
                    padding: const EdgeInsets.only(bottom: 20),
                    decoration: BoxDecoration(
                      color: Colors.grey[200],
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.3),
                          spreadRadius: 2,
                          blurRadius: 2,
                        ),
                      ],
                    ),
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                            child: TextFormField(
                              key: Key('createBeneficiaryCustomerId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '客户ID',
                              ),
                              controller: _customerIDController,
                              onChanged: (value) {
                                setState(() {
                                  customerID = value;
                                });
                              },
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                            child: TextFormField(
                              key: Key('createBeneficiaryPaymentSourceId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '支付来源ID',
                              ),
                              controller: _paymentSourceIDController,
                              onChanged: (value) {
                                setState(() {
                                  paymentSourceID = value;
                                });
                              },
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.only(bottom: 14, left: 8, right: 8),
                            child: TextFormField(
                              key: Key('createBeneficiaryPaymentDestinationId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '支付目的地ID',
                              ),
                              controller: _paymentDestinationIDController,
                              onChanged: (value) {
                                setState(() {
                                  paymentDestinationID = value;
                                });
                              },
                            ),
                          ),
                          ElevatedButton(
                            onPressed: () => _createPaymentSource(),
                            style: _buttonStyle(),
                            child: const Text('创建支付来源'),
                          ),
                        ]),
                  ),
                  Container(
                    margin: const EdgeInsets.all(10.0),
                    padding: const EdgeInsets.only(bottom: 20),
                    decoration: BoxDecoration(
                      color: Colors.grey[200],
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.3),
                          spreadRadius: 2,
                          blurRadius: 2,
                        ),
                      ],
                    ),
                    child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Padding(
                              padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                              child: Row(
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: [
                                  const Text("显示余额"),
                                  Switch(
                                    value: isShowBalances,
                                    onChanged: (value) {
                                      setState(() {
                                        isShowBalances = value;
                                      });
                                    },
                                  ),
                                ],
                              )),
                          Padding(
                            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
                            child: TextFormField(
                              key: Key('payAccountId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '账户ID',
                              ),
                              controller: _accountIdController,
                              onChanged: (value) {
                                setState(() {
                                  accountId = value;
                                });
                              },
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.only(bottom: 14, left: 8, right: 8),
                            child: TextFormField(
                              key: Key('paymentIntentId'),
                              decoration: const InputDecoration(
                                border: UnderlineInputBorder(),
                                labelText: '支付意向ID',
                              ),
                              controller: _paymentIntentIDController,
                              onChanged: (value) {
                                setState(() {
                                  paymentIntentID = value;
                                });
                              },
                            ),
                          ),
                          ElevatedButton(
                            onPressed: () => _pay(),
                            style: _buttonStyle(),
                            child: const Text('支付'),
                          ),
                        ]),
                  ),
                ],
              ),
            )));
  }

  // _cardStyle() =>

  _buttonStyle() => ElevatedButton.styleFrom(
        shape: const StadiumBorder(),
        backgroundColor: Colors.black,
        minimumSize: const Size(200, 40),
        maximumSize: const Size(200, 40),
      );
}

/// 成功屏幕
class SuccessScreen extends StatelessWidget {
  /// 构造函数。
  const SuccessScreen({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('成功')),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text("账户已连接。"),
          ElevatedButton(
            onPressed: () => context.go('/'),
            child: const Text('返回主屏幕'),
          ),
        ],
      )),
    );
  }
}

/// 失败屏幕
class FailScreen extends StatelessWidget {
  /// 构造函数。
  const FailScreen({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('失败')),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text("账户连接失败。"),
          ElevatedButton(
            onPressed: () => context.go('/'),
            child: const Text('返回主屏幕'),
          ),
        ],
      )),
    );
  }
}

更多关于Flutter集成LeanCloud服务插件lean_sdk_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter集成LeanCloud服务插件lean_sdk_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


要在Flutter项目中集成LeanCloud服务,可以使用lean_sdk_flutter插件。以下是详细的使用步骤:

1. 添加依赖

pubspec.yaml文件中添加lean_sdk_flutter插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  lean_sdk_flutter: ^0.0.1 # 使用最新版本

然后运行flutter pub get来安装依赖。

2. 初始化LeanCloud SDK

在Flutter应用的入口文件(通常是main.dart)中初始化LeanCloud SDK:

import 'package:flutter/material.dart';
import 'package:lean_sdk_flutter/lean_sdk_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化LeanCloud SDK
  await LeanSdkFlutter.init(
    appId: 'your-app-id',  // 替换为你的App ID
    appKey: 'your-app-key',  // 替换为你的App Key
    serverUrl: 'https://your-server-url',  // 替换为你的服务器地址
  );
  
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

3. 使用LeanCloud服务

在应用中可以使用LeanCloud提供的各种服务,例如存储对象、查询数据等。

存储对象

import 'package:lean_sdk_flutter/lean_sdk_flutter.dart';

class MyHomePage extends StatelessWidget {
  Future<void> saveObject() async {
    var object = LeanObject('TestObject');
    object.setString('name', 'Flutter');
    object.setInt('age', 3);
    
    await object.save();
    print('Object saved successfully');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('LeanCloud Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: saveObject,
          child: Text('Save Object'),
        ),
      ),
    );
  }
}

查询数据

import 'package:lean_sdk_flutter/lean_sdk_flutter.dart';

class MyHomePage extends StatelessWidget {
  Future<void> queryObjects() async {
    var query = LeanQuery('TestObject');
    query.whereEqualTo('name', 'Flutter');
    
    var results = await query.find();
    for (var obj in results) {
      print('Object ID: ${obj.objectId}, Name: ${obj.getString('name')}, Age: ${obj.getInt('age')}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('LeanCloud Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: queryObjects,
          child: Text('Query Objects'),
        ),
      ),
    );
  }
}

4. 其他功能

lean_sdk_flutter插件还提供了其他功能,如用户管理、文件上传、云函数调用等。具体使用方法可以参考插件的官方文档或源码。

5. 注意事项

  • 确保在LeanCloud控制台中正确配置了应用。
  • 确保网络请求权限已添加到AndroidManifest.xmlInfo.plist中。
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>
回到顶部