Flutter财务管理插件invoiceninja的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter财务管理插件invoiceninja的使用

描述

通过Flutter应用创建PDF发票并接受付款。

Sample

功能

  • 在移动、Web和桌面Flutter应用中接受在线支付。
  • 支持多种支付网关,包括Stripe、PayPal等。
  • 创建专业的PDF发票。
  • 包含一个自助服务客户端门户。
  • 更多功能…

安装

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

dependencies:
  invoiceninja: ^0.0.10

导入

在你的Dart文件中导入包:

import 'package:invoiceninja/invoiceninja.dart';

该包提供了两个主要类:

  • InvoiceNinja: 支持公共“店面”路由,允许读取产品列表并创建/查找客户和发票。使用此类时访问权限受限。
  • InvoiceNinjaAdmin: 支持REST Admin API,使用基于令牌的安全机制。使用此类需要API令牌来访问账户。

Storefront API配置

// 配置公司密钥和URL
InvoiceNinja.configure(
  'KEY', // 设置您的公司密钥或使用'KEY'进行测试
  url: 'https://demo.invoiceninja.com', // 设置您自己的应用程序URL
  debugEnabled: true, // 启用调试模式
);

加载产品列表

final products = await InvoiceNinja.products.load(); // 异步加载产品列表

按键查找产品

final product = await InvoiceNinja.products.findByKey('product_key'); // 根据产品键查找产品

创建/保存客户

var client = Client.forContact(email: 'test@example.com'); // 创建客户对象
client = await InvoiceNinja.clients.save(client); // 保存客户到服务器

创建/保存发票

var invoice = Invoice.forClient(client, products: [product]); // 创建发票对象
invoice = await InvoiceNinja.invoices.save(invoice); // 保存发票到服务器

显示PDF发票

launch(
  'https://docs.google.com/gview?embedded=true&url=${invoice.pdfUrl}',
  forceWebView: true,
); // 打开PDF发票链接

接受付款

var invoiceKey = invoice.key;
launch(invoice.url);

// ...

final invoice = await InvoiceNinja.invoices.findByKey(invoiceKey);
if (invoice.isPaid) {
  // 处理已支付的发票逻辑
}

Admin API配置

// 配置API令牌和URL
InvoiceNinjaAdmin.configure(
  'TOKEN', // 设置您的API令牌或使用'TOKEN'进行测试
  url: 'https://demo.invoiceninja.com', // 设置您自己的应用程序URL
  debugEnabled: true, // 启用调试模式
);

按电子邮件查找客户

final client = await InvoiceNinjaAdmin.clients.findByEmail(email); // 根据电子邮件查找客户

加载所有发票

final payments = await InvoiceNinjaAdmin.payments.load(); // 加载所有支付记录

加载支付列表

final payments = await InvoiceNinjaAdmin.payments.load(); // 加载支付列表

按ID查找支付

final payment = await InvoiceNinjaAdmin.payments.findById(id); // 根据ID查找支付

创建/保存发票并自动计费

var invoice = Invoice.forClient(client, products: [product]);
invoice = await InvoiceNinjaAdmin.invoices.save(invoice, action: InvoiceAction.autoBill); // 创建并保存发票,同时自动计费

示例代码

以下是完整的示例代码,展示了如何使用invoiceninja插件创建和管理发票:

import 'package:flutter/material.dart';
import 'package:invoiceninja/invoiceninja.dart';
import 'package:invoiceninja/models/client.dart';
import 'package:invoiceninja/models/invoice.dart';
import 'package:invoiceninja/models/product.dart';
import 'package:url_launcher/url_launcher.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Invoice Ninja',
      theme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key}) : super(key: key);

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

