Flutter电商集成插件shopify_flutter的使用

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

Flutter电商集成插件shopify_flutter的使用

shopify_flutter

Analyzer status

shopify_flutter 是一个Flutter包,它作为Shopify商店和Flutter应用程序之间的桥梁。通过这个包,您可以轻松地将您的Shopify在线商店与移动应用连接起来。

如何使用

创建私有应用

首先,在您的Shopify商店中创建一个私有应用。请按照此文档进行操作以开始。在创建Storefront API访问令牌时,请确保检查所有API权限,因为某些查询和变更需要对像产品标签这样的对象具有权限。

配置ShopifyConfig

接下来,配置ShopifyConfig

void main() {
  
  ShopifyConfig.setConfig(
    storefrontAccessToken: '*******************',
    storeUrl: '*****.myshopify.com',

    // 可选 | 仅在需要调用Admin API时需要
    adminAccessToken: "shpat_*******************", 

    // 可选 | 默认值:2024-07
    storefrontApiVersion: '2024-07',

    // 可选 | 默认值:null
    cachePolicy: CachePolicy.cacheAndNetwork,

     // 商店语言 | 默认值:en
    language: 'en',
  );
  
  runApp(MyApp());
}

adminAccessToken仅用于如deleteCustomer()等Admin API调用。如果您不使用这些功能,则不需要提供它。

storefrontApiVersion默认版本设置为’2024-07’。

language默认为’en’。这是商店支持的语言代码,默认情况下是商店的语言。只有当商店支持提供的语言代码时才会生效。


以下是shopify_flutter提供的主要实例及其方法,帮助您与Shopify Storefront API交互:

Shopify Auth

用于处理用户认证相关操作:

ShopifyAuth shopifyAuth = ShopifyAuth.instance;

Future<ShopifyUser> signInWithEmailAndPassword({required String email, required String password});
Future<ShopifyUser> createUserWithEmailAndPassword({required String email, required String password, required String phone, String? firstName, String? lastName, bool? acceptsMarketing});
Future<void> signOutCurrentUser();
Future<void> sendPasswordResetEmail({required String email});
Future<ShopifyUser> currentUser({bool forceRefresh = false});
Future<void> deleteCustomer({required String userId});
Future<String?> get currentCustomerAccessToken;
Future<bool> get isAccessTokenExpired;
Future<AccessTokenWithExpDate?> get accessTokenWithExpDate;

Shopify Store

用于获取产品、集合、店铺信息等:

ShopifyStore shopifyStore = ShopifyStore.instance;

Future<List<Product>> getProductsByIds();
Future<List<Product>> getXProductsAfterCursor(int limit, String startCursor);
Future<List<Product>> getAllProducts();
Future<List<Product>> getNProducts({required int n, required SortKey sortKey});
Future<Shop> getShop();
Future<Collection> getCollectionById(String collectionId);
Future<List<Collection>> getAllCollections();
Future<List<Product>> getAllProductsFromCollectionById(String id);
Future<List<Product>> getAllProductsOnQuery(String cursor, SortKeyProduct sortKey, String query);
Future<List<Product>> getXProductsOnQueryAfterCursor(String cursor, int limit, SortKeyProduct sortKey, String query);

/// 过滤可用查询
Future<List<Product>> getXProductsAfterCursorWithinCollection(String id, int limit, String startCursor, SortKeyProduct sortKey, Map<String, dynamic>? filters);
Future<List<Product>?> searchProducts(String query, {int limit = 15, String? startCursor, SearchSortKeys sortKey = SearchSortKeys.RELEVANCE, bool reverse = false, Map<String, dynamic>? filters});

Shopify Checkout (已弃用)

在Shopify API版本2024-07中已弃用。请改用ShopifyCart

Shopify Cart

用于购物车管理:

ShopifyCart shopifyCart = ShopifyCart.instance;

Future<Cart> getCartById(String cartId);
Future<Cart> createCart(CartInput cartInput);
Future<Cart> addLineItemsToCart({required String cartId, required List<CartLineInput> cartLineInputs});
Future<Cart> removeLineItemsFromCart({required String cartId, required List<String> lineIds });
Future<Cart> updateLineItemsInCart({ required String cartId, required List<CartLineInput> cartLineInputs });
Future<Cart> updateNoteInCart({ required String cartId, required String note });
Future<Cart> updateCartDiscountCodes({ required String cartId, required List<String> discountCodes });
Future<Cart> updateBuyerIdentityInCart({ required String cartId, required CartBuyerIdentityInput buyerIdentity });

Shopify Order

用于订单管理:

ShopifyOrder shopifyOrder = ShopifyOrder.instance;

Future<List<Order>> getAllOrders({String customerAccessToken});

Shopify Customer

用于客户信息管理:

ShopifyCustomer shopifyCustomer = ShopifyCustomer.instance;

