Mi código en flutter de compras in app, por si alguien lo necesita

Mi código en flutter de compras in app, por si alguien lo necesita




import 'dart:async';

import 'package:calca_app/pages/paginas_publi_subs/banners_apliarte/banner_chico.dart';
import 'package:calca_app/pages/paginas_publi_subs/inAppPurchase/listados_in_app.dart';
import 'package:calca_app/widget/variables_funciones/variables_que_se_guardan/esta_suscrito.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:onepref/onepref.dart';

import '../../../generated/l10n.dart';
import '../../../widget/variables_funciones/navegar_a.dart';

/// Este archivo contiene la clase SubscriptionService que se utiliza para interactuar con el servicio de suscripción de la aplicación.
/// Proporciona métodos para obtener los productos disponibles, suscribirse a un producto específico y restaurar las compras anteriores.
/// Utiliza la biblioteca In-App Purchase para realizar las operaciones relacionadas con las compras en la aplicación.
class SubscriptionService {
  final IApEngine iApEngine = IApEngine();
  final List _productsIds = [
    ProductId(id: "year", isConsumable: false),
  ];

  /// Obtiene la lista de detalles de los productos disponibles para la compra.
  /// Retorna una lista vacía si no hay productos disponibles o si la funcionalidad de compra en la aplicación no está disponible.
  Future> getProducts() async {
    final isAvailable = await iApEngine.getIsAvailable();
    if (isAvailable) {
      final response = await iApEngine.queryProducts(_productsIds);
      return response.productDetails;
    }
    return [];
  }

  /// Suscribe al usuario al producto especificado.
  /// Maneja cualquier error que pueda ocurrir durante el proceso de suscripción.
  Future subscribe(ProductDetails product) async {
    try {
      // Código de suscripción aquí
      iApEngine.handlePurchase(product, _productsIds);
    } catch (e) {
      // Manejo de errores aquí
      if (kDebugMode) {
        print('Error al suscribirse: $e');
      }
    }
  }

  /// Restaura las compras anteriores del usuario.
  /// Maneja cualquier error que pueda ocurrir durante el proceso de restauración.
  Future restore() async {
    try {
      // Código de restauración aquí
      await InAppPurchase.instance.restorePurchases();
    } catch (e) {
      // Manejo de errores aquí
      if (kDebugMode) {
        print('Error al restaurar: $e');
      }
    }
  }
}

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

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

class _SubscriptionsState extends State {
  late List _products = [];
  SubscriptionService _subscriptionService = SubscriptionService();
  bool isSubscribed = false;
  bool isRestore = false;
  List benefits = [];
  StreamSubscription>? _purchaseUpdatedSubscription;
  @override
  void initState() {
    super.initState();
    isSubscribed = OnePref.getPremium() ?? false;
    _subscriptionService.getProducts().then((products) {
      setState(() {
        _products = products;
      });
    });
    _purchaseUpdatedSubscription =
        InAppPurchase.instance.purchaseStream.listen((purchaseDetailsList) {
      _handlePurchaseUpdates(purchaseDetailsList);
    }, onDone: () {
      _purchaseUpdatedSubscription?.cancel();
    }, onError: (error) {
      // manejar errores aquí
    });
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // Inicializa 'benefits' aquí
    benefits = [S.of(context).inAppsubAnioDescripcion];
  }