class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  List<Product> _products = [];

  String _email = '';
  Product? _product;
  Invoice? _invoice;

  [@override](/user/override)
  initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);

    // 配置Invoice Ninja
    InvoiceNinja.configure(
      'KEY', // 设置您的公司密钥或使用'KEY'进行测试
      url: 'https://demo.invoiceninja.com', // 设置您自己的应用程序URL
      debugEnabled: true,
    );

    // 加载产品列表
    InvoiceNinja.products.load().then((products) {
      setState(() {
        _products = products;
      });
    });
  }

  void _createInvoice() async {
    if (_product == null) {
      return;
    }

    // 创建并保存客户
    var client = Client.forContact(email: _email);
    client = await InvoiceNinja.clients.save(client);

    // 创建并保存发票
    var invoice = Invoice.forClient(client, products: [_product!]);
    invoice = await InvoiceNinja.invoices.save(invoice);

    setState(() {
      _invoice = invoice;
    });
  }

  void _viewPdf() {
    if (_invoice == null) {
      return;
    }

    // 查看PDF发票
    launch(
      'https://docs.google.com/gview?embedded=true&url=${_invoice!.pdfUrl}',
      forceWebView: true,
    );
  }

  void _viewPortal() {
    if (_invoice == null) {
      return;
    }

    final invitation = _invoice!.invitations.first;
    launch(invitation.url);
  }

  [@override](/user/override)
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    if (_invoice == null || state != AppLifecycleState.resumed) {
      return;
    }

    final invoice = await InvoiceNinja.invoices.findByKey(_invoice!.key);

    if (invoice.isPaid) {
      // 处理已支付的发票逻辑
    }
  }

  [@override](/user/override)
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Invoice Ninja Example'),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  TextFormField(
                    decoration: InputDecoration(
                      labelText: 'Email',
                      suffixIcon: Icon(Icons.email),
                    ),
                    onChanged: (value) => setState(() => _email = value),
                    keyboardType: TextInputType.emailAddress,
                  ),
                  DropdownButtonFormField<Product>(
                    decoration: InputDecoration(
                      labelText: 'Product',
                    ),
                    onChanged: (value) => setState(() => _product = value),
                    items: _products
                        .map((product) => DropdownMenuItem(
                              child: Text(product.productKey),
                              value: product,
                            ))
                        .toList(),
                  ),
                  SizedBox(height: 16),
                  OutlinedButton(
                    child: Text('Create Invoice'),
                    onPressed: (_email.isNotEmpty && _product != null)
                        ? () => _createInvoice()
                        : null,
                  ),
                  OutlinedButton(
                    child: Text('View PDF'),
                    onPressed: (_invoice != null) ? () => _viewPdf() : null,
                  ),
                  OutlinedButton(
                    child: Text('View Portal'),
                    onPressed: (_invoice != null) ? () => _viewPortal() : null,
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

更多关于Flutter财务管理插件invoiceninja的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter财务管理插件invoiceninja的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于在Flutter项目中使用Invoiceninja财务管理插件,下面是一个简单的代码示例,展示如何集成和使用该插件(假设Invoiceninja有一个官方的Flutter插件或者可以通过HTTP API进行交互)。由于Invoiceninja主要是一个SaaS服务,更多时候我们可能通过其API进行集成。以下是一个通过HTTP请求与Invoiceninja API交互的示例。

首先,确保在pubspec.yaml文件中添加必要的依赖项,比如http用于发送网络请求:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.3  # 确保使用最新版本

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

接下来,创建一个Dart文件来处理与Invoiceninja API的交互。例如,创建一个名为invoiceninja_api.dart的文件:

import 'dart:convert';
import 'package:http/http.dart' as http;

class InvoiceninjaApi {
  static const String apiUrl = 'https://your-invoiceninja-instance.com/api/v1';
  static const String apiKey = 'your-api-key-here';  // 请替换为你的API密钥

  Future<Map<String, dynamic>> getClient(String clientId) async {
    final response = await http.get(
      Uri.parse('$apiUrl/clients/$clientId'),
      headers: <String, String>{
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $apiKey',
      },
    );

    if (response.statusCode == 200) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to fetch client: ${response.statusCode}');
    }
  }

  Future<Map<String, dynamic>> createInvoice({
    required String clientId,
    required String number,
    required double amount,
    required String date,
  }) async {
    final body = jsonEncode(<String, dynamic>{
      'client_id': clientId,
      'number': number,
      'amount': amount,
      'date': date,
    });

    final response = await http.post(
      Uri.parse('$apiUrl/invoices'),
      headers: <String, String>{
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $apiKey',
      },
      body: body,
    );

    if (response.statusCode == 201) {
      return jsonDecode(response.body);
    } else {
      throw Exception('Failed to create invoice: ${response.statusCode}');
    }
  }
}

在Flutter应用的某个地方,比如一个按钮点击事件中,你可以调用上述API方法来获取客户或创建发票:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Invoiceninja Integration'),
        ),
        body: Center(
          child: MyHomePage(),
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final InvoiceninjaApi _api = InvoiceninjaApi();

  void _fetchClient() async {
    try {
      final client = await _api.getClient('client-id-here');  // 替换为实际的客户端ID
      print('Fetched client: $client');
    } catch (e) {
      print('Error: $e');
    }
  }

  void _createInvoice() async {
    try {
      final invoice = await _api.createInvoice(
        clientId: 'client-id-here',  // 替换为实际的客户端ID
        number: 'INV001',
        amount: 100.0,
        date: '2023-10-10',
      );
      print('Created invoice: $invoice');
    } catch (e) {
      print('Error: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        ElevatedButton(
          onPressed: _fetchClient,
          child: Text('Fetch Client'),
        ),
        SizedBox(height: 20),
        ElevatedButton(
          onPressed: _createInvoice,
          child: Text('Create Invoice'),
        ),
      ],
    );
  }
}

请注意,以上代码中的API URL和API密钥需要替换为你自己的Invoiceninja实例和API密钥。此外,确保你已经在Invoiceninja后台为你的应用生成了API密钥,并且API密钥具有执行这些操作的权限。

这个例子仅展示了基本的HTTP请求。如果Invoiceninja提供了官方的Flutter插件,那么集成方式可能会有所不同,通常会更简单且更符合Flutter的开发习惯。请参考官方文档以获取更多信息和最新的API端点。

回到顶部