Future<void> customerAddressUpdate({String address1, String address2, String company, String city, String country, String firstName, String lastName, String phone, String province, String zip, String customerAccessToken, id});
Future<void> customerUpdate({String email, String firstName, String lastName, String password, String phoneNumber, String customerAccessToken, bool acceptsMarketing});
Future<void> customerAddressCreate({String address1, String address2, String company, String city, String country, String firstName, String lastName, String phone, String province, String zip, String customerAccessToken});
Future<void> customerAddressDelete({String customerAccessToken, String addressId});
Future<void> customerDefaultAddressUpdate({required String addressId, required String customerAccessToken});

Shopify Blog

用于博客管理:

ShopifyBlog shopifyBlog = ShopifyBlog.instance;

Future<List<Blog>> getAllBlogs();
Future<Blog> getBlogByHandle(String handle, SortKeyArticle sortKeyArticle);
Future<List<Article>> getXArticlesSorted({int articleAmount, SortKeyArticle sortKeyArticle});

Shopify Page

用于页面管理:

ShopifyPage shopifyPage = ShopifyPage.instance;

Future<List<Page>> getAllPages();
Future<Page> getPageByHandle(String handle);

Shopify Localization

用于本地化设置:

ShopifyLocalization shopifyLocalizatoin = ShopifyLocalization.instance;

Future<List<Page>> getLocalization();

// 用于更改货币单位。例如:"US", "NP", "JP"等。只有当商店支持提供的货币时才会生效。
void setCountryCode(String? countryCode);

Shopify Custom

用于自定义查询和变更:

ShopifyCustom shopifyCustom = ShopifyCustom.instance;

Future<Map<String, dynamic>?> customQuery({required String gqlQuery, Map<String, dynamic> variables = const {}, bool adminAccess = false});
Future<Map<String, dynamic>?> customMutation({required String gqlMutation, Map<String, dynamic> variables = const {}, bool adminAccess = false});

示例代码

以下是一个完整的示例demo,展示了如何使用shopify_flutter来构建一个简单的Shopify电商应用:

import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:shopify_flutter/shopify_flutter.dart';

import 'screens/auth_tab.dart';
import 'screens/blog_tab.dart';
import 'screens/collection_tab.dart';
import 'screens/home_tab.dart';
import 'screens/shop_tab.dart';
import 'screens/search_tab.dart';
import 'screens/cart_tab.dart';
import 'screens/orders_tab.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: '.env');

  ShopifyConfig.setConfig(
    storefrontAccessToken: dotenv.env['STOREFRONT_ACCESS_TOKEN'] ?? '',
    storeUrl: dotenv.env['STORE_URL'] ?? '',
    adminAccessToken: dotenv.env['ADMIN_ACCESS_TOKEN'],
    storefrontApiVersion: dotenv.env['STOREFRONT_API_VERSION'] ?? '2023-07',
    cachePolicy: CachePolicy.networkOnly,
    language: dotenv.env['COUNTRY_LOCALE'],
  );

  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Shopify Example',
      theme: ThemeData(primaryColor: Colors.redAccent),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

class MyHomePageState extends State<MyHomePage> {
  int _currentIndex = 0;

  List<Widget> tabs = [
    const HomeTab(),
    const CollectionTab(),
    const SearchTab(),
    const ShopTab(),
    const BlogTab(),
    const CartTab(),
    const OrdersTab(),
    const AuthTab(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _currentIndex,
        children: tabs,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: _onNavigationBarItemClick,
        fixedColor: Theme.of(context).primaryColor,
        unselectedItemColor: Colors.black,
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
          BottomNavigationBarItem(icon: Icon(Icons.category), label: 'Collections'),
          BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
          BottomNavigationBarItem(icon: Icon(Icons.shopify), label: 'Shop'),
          BottomNavigationBarItem(icon: Icon(Icons.book_online_outlined), label: 'Blog'),
          BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), label: 'Cart'),
          BottomNavigationBarItem(icon: Icon(Icons.history), label: 'Orders'),
          BottomNavigationBarItem(icon: Icon(Icons.login), label: 'Login'),
        ],
      ),
    );
  }

  void _onNavigationBarItemClick(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}

以上代码展示了如何初始化Shopify配置,并构建一个包含多个页面(如主页、分类、搜索、商店、博客、购物车、订单和个人资料)的电商应用。每个页面都对应于Shopify商店中的不同部分或功能,使用户能够浏览商品、管理购物车、查看订单历史和个人信息等。


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

1 回复

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


当然,下面是一个关于如何在Flutter电商应用中集成shopify_flutter插件的代码案例。shopify_flutter是一个用于与Shopify Storefront API交互的Flutter插件,可以帮助你轻松地在Flutter应用中集成Shopify商店的功能。

首先,确保你已经在pubspec.yaml文件中添加了shopify_flutter依赖:

