应用内购买演示应用


欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

适配的第三方库地址:

一、项目概述

运行效果图

image-20260412152754602

image-20260412152800818

image-20260412152806437

image-20260412152813770

image-20260412152819111

image-20260412152823503

image-20260412152828337

1.1 应用简介

应用内购买演示是一款展示完整购买流程的示例应用,帮助开发者了解和掌握应用内购买的实现方式。应用展示了消耗品、非消耗品、订阅三种商品类型的购买流程,包含商品展示、购买验证、购买记录管理、恢复购买等完整功能。用户可以体验真实的购买交互流程,了解应用内购买的最佳实践。

应用以优雅的紫色为主色调,象征尊贵与品质。涵盖商店、我的、记录、设置四大模块。用户可以浏览商品、完成购买、查看记录、管理设置,体验完整的应用内购买流程。

1.2 核心功能

功能模块 功能描述 实现方式
商品展示 展示可购买的商品列表 列表组件
商品分类 消耗品、非消耗品、订阅 分类展示
购买流程 完整的购买交互流程 模拟购买
生物认证 购买前指纹/面容验证 local_auth
购买记录 查看历史购买记录 本地存储
恢复购买 恢复已购买的项目 数据恢复
我的物品 查看已拥有的物品 状态管理
购买动画 流畅的购买交互动画 AnimationController

1.3 商品类型定义

序号 类型名称 描述 特点
1 消耗品 可重复购买的商品 如金币、道具,购买后数量增加
2 非消耗品 一次购买永久拥有 如去广告、主题包,购买后标记已拥有
3 订阅 按周期付费的服务 如VIP会员,有有效期限制

1.4 购买状态定义

序号 状态名称 描述 颜色
1 处理中 购买请求处理中 橙色
2 已完成 购买成功完成 绿色
3 失败 购买失败 红色
4 已恢复 购买记录已恢复 蓝色
5 已取消 用户取消购买 灰色

1.5 商品信息字段

序号 字段名称 是否必填 说明
1 商品ID 唯一标识符
2 商品名称 显示名称
3 商品描述 详细描述
4 价格 商品价格
5 货币符号 可选 默认为¥
6 商品类型 消耗品/非消耗品/订阅
7 图标 可选 商品图标
8 是否热门 可选 标记热门商品
9 折扣信息 可选 显示折扣标签

1.6 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
数据存储 shared_preferences >= 2.2.2
生物认证 local_auth >= 2.3.0
日期格式 intl >= 0.19.0
目标平台 鸿蒙OS / Android / iOS API 21+

1.7 项目结构

lib/
└── main_in_app_purchase.dart
    ├── InAppPurchaseDemoApp        # 应用入口
    ├── ProductType                 # 商品类型枚举
    ├── PurchaseStatus              # 购买状态枚举
    ├── Product                     # 商品模型
    ├── PurchaseRecord              # 购买记录模型
    ├── InAppPurchaseHomePage       # 主页面(底部导航)
    ├── _buildStorePage             # 商店页面
    ├── _buildProductsPage          # 我的物品页
    ├── _buildHistoryPage           # 购买记录页
    ├── _buildSettingsPage          # 设置页
    ├── _purchaseProduct            # 购买商品
    └── _restorePurchases           # 恢复购买

二、系统架构

2.1 整体架构图

Data Layer

Business Layer

Presentation Layer

主页面
InAppPurchaseHomePage

商店页

我的物品页

购买记录页

设置页

热门推荐

商品列表

购买按钮

消耗品列表

永久物品

订阅列表

记录列表

购买管理器
PurchaseManager

认证管理器
AuthManager

存储管理器
StorageManager

Product
商品

PurchaseRecord
购买记录

ProductType
商品类型

2.2 类图设计

uses

uses

manages

manages

InAppPurchaseDemoApp

+Widget build()

«enumeration»

ProductType

+String label

+String description

+consumable()

+nonConsumable()

+subscription()

«enumeration»

PurchaseStatus

+String label

+Color color

+pending()

+completed()

+failed()

+restored()

+cancelled()

Product

+String id

+String name

+String description

+double price

+String currency

+ProductType type

+String? icon

+bool isPopular

+String? discount

+formattedPrice

PurchaseRecord

+String id

+String productId

+String productName

+double price

+DateTime purchaseTime

+PurchaseStatus status

+String? transactionId

+formattedTime

InAppPurchaseHomePage

-int _currentIndex

-List<Product> _products

-List<PurchaseRecord> _purchaseHistory

-Set<String> _ownedProducts

-Map<String,int> _consumableCount

-bool _isPurchasing

+purchaseProduct()

+restorePurchases()

+loadPurchaseHistory()

+savePurchaseHistory()

2.3 页面导航流程

成功

失败

应用启动

商店页

浏览商品

选择商品

