I have integrated in flutter in_app_purchase subscription (android ), but it always automatically refund after 3 days
I am using below code for flutter subscription. I can't find the actual issue in the code, please help what I have missed in this code
import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:in_app_purchase/in_app_purchase.dart'; import 'util/ConsumableStore.dart'; const bool _kAutoConsume = true; const String _kConsumableId = 'consumable'; const List _kProductIds = ['subscription_item', 'purchase_item']; class StoreScreenNew extends StatefulWidget { @override _StoreScreenState createState() => _StoreScreenState(); } class _StoreScreenState extends State { final InAppPurchaseConnection _connection = InAppPurchaseConnection.instance; StreamSubscription> _subscription; List _notFoundIds = []; List _products = []; List _purchases = []; bool _isAvailable = false; bool _purchasePending = false; bool _loading = true; String _queryProductError; bool _isConnected = false; String storeName = ""; @override void initState() { checkInternet().then((onValue) { setState(() { _isConnected = onValue; }); }); Stream purchaseUpdated = InAppPurchaseConnection.instance.purchaseUpdatedStream; _subscription = purchaseUpdated.listen((purchaseDetailsList) { _listenToPurchaseUpdated(purchaseDetailsList); }, onDone: () { _subscription.cancel(); }, onError: (error) { // handle error here. }); initStoreInfo(); super.initState(); } Future checkInternet() async { try { final result = await InternetAddress.lookup('google.com'); if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { return Future.value(true); } else { return Future.value(false); } } on SocketException catch (_) { return Future.value(false); } } Future initStoreInfo() async { if (Platform.isIOS) { storeName = "iTunes"; } else { storeName = "Play Store"; } final bool isAvailable = await _connection.isAvailable(); if (!isAvailable) { setState(() { _isAvailable = isAvailable; _products = []; _purchases = []; _notFoundIds = []; _purchasePending = false; _loading = false; }); return; } ProductDetailsResponse productDetailResponse = await _connection.queryProductDetails(_kProductIds.toSet()); if (productDetailResponse.error != null) { setState(() { _queryProductError = productDetailResponse.error.message; _isAvailable = isAvailable; _products = productDetailResponse.productDetails; _purchases = []; _notFoundIds = productDetailResponse.notFoundIDs; _purchasePending = false; _loading = false; }); return; } if (productDetailResponse.productDetails.isEmpty) { setState(() { _queryProductError = null; _isAvailable = isAvailable; _products = productDetailResponse.productDetails; _purchases = []; _notFoundIds = productDetailResponse.notFoundIDs; _purchasePending = false; _loading = false; }); return; } final QueryPurchaseDetailsResponse purchaseResponse = await _connection.queryPastPurchases(); if (purchaseResponse.error != null) { // handle query past purchase error.. } final List verifiedPurchases = []; for (PurchaseDetails purchase in purchaseResponse.pastPurchases) { if (await _verifyPurchase(purchase)) { verifiedPurchases.add(purchase); } } setState(() { _isAvailable = isAvailable; _products = productDetailResponse.productDetails; _purchases = verifiedPurchases; _notFoundIds = productDetailResponse.notFoundIDs; _purchasePending = false; _loading = false; }); } @override void dispose() { _subscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { List stack = []; if (_queryProductError == null) { stack.add( ListView( children: [ _buildConnectionCheckTile(), _buildProductList(), addPrivacy(), addLink() ], ), ); } else { stack.add(Center( child: Text(_queryProductError), )); } if (_purchasePending) { stack.add( Stack( children: [ Opacity( opacity: 0.3, child: const ModalBarrier(dismissible: false, color: Colors.grey), ), Center( child: CircularProgressIndicator(), ), ], ), ); } return MaterialApp( home: Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).primaryColor, automaticallyImplyLeading: true, title: Text('PRO', style: Theme.of(context).textTheme.headline5), leading: IconButton( icon: Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context, false), )), body: _isConnected ? Stack( children: stack, ) : Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( height: 10, ), Container( margin: EdgeInsets.all(20), child: Text( "Check your internet connection and try again.", textAlign: TextAlign.center, style: TextStyle(color: Colors.black45, fontSize: 26), )) ])), ), ); } Card _buildConnectionCheckTile() { if (_loading) { return Card(child: ListTile(title: const Text('Trying to connect...'))); } final Widget storeHeader = ListTile( leading: Icon(_isAvailable ? Icons.check : Icons.block, color: _isAvailable ? Colors.green : ThemeData.light().errorColor), title: Text( 'The store is ' + (_isAvailable ? 'available' : 'unavailable') + '.'), ); final List children = [ !_isAvailable ? storeHeader : Container() ]; if (!_isAvailable) { children.addAll([ Divider(), ListTile( title: Text('Not connected', style: TextStyle(color: ThemeData.light().errorColor)), subtitle: const Text( 'Unable to connect to the payments processor. Has this app been configured correctly? See the example README for instructions.'), ), ]); } return Card(child: Column(children: children)); } Card _buildProductList() { if (_loading) { return Card( child: (ListTile( leading: CircularProgressIndicator(), title: Text('Fetching products...')))); } if (!_isAvailable) { return Card(); } final ListTile productHeader = ListTile( title: Text( 'Available Options', style: TextStyle(fontSize: 20), ), ); List productList = []; if (_notFoundIds.isNotEmpty) { productList.add(ListTile( title: Text('[${_notFoundIds.join(", ")}] not found', style: TextStyle(color: ThemeData.light().errorColor)), subtitle: Text( 'This app needs special configuration to run. Please see example/README.md for instructions.'))); } Map purchases = Map.fromEntries(_purchases.map((PurchaseDetails purchase) { if (purchase.pendingCompletePurchase) { InAppPurchaseConnection.instance.completePurchase(purchase); } return MapEntry(purchase.productID, purchase); })); productList.addAll(_products.map( (ProductDetails productDetails) { PurchaseDetails previousPurchase = purchases[productDetails.id]; return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: Colors.white, boxShadow: [ BoxShadow(color: Colors.grey, spreadRadius: 1), ], ), margin: EdgeInsets.all(5), padding: EdgeInsets.all(10), child: Column( children: [ Text( productDetails.title, textAlign: TextAlign.center, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: previousPurchase != null ? Colors.green : Colors.black), ), SizedBox( height: 10, ), Divider(), SizedBox( height: 10, ), Text( productDetails.description, textAlign: TextAlign.left, ), SizedBox( height: 20, ), Divider(), Container( alignment: Alignment.bottomRight, child: previousPurchase != null ? Container( padding: const EdgeInsets.all(10.0), decoration: new BoxDecoration( shape: BoxShape.circle, color: Colors.green, ), child: Icon( Icons.check, size: 30, color: Colors.white, )) : FlatButton( child: Text( productDetails.price, style: TextStyle(fontSize: 18), ), color: Colors.green[800], textColor: Colors.white, onPressed: () { PurchaseParam purchaseParam = PurchaseParam( productDetails: productDetails, applicationUserName: null, sandboxTesting: false); if (productDetails.id == _kConsumableId) { _connection.buyConsumable( purchaseParam: purchaseParam, autoConsume: _kAutoConsume || Platform.isIOS); } else { _connection.buyNonConsumable( purchaseParam: purchaseParam); } }, )) ], ), ); }, )); return Card( margin: EdgeInsets.all(10), elevation: 0, child: Column( children: [ productHeader, Divider(), ] + productList, )); } void showPendingUI() { setState(() { _purchasePending = true; }); } void deliverProduct(PurchaseDetails purchaseDetails) async { if (purchaseDetails.productID == _kConsumableId) { await ConsumableStore.save(purchaseDetails.purchaseID); App.setPurchasesStatus(true); setState(() { _purchasePending = false; }); } else { setState(() { _purchases.add(purchaseDetails); _purchasePending = false; }); } } void handleError(IAPError error) { setState(() { _purchasePending = false; }); } Future _verifyPurchase(PurchaseDetails purchaseDetails) { return Future.value(true); } void _handleInvalidPurchase(PurchaseDetails purchaseDetails) { } void _listenToPurchaseUpdated(List purchaseDetailsList) { purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async { if (purchaseDetails.status == PurchaseStatus.pending) { showPendingUI(); } else { if (purchaseDetails.status == PurchaseStatus.error) { handleError(purchaseDetails.error); } else if (purchaseDetails.status == PurchaseStatus.purchased) { bool valid = await _verifyPurchase(purchaseDetails); if (valid) { deliverProduct(purchaseDetails); } else { _handleInvalidPurchase(purchaseDetails); return; } } if (Platform.isAndroid) { if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) { await InAppPurchaseConnection.instance .consumePurchase(purchaseDetails); } } if (purchaseDetails.pendingCompletePurchase) { await InAppPurchaseConnection.instance .completePurchase(purchaseDetails); } } }); } }