dependencies:
  flutter:
    sdk: flutter
  shopify_flutter: ^x.y.z  # 替换为最新版本号

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

接下来,我们需要在Flutter应用中初始化Shopify客户端,并获取商店的产品数据。以下是一个简单的示例代码:

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

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  late ShopifyClient shopifyClient;
  late List<Product> products;
  late bool isLoading = true;
  late String errorMessage = "";

  @override
  void initState() {
    super.initState();
    initShopifyClient();
  }

  void initShopifyClient() async {
    // 替换为你的Shopify域名和访问令牌
    final domain = "your-shop-name.myshopify.com";
    final storefrontAccessToken = "your-storefront-access-token";

    shopifyClient = ShopifyClient(
      domain: domain,
      storefrontAccessToken: storefrontAccessToken,
    );

    try {
      // 获取前10个产品
      final productResult = await shopifyClient.queryGraphql(
        query: """
        query {
          products(first: 10) {
            edges {
              node {
                id
                title
                handle
                descriptionHtml
                images(first: 1) {
                  edges {
                    node {
                      id
                      originalSrc
                    }
                  }
                }
                priceRange {
                  minVariantPrice {
                    amount
                    currencyCode
                  }
                }
              }
            }
          }
        }
        """,
      );

      // 解析结果并设置状态
      if (productResult.data?.products?.edges != null) {
        products = productResult.data!.products!.edges!.map((edge) => Product.fromGraphql(edge.node!)).toList();
      } else {
        products = [];
      }

      setState(() {
        isLoading = false;
      });
    } catch (e) {
      setState(() {
        isLoading = false;
        errorMessage = e.toString();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Shopify Example'),
      ),
      body: isLoading
          ? Center(child: CircularProgressIndicator())
          : Column(
              children: [
                Text(errorMessage, style: TextStyle(color: Colors.red)),
                Expanded(
                  child: ListView.builder(
                    itemCount: products.length,
                    itemBuilder: (context, index) {
                      final product = products[index];
                      return Card(
                        child: ListTile(
                          leading: Image.network(product.images.firstOrNull?.node?.originalSrc ?? ""),
                          title: Text(product.title),
                          subtitle: Text("\$${product.priceRange.minVariantPrice.amount} ${product.priceRange.minVariantPrice.currencyCode}"),
                          trailing: Icon(Icons.arrow_forward),
                          onTap: () {
                            // 导航到产品详情页面
                          },
                        ),
                      );
                    },
                  ),
                ),
              ],
            ),
    );
  }
}

// 定义Product类(根据GraphQL返回的数据结构)
class Product {
  String id;
  String title;
  String handle;
  String descriptionHtml;
  List<Image> images;
  PriceRange priceRange;

  Product({
    required this.id,
    required this.title,
    required this.handle,
    required this.descriptionHtml,
    required this.images,
    required this.priceRange,
  });

  factory Product.fromGraphql(Map<String, dynamic> graphqlNode) {
    return Product(
      id: graphqlNode['id'] as String,
      title: graphqlNode['title'] as String,
      handle: graphqlNode['handle'] as String,
      descriptionHtml: graphqlNode['descriptionHtml'] as String,
      images: graphqlNode['images']['edges']
          ?.map((edge) => Image.fromGraphql(edge['node'] as Map<String, dynamic>))
          ?.toList() ?? [],
      priceRange: PriceRange.fromGraphql(graphqlNode['priceRange'] as Map<String, dynamic>),
    );
  }
}

class Image {
  String id;
  String originalSrc;

  Image({
    required this.id,
    required this.originalSrc,
  });

  factory Image.fromGraphql(Map<String, dynamic> graphqlNode) {
    return Image(
      id: graphqlNode['id'] as String,
      originalSrc: graphqlNode['originalSrc'] as String,
    );
  }
}

class PriceRange {
  MinVariantPrice minVariantPrice;

  PriceRange({
    required this.minVariantPrice,
  });

  factory PriceRange.fromGraphql(Map<String, dynamic> graphqlNode) {
    return PriceRange(
      minVariantPrice: MinVariantPrice.fromGraphql(graphqlNode['minVariantPrice'] as Map<String, dynamic>),
    );
  }
}

class MinVariantPrice {
  String amount;
  String currencyCode;

  MinVariantPrice({
    required this.amount,
    required this.currencyCode,
  });

  factory MinVariantPrice.fromGraphql(Map<String, dynamic> graphqlNode) {
    return MinVariantPrice(
      amount: graphqlNode['amount'] as String,
      currencyCode: graphqlNode['currencyCode'] as String,
    );
  }
}

这个示例展示了如何初始化Shopify客户端,通过GraphQL查询获取产品数据,并在Flutter应用中展示这些产品。请确保替换your-shop-name.myshopify.comyour-storefront-access-token为你的实际Shopify商店域名和访问令牌。

希望这个示例能帮助你在Flutter应用中集成Shopify功能!

回到顶部