点击购买

需要认证?

生物认证

处理购买

认证成功?

认证失败

购买结果

显示成功对话框

显示失败提示

更新物品列表

我的物品页

查看消耗品

查看永久物品

查看订阅

购买记录页

查看历史记录

设置页

开启/关闭认证

恢复购买

2.4 购买流程

存储管理器 购买管理器 认证管理器 商店页 用户 存储管理器 购买管理器 认证管理器 商店页 用户 alt [需要生物认证] alt [购买成功] [购买失败] 点击购买按钮 请求认证 显示认证界面 完成认证 返回认证结果 开始购买流程 显示处理状态 模拟支付处理 保存购买记录 保存成功 返回成功结果 显示成功对话框 保存失败记录 返回失败结果 显示失败提示

三、核心模块设计

3.1 数据模型设计

3.1.1 商品类型枚举 (ProductType)
enum ProductType {
  consumable(label: '消耗品', description: '可重复购买,如金币、道具'),
  nonConsumable(label: '非消耗品', description: '一次购买永久拥有'),
  subscription(label: '订阅', description: '按周期付费,如会员');

  final String label;
  final String description;
  const ProductType({
    required this.label,
    required this.description,
  });
}
3.1.2 购买状态枚举 (PurchaseStatus)
enum PurchaseStatus {
  pending(label: '处理中', color: Colors.orange),
  completed(label: '已完成', color: Colors.green),
  failed(label: '失败', color: Colors.red),
  restored(label: '已恢复', color: Colors.blue),
  cancelled(label: '已取消', color: Colors.grey);

  final String label;
  final Color color;
  const PurchaseStatus({
    required this.label,
    required this.color,
  });
}
3.1.3 商品模型 (Product)
class Product {
  final String id;
  final String name;
  final String description;
  final double price;
  final String currency;
  final ProductType type;
  final String? icon;
  final bool isPopular;
  final String? discount;

  String get formattedPrice => '$currency${price.toStringAsFixed(2)}';
}
3.1.4 商品类型分布
45% 30% 25% 商品类型分布示例 消耗品 非消耗品 订阅

3.2 页面结构设计

3.2.1 主页面布局

InAppPurchaseHomePage

IndexedStack

商店页

我的物品页

购买记录页

设置页

NavigationBar

商店 Tab

我的 Tab

记录 Tab

设置 Tab

3.2.2 商店页结构

商店页

SliverAppBar

热门推荐区

消耗品区

非消耗品区

订阅区

横向滚动卡片

商品卡片列表

商品卡片列表

商品卡片列表

3.2.3 商品卡片结构

商品卡片

图标容器

商品信息

购买按钮

商品名称

商品描述

价格显示

折扣标签

拥有数量

3.3 购买处理逻辑

成功

失败

开始购买

是否正在购买?

返回

需要生物认证?

执行认证

设置购买状态

认证成功?

显示失败提示

启动动画

模拟支付处理

随机结果

创建购买记录

创建失败记录

更新拥有状态

保存数据

停止动画

显示成功对话框

3.4 数据存储逻辑

保存数据

获取SharedPreferences

序列化购买记录

保存购买历史

保存拥有商品列表

保存消耗品数量

返回成功

加载数据

获取SharedPreferences

读取购买历史

反序列化记录

读取拥有商品

读取消耗品数量

更新状态


四、UI设计规范

4.1 配色方案

应用以优雅的紫色为主色调,象征尊贵与品质:

颜色类型 色值 用途
主色 #6200EE (Purple) 导航、主题元素
辅助色 #7C4DFF 次要按钮
第三色 #B388FF 背景装饰
强调色 #3700B3 重要操作
背景色 #FAFAFA 页面背景
卡片背景 #FFFFFF 信息卡片
成功色 #4CAF50 购买成功
失败色 #F44336 购买失败
处理色 #FF9800 处理中

4.2 状态配色

状态 色值 视觉效果
处理中 #FF9800 橙色
已完成 #4CAF50 绿色
失败 #F44336 红色
已恢复 #2196F3 蓝色
已取消 #9E9E9E 灰色

4.3 字体规范

元素 字号 字重 颜色
页面标题 24px Bold 主色
商品名称 16px Bold 黑色
商品描述 12px Regular 灰色
价格 16px Bold 主色
状态标签 12px Bold 状态色
按钮文字 14px Medium 白色

4.4 组件规范