  void _handlePurchaseUpdates(List purchaseDetailsList) {
    purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
      if (purchaseDetails.status == PurchaseStatus.purchased ||
          purchaseDetails.status == PurchaseStatus.restored) {
        if (purchaseDetails.productID == 'year') {
          setState(() {
            isSubscribed = true;
          });
          Suscrito().cambiarUnAnio(true);
          // Aquí puedes guardar el estado de la suscripción en un almacenamiento persistente
          // para que puedas comprobar si el usuario está suscrito cuando la aplicación se reinicie.
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) => PopScope(
        canPop: false,
        onPopInvoked: (didPop) {
          Navegacion().reiniciarApp(context);
          // Prevents the default behavior
        },
        child: Scaffold(
          appBar: AppBar(
            leading: IconButton(
              icon: const Icon(Icons.arrow_back),
              onPressed: () {
                Navegacion().reiniciarApp(context);
              },
            ),
            title: const Text('💰 💵 📅 🔁 '),
            centerTitle: true,
          ),
          body: Container(
            decoration: const BoxDecoration(
              image: DecorationImage(
                image: AssetImage('assets/images/1.webp'),
                fit: BoxFit.cover,
                opacity: 0.5,
              ),
            ),
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Row(
                    children: [
                      Container(
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: isSubscribed ? Colors.green : Colors.red,
                        ),
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text(isSubscribed
                              ? S.of(context).suscritoTexto
                              : S.of(context).nosuscritoTexto),
                        ),
                      ),
                      const Spacer(),
                      FloatingActionButton.extended(
                        onPressed: () async => {
                          await _subscriptionService.restore(),
                        },
                        label: Text(
                          S.of(context).restaurarTexto,
                          style: const TextStyle(fontWeight: FontWeight.bold),
                        ),
                      ),
                    ],
                  ),
                ),
                SizedBox(
                  height: 200,
                  child: ListView.builder(
                    itemCount: benefits.length,
                    itemBuilder: (context, index) => ListaBeneficios(
                      title: benefits[index],
                      icon: Icons.check,
                    ),
                  ),
                ),
                Visibility(
                  visible: !_products.isNotEmpty,
                  child: const SizedBox(
                    height: 90,
                    width: 90,
                    child: CircularProgressIndicator(),
                  ),
                ),
                Expanded(
                  child: Visibility(
                    visible: _products.isNotEmpty,
                    child: ListView.builder(
                      itemBuilder: ((context, index) => Padding(
                            padding: const EdgeInsets.symmetric(
                                vertical: 5.0, horizontal: 25.0),
                            child: Row(
                              children: [
                                Expanded(
                                  child: Container(
                                      decoration: BoxDecoration(
                                        border: Border.all(
                                          width: 0.5,
                                        ),
                                      ),
                                      child: Padding(
                                          padding: const EdgeInsets.symmetric(
                                            horizontal: 5.0,
                                          ),
                                          child: ListTile(
                                            title: Text(
                                              _products[index].price,
                                              style: const TextStyle(),
                                            ),
                                            subtitle: Text(
                                              _products[index].description,
                                              style: const TextStyle(),
                                            ),
                                            trailing: ElevatedButton(
                                              onPressed: () async {
                                                await _subscriptionService
                                                    .subscribe(
                                                        _products[index]);
                                              },
                                              child: const Text(
                                                "Subscribe",
                                              ),
                                            ),
                                          ))),
                                ),
                              ],
                            ),
                          )),
                      itemCount: _products.length,
                    ),
                  ),
                ),
                Visibility(
                  visible: !isSubscribed,
                  child: const Padding(
                      padding: EdgeInsets.all(8.0), child: BannerChico()),
                ),
              ],
            ),
          ),
        ),
      );
}


Mi código en flutter de compras sin app, por si alguien lo necesita ----LISTA DE PRODUCTOS

import 'package:flutter/material.dart'; // ignore: must_be_immutable class ListaBeneficios extends StatelessWidget { String title; IconData icon; double? spaceBetween; double? iconSize; Color? iconColor; Color? iconBackgroundColor; TextStyle? titleStyle; ListaBeneficios({ super.key, required this.title, required this.icon, this.iconSize, this.iconColor, this.iconBackgroundColor, this.spaceBetween, this.titleStyle, }); @override Widget build(BuildContext context) => Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 10), child: Row( children: [ Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), color: iconBackgroundColor ?? Colors.orange, ), child: Icon( Icons.check, color: iconColor ?? Colors.white, size: iconSize ?? 20, ), ), SizedBox( width: spaceBetween ?? 20, ), SizedBox( width: MediaQuery.of(context).size.width * 0.7, child: Text( title, style: titleStyle, ), ), ], ), ); }

Comentarios