4.4.1 热门推荐卡片
┌─────────────────────────────────────┐
│  💎 500金币              [赠送10%]  │
│                                     │
│  超值金币包                          │
│  额外赠送50金币                      │
│                                     │
│  ¥25.00                    [购买]   │
└─────────────────────────────────────┘
4.4.2 商品卡片
┌─────────────────────────────────────┐
│  ┌────┐  100金币                     │
│  │ 💰 │  基础金币包,适合新手玩家     │
│  └────┘  ¥6.00  已拥有: 5     [购买] │
└─────────────────────────────────────┘
4.4.3 已拥有商品卡片
┌─────────────────────────────────────┐
│  ┌────┐  去广告                      │
│  │ 🚫 │  永久移除应用内广告          │
│  └────┘  ¥18.00            [✓已拥有]│
└─────────────────────────────────────┘
4.4.4 购买记录卡片
┌─────────────────────────────────────┐
│  [✓]  500金币                       │
│        ¥25.00                       │
│        04-12 14:30        [已完成]  │
└─────────────────────────────────────┘
4.4.5 购买成功对话框
┌─────────────────────────────────────┐
│              ┌────┐                 │
│              │ ✓  │                 │
│              └────┘                 │
│                                     │
│          购买成功!                  │
│           500金币                    │
│                                     │
│           [确定]                     │
└─────────────────────────────────────┘

五、核心功能实现

5.1 商品展示实现

Widget _buildProductCard(Product product) {
  final isOwned = _ownedProducts.contains(product.id);
  final isPurchasing = _currentPurchasingProduct == product.id;
  final count = _consumableCount[product.id] ?? 0;

  return Card(
    elevation: 2,
    margin: const EdgeInsets.only(bottom: 12),
    child: Padding(
      padding: const EdgeInsets.all(16),
      child: Row(
        children: [
          Container(
            width: 56,
            height: 56,
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.primaryContainer,
              borderRadius: BorderRadius.circular(12),
            ),
            child: Center(
              child: Text(product.icon ?? '📦', style: const TextStyle(fontSize: 28)),
            ),
          ),
          const SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(product.name, style: Theme.of(context).textTheme.titleMedium),
                Text(product.description, style: Theme.of(context).textTheme.bodySmall),
                Text(product.formattedPrice, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
              ],
            ),
          ),
          _buildBuyButton(product),
        ],
      ),
    ),
  );
}

5.2 购买流程实现

Future<void> _purchaseProduct(Product product) async {
  if (_isPurchasing) return;

  if (_useBiometric && _isBiometricAvailable) {
    final authenticated = await _authenticateWithBiometric();
    if (!authenticated) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('认证失败,无法完成购买')),
      );
      return;
    }
  }

  setState(() {
    _isPurchasing = true;
    _currentPurchasingProduct = product.id;
  });

  _pulseController.repeat(reverse: true);

  await Future.delayed(const Duration(seconds: 2));

  final success = math.Random().nextDouble() > 0.1;

  if (success) {
    final record = PurchaseRecord(
      id: 'purchase_${DateTime.now().millisecondsSinceEpoch}',
      productId: product.id,
      productName: product.name,
      price: product.price,
      purchaseTime: DateTime.now(),
      status: PurchaseStatus.completed,
      transactionId: 'TXN${DateTime.now().millisecondsSinceEpoch}',
    );

    setState(() {
      _purchaseHistory.insert(0, record);
      if (product.type == ProductType.consumable) {
        _consumableCount[product.id] = (_consumableCount[product.id] ?? 0) + 1;
      } else {
        _ownedProducts.add(product.id);
      }
      _isPurchasing = false;
      _currentPurchasingProduct = null;
    });

    await _savePurchaseHistory();
    await _saveOwnedProducts();

    _showPurchaseSuccessDialog(product);
  }
}

5.3 生物认证实现

Future<bool> _authenticateWithBiometric() async {
  try {
    return await _localAuth.authenticate(
      localizedReason: '请验证身份以完成购买',
      options: const AuthenticationOptions(
        stickyAuth: true,
        biometricOnly: true,
      ),
    );
  } catch (e) {
    debugPrint('生物认证失败: $e');
    return false;
  }
}

5.4 数据存储实现

Future<void> _savePurchaseHistory() async {
  final prefs = await SharedPreferences.getInstance();
  final historyJson = _purchaseHistory.map((r) =>
    '${r.id}|${r.productId}|${r.productName}|${r.price}|${r.purchaseTime.millisecondsSinceEpoch}|${r.status.name}|${r.transactionId ?? ''}'
  ).toList();
  await prefs.setStringList('purchase_history', historyJson);
}

Future<void> _loadPurchaseHistory() async {
  final prefs = await SharedPreferences.getInstance();
  final historyJson = prefs.getStringList('purchase_history') ?? [];
  setState(() {
    _purchaseHistory.clear();
    for (var json in historyJson) {
      final parts = json.split('|');
      if (parts.length >= 6) {
        _purchaseHistory.add(PurchaseRecord(
          id: parts[0],
          productId: parts[1],
          productName: parts[2],
          price: double.tryParse(parts[3]) ?? 0,
          purchaseTime: DateTime.fromMillisecondsSinceEpoch(int.tryParse(parts[4]) ?? 0),
          status: PurchaseStatus.values.firstWhere(
            (s) => s.name == parts[5],
            orElse: () => PurchaseStatus.completed,
          ),
        ));
      }
    }
  });
}

5.5 恢复购买实现

Future<void> _restorePurchases() async {
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('恢复购买'),
      content: const Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          CircularProgressIndicator(),
          SizedBox(height: 16),
          Text('正在恢复购买记录...'),
        ],
      ),
    ),
  );

  await Future.delayed(const Duration(seconds: 2));

  Navigator.pop(context);

  final restoredCount = _purchaseHistory
      .where((r) => r.status == PurchaseStatus.completed)
      .length;

  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('已恢复 $restoredCount 个购买记录')),
  );
}

六、交互设计

6.1 购买流程

购买管理器 认证管理器 商店页 用户 购买管理器 认证管理器 商店页 用户 alt [需要认证] alt [购买成功] [购买失败] 点击购买 检查认证设置 请求生物认证 完成认证 认证成功 开始购买 显示处理动画 模拟支付 返回成功 显示成功对话框 返回失败 显示失败提示

6.2 商品浏览流程

浏览

购买

切换Tab

进入商店

加载商品列表

显示热门推荐

显示分类商品

用户操作

滚动查看

点击购买

跳转页面

购买流程

6.3 恢复购买流程

点击恢复购买

显示加载对话框

查询购买记录

处理记录

关闭对话框

显示恢复结果


七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 2024-03-31 基础UI框架 商品展示功能 购买流程演示 真实支付集成 订阅管理功能 促销活动功能 收据验证 后端服务集成 数据分析统计 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 应用内购买演示开发计划

7.2 功能扩展建议

7.2.1 真实支付集成

支付功能:

  • 对接应用商店支付
  • 支付结果验证
  • 收据处理
  • 退款处理
7.2.2 订阅管理

订阅功能:

  • 订阅状态管理
  • 到期提醒
  • 自动续费
  • 订阅历史
7.2.3 促销活动

促销功能:

  • 限时折扣
  • 批量优惠
  • 优惠券系统
  • 会员专享

八、注意事项

8.1 开发注意事项

  1. 支付安全:确保支付流程安全可靠

  2. 数据验证:验证购买收据的真实性

  3. 错误处理:妥善处理各种支付异常

  4. 状态同步:确保购买状态正确同步

  5. 用户体验:提供清晰的购买反馈

8.2 常见问题

问题 原因 解决方案
购买失败 网络问题 提示用户重试
认证失败 设备不支持 使用密码认证
数据丢失 本地存储问题 云端备份
重复扣款 重复请求 请求去重
恢复失败 记录不存在 提示用户

8.3 使用技巧

🛒 应用内购买使用技巧 🛒

购买技巧

  • 确认商品信息再购买
  • 开启生物认证保护
  • 保存购买凭证
  • 及时查看购买记录

管理技巧

  • 定期查看已购物品
  • 及时恢复购买记录
  • 注意订阅到期时间
  • 合理规划消费

安全技巧

  • 不要分享账户信息
  • 定期检查购买记录
  • 发现异常及时反馈
  • 使用官方渠道购买

九、运行说明

9.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+
Android API 21+
iOS 12.0+

9.2 依赖配置

pubspec.yaml 中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2
  local_auth: ^2.3.0
  intl: ^0.19.0

9.3 运行命令

# 查看可用设备
flutter devices

# 运行到Web服务器
flutter run -d web-server -t lib/main_in_app_purchase.dart --web-port 8150

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_in_app_purchase.dart

# 运行到Android设备
flutter run -d android lib/main_in_app_purchase.dart

# 代码分析
flutter analyze lib/main_in_app_purchase.dart

9.4 权限配置

Android权限 (android/app/src/main/AndroidManifest.xml)
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
iOS权限 (ios/Runner/Info.plist)
<key>NSFaceIDUsageDescription</key>
<string>需要面容识别权限以验证购买</string>

十、总结

应用内购买演示应用通过整合商品展示、购买流程、生物认证、购买记录、恢复购买等功能,为开发者提供了完整的应用内购买实现参考。应用展示了消耗品、非消耗品、订阅三种商品类型的处理方式,包含热门推荐、折扣标签、拥有状态等实用功能。

核心功能涵盖商品展示、购买流程、生物认证、购买记录、恢复购买、我的物品、购买动画、数据存储八大模块。开发者可以参考本应用了解应用内购买的最佳实践,快速实现自己的应用内购买功能。

应用采用 Material Design 3 设计规范,以优雅的紫色为主色调,象征尊贵与品质。通过本应用,希望能够帮助开发者更好地理解和实现应用内购买功能,提升应用的商业化能力。

应用内购买演示——掌握商业化的关键


Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