flutter_inapp_purchase 2.0.2

  • Readme
  • Changelog
  • Example
  • Installing
  • 96

flutter_inapp_purchase #

Pub Version Build Status License Coverage Status

Sun Rise 🌅

Since many one of you wanted me to keep working on this plugin in #93, I've decided to keep working on current project. I hope many one of you can help me maintain this. Thank you for all your supports in advance 🎉.

## Deprecated I've been maintaining this plugin since there wasn't an official plugin out when I implemented it. I saw in flutter github issue #9591 that many people have been waiting for this plugin for more than a year before I've thought of building one. However, there has been an official Google plugin rised today which is in_app_purchase. Please try to use an official one because you might want to get much prompt support from giant Google. Also, thanks for all your supports that made me stubborn to work hard on this plugin. I've had great experience with all of you and hope we can meet someday with other projects. I'll leave this project as live for those who need time. I'll also try to merge the new PR's and publish to pub if there's any further work given to this repo.

What this plugin do #

This is an In App Purchase plugin for flutter. This project has been forked from react-native-iap. We are trying to share same experience of in-app-purchase in flutter as in react-native. We will keep working on it as time goes by just like we did in react-native-iap.

PR is always welcomed.

Breaking Changes #

  • Sunrise in 2.0.0 for highly requests from customers on discomfort in what's called an official plugin in_app_purchase.
  • Migrated to Android X in 0.9.0. Please check the Migration Guide.
  • There was parameter renaming in 0.5.0 to identify different parameters sent from the device. Please check the readme.

Migration Guide #

To migrate to 0.9.0 you must migrate your Android app to Android X by following the Migrating to AndroidX Guide.

Getting Started #

Follow the Medium Blog for the configuration.

For help getting started with Flutter, view our online documentation.

For help on editing plugin code, view the documentation.

Methods #

FuncParamReturnDescription
initConnectionStringPrepare IAP module. Must be called on Android before any other purchase flow methods. In ios, it will simply call canMakePayments method and return value.
getProductsList<String> Product IDs/skusList<IAPItem>Get a list of products (consumable and non-consumable items, but not subscriptions). Note: On iOS versions earlier than 11.2 this method will return subscriptions if they are included in your list of SKUs. This is because we cannot differentiate between IAP products and subscriptions prior to 11.2.
getSubscriptionsList<String> Subscription IDs/skusList<IAPItem>Get a list of subscriptions. Note: On iOS this method has the same output as getProducts. Because iOS does not differentiate between IAP products and subscriptions.
getPurchaseHistoryList<IAPItem>Gets an invetory of purchases made by the user regardless of consumption status (where possible)
getAvailablePurchasesList<PurchasedItem>(aka restore purchase) Get all purchases made by the user (either non-consumable, or haven't been consumed yet)
getAppStoreInitiatedProductsList<IAPItem>If the user has initiated a purchase directly on the App Store, the products that the user is attempting to purchase will be returned here. (iOS only) Note: On iOS versions earlier than 11.0 this method will always return an empty list, as the functionality was introduced in v11.0. See Apple Docs for more info Always returns an empty list on Android.
requestSubscriptionString sku, String oldSkuAndroid?, int prorationModeAndroid?, String developerIdAndroid, String accountIdAndroidNullCreate (request) a subscription to a sku. For upgrading/downgrading subscription on Android pass second parameter with current subscription ID, on iOS this is handled automatically by store. purchaseUpdatedListener will receive the result.
requestPurchaseString sku, String developerIdAndroid, String accoundIdAndroidNullRequest a purchase. purchaseUpdatedListener will receive the result.
finishTransactionIOSString purchaseTokenPurchaseResultSend finishTransaction call to Apple IAP server. Call this function after receipt validation process
acknowledgePurchaseAndroidString purchaseToken, String developerPayload?PurchaseResultAcknowledge a product (on Android) for non-consumable and subscription purchase. No-op on iOS.
consumePurchaseAndroidString purchaseToken, String developerPayload?PurchaseResultConsume a product (on Android) for consumable purchase. No-op on iOS.
finishTransactionString purchaseToken, String deveoperPayloadAndroid?, bool isConsumable? }PurchaseResultSend finishTransaction call that abstracts all acknowledgePurchaseAndroid, finishTransactionIOS, consumePurchaseAndroid methods.
endConnectionStringEnd billing connection (on Android.) No-op on iOS.
consumeAllItemsStringManually consume all items in android. Do NOT call if you have any non-consumables (one time purchase items). No-op on iOS.
validateReceiptIosMap<String,String> receiptBody, bool isTesthttp.ResponseValidate receipt for ios.
validateReceiptAndroidString packageName, String productId, String productToken, String accessToken, bool isSubscriptionhttp.ResponseValidate receipt for android.

Purchase flow in `flutter_inapp_purchase@2.0.0+ #

purchase-flow-sequence

When you've successfully received result from purchaseUpdated listener, you'll have to verify the purchase either by acknowledgePurchaseAndroid, consumePurchaseAndroid, finishTransactionIOS depending on the purchase types or platforms. You'll have to use consumePurchasAndroid for consumable products and android and acknowledgePurchaseAndroid for non-consumable products either subscription. For ios, there is no differences in verifying purchases. You can just call finishTransaction. If you do not verify the purchase, it will be refunded within 3 days to users. We recommend you to verifyReceipt first before actually finishing transaction. Lastly, if you want to abstract three different methods into one, consider using finishTransaction method.

Data Types #

  • IAPItem

    final String productId;
    final String price;
    final String currency;
    final String localizedPrice;
    final String title;
    final String description;
    final String introductoryPrice;
    
    /// ios only
    final String subscriptionPeriodNumberIOS;
    final String subscriptionPeriodUnitIOS;
    final String introductoryPricePaymentModeIOS;
    final String introductoryPriceNumberOfPeriodsIOS;
    final String introductoryPriceSubscriptionPeriodIOS;
    
    /// android only
    final String subscriptionPeriodAndroid;
    final String introductoryPriceCyclesAndroid;
    final String introductoryPricePeriodAndroid;
    final String freeTrialPeriodAndroid;
    final String signatureAndroid;
    
    final String iconUrl;
    final String originalJson;
    final String originalPrice;
    
  • PurchasedItem

    final String productId;
    final String transactionId;
    final DateTime transactionDate;
    final String transactionReceipt;
    final String purchaseToken;
    final String orderId;
    
    // Android only
    final String dataAndroid;
    final String signatureAndroid;
    final bool autoRenewingAndroid;
    final bool isAcknowledgedAndroid;
    final int purchaseStateAndroid;
    final String developerPayloadAndroid;
    final String originalJsonAndroid;
    
    // iOS only
    final DateTime originalTransactionDateIOS;
    final String originalTransactionIdentifierIOS;
    

Install #

Add flutter_inapp_purchase as a dependency in pubspec.yaml

For help on adding as a dependency, view the documentation.

Configuring in app purchase #

Usage Guide #

Android connect and endConnection

  • You should start the billing service in android to use its funtionalities. We recommend you to use initConnection getter method in initState(). Note that this step is necessary in ios also from flutter_inapp_purchase@2.0.0+ which will also register the purchaseUpdated and purchaseError Stream.

      /// start connection for android
      @override
      void initState() {
        super.initState();
        asyncInitState(); // async is not allowed on initState() directly
      }
    
      void asyncInitState() async {
        await FlutterInappPurchase.initConnection;
      }
    
  • You should end the billing service in android when you are done with it. Otherwise it will be keep running in background. We recommend to use this feature in dispose().

  • Additionally, we've added connectionUpdated stream just in case if you'd like to monitor the connection more thoroughly form 2.0.1.

    _conectionSubscription = FlutterInappPurchase.connectionUpdated.listen((connected) {
      print('connected: $connected');
    });
    

    You can see how you can use this in detail in example project.

      /// start connection for android
      @override
      void dispose() async{
        super.dispose();
        await FlutterInappPurchase.endConnection;
      }
    

Get IAP items #

  void getItems () async {
    List<IAPItem> items = await FlutterInappPurchase.getProducts(_productLists);
    for (var item in items) {
      print('${item.toString()}');
      this._items.add(item);
    }
  }

Purchase Item #

  void purchase() {
    FlutterInappPurchase.instance.requestPurchase(item.productId);
  }

Register listeners to receive purchase #

  StreamSubscription _purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((productItem) {
    print('purchase-updated: $productItem');
  });

  StreamSubscription _purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen((purchaseError) {
    print('purchase-error: $purchaseError');
  });

Remove listeners when ending connection #

  _purchaseUpdatedSubscription.cancel();
  _purchaseUpdatedSubscription = null;
  _purchaseErrorSubscription.cancel();
  _purchaseErrorSubscription = null;

Receipt validation #

From 0.7.1, we support receipt validation. For Android, you need separate json file from the service account to get the access_token from google-apis, therefore it is impossible to implement serverless. You should have your own backend and get access_token. With access_token you can simply call validateReceiptAndroid method we implemented. Further reading is here. Currently, serverless receipt validation is possible using validateReceiptIos method. The first parameter, you should pass transactionReceipt which returns after requestPurchase. The second parameter, you should pass whether this is test environment. If true, it will request to sandbox and false it will request to production.

  validateReceipt() async {
    var receiptBody = {
      'receipt-data': purchased.transactionReceipt,
      'password': '******'
    };
    const result = await validateReceiptIos(receiptBody, false);
    console.log(result);
  }

For further information, please refer to guide.

App Store initiated purchases #

When the user starts an in-app purchase in the App Store, the transaction continues in your app, the product will then be added to a list that you can access through the method getAppStoreInitiatedProducts. This means you can decide how and when to continue the transaction. To continue the transaction simple use the standard purchase flow from this plugin.

void checkForAppStoreInitiatedProducts() async {
  List<IAPItem> appStoreProducts = await FlutterInappPurchase.getAppStoreInitiatedProducts(); // Get list of products
  if (appStoreProducts.length > 0) {
    _requestPurchase(appStoreProducts.last); // Buy last product in the list
  }
}

Example #

Direct to example readme which is just a cp from example project. You can test this in real example project.

ProGuard #

If you have eneabled proguard you will need to add the following rules to your proguard-rules.pro

#In app Purchase
-keep class com.amazon.** {*;}
-keep class com.dooboolab.** { *; }
-keep class com.android.vending.billing.**
-dontwarn com.amazon.**
-keepattributes *Annotation*

Q & A

Can I buy product right away skipping fetching products if I already know productId? #

  • You can in Android but not in ios. In ios you should always fetchProducts first. You can see more info here.

How do I validate receipt in ios? #

  • Official doc is here.

How do I validate receipt in android? #

  • Offical doc is here.
  • I've developed this feature for other developers to contribute easily who are aware of these things. The doc says you can also get the accessToken via play console without any of your backend server. You can get this by following process.
    • Select your app > Services & APIs > "YOUR LICENSE KEY FOR THIS APPLICATION Base64-encoded RSA public key to include in your binary". reference.

Invalid productId in ios. #

  • Please try below and make sure you've done belows.
    • Steps
      1. Completed an effective "Agreements, Tax, and Banking."
      2. Setup sandbox testing account in "Users and Roles."
      3. Signed into iOS device with sandbox account.
      4. Set up three In-App Purchases with the following status: i. Ready to Submit ii. Missing Metadata iii. Waiting for Review
      5. Enable "In-App Purchase" in Xcode "Capabilities" and in Apple Developer -> "App ID" setting. Delete app / Restart device / Quit "store" related processes in Activity Monitor / Xcode Development Provisioning Profile -> Clean -> Build.

Help Maintenance #

I've been maintaining quite many repos these days and burning out slowly. If you could help me cheer up, buying me a cup of coffee will make my life really happy and get much energy out of it.

Paypal Buy Me A Coffee

2.0.2 #

  • use ConnectionResult as type for connection stream, fix controller creation #112

2.0.0+16 #

  • Resolve #106 by not sending result.error to the listener. Created use _conectionSubscription.

2.0.0+15 #

  • Fixed minor typo when generating string with toString. Resolve #110.

2.0.0+14 #

  • Pass android exception to flutter side.

2.0.0+13 #

  • Android receipt validation api upgrade to v3.

2.0.0+12 #

  • Resolve #102. Fluter seems to only sends strings between platforms.

2.0.0+9 #

2.0.0+8 #

2.0.0+7 #

2.0.0+6 #

  • Send purchase-error with purchases returns null.

2.0.0+5 #

  • Renamed invoked parameters non-platform specific.

2.0.0+4 #

  • Add deveoperId and accountId when requesting purchase or subscription in android. Find out more in requestPurchase and requestSubscription.

2.0.0+3 #

  • Correctly mock invoke method and return results #94

2.0.0+2 #

  • Seperate long example code to example readme.

2.0.0+1 #

  • Properly set return type PurchaseResult of when finishing transaction.

2.0.0 🎉

  • Removed deprecated note in the readme.
  • Make the previous tests work in travis.
  • Documentation on readme for breaking features.
  • Abstracts finishTransaction.
    • acknowledgePurchaseAndroid, consumePurchaseAndroid, finishTransactionIOS.

[Android]

  • Completely remove prepare.
  • Upgrade billingclient to 2.0.3 which is currently recent in Sep 15 2019.
  • Remove [IInAppBillingService] binding since billingClient has its own functionalities.
  • Add [DoobooUtils] and add getBillingResponseData that visualizes erorr codes better.
  • buyProduct no more return asyn result. It rather relies on the purchaseUpdatedListener.
  • Add feature method acknowledgePurchaseAndroid
    • Implement acknowledgePurchaseAndroid.
    • Renamed consumePurchase to consumePurchaseAndroid in dart side.
    • Update test codes.
  • Renamed methods
    • buyProduct to requestPurchase.
    • buySubscription to requestSubscription.

[iOS]

  • Implment features in new releases.
    • enforce to finishTransaction after purchases.
    • Work with purchaseUpdated and purchaseError listener as in android.
    • Feature set from react-native-iap v3.
    • Should call finish transaction in every purchase request.
    • Add IAPPromotionObserver cocoa touch file
    • Convert dic to json string before invoking purchase-updated
    • Add getPromotedProductIOS and requestPromotedProductIOS methods
    • Implement clearTransaction for ios
    • Include purchasePromoted stream that listens to iap-promoted-product.

1.0.0 #

0.9.+ #

  • Breaking change. Migrate from the deprecated original Android Support Library to AndroidX. This shouldn't result in any functional changes, but it requires any Android apps using this plugin to also migrate to Android X if they're using the original support library. Android's Migrating to Android X Guide.
  • Improved getPurchaseHistory's speed 44% faster #68.

0.8.+ #

  • Fixed receipt validation param for android.
  • Updated http package.
  • Implemented new method getAppStoreInitiatedProducts.
    • Handling of iOS method paymentQueue:shouldAddStorePayment:forProduct:
    • Has no effect on Android.
  • Fixed issue with method buyProductWithoutFinishTransaction for iOS, was not getting the productId.
  • Fixed issue with toString method of class IAPItem, was printing incorrect values.
  • Fixes for #44. Unsafe getting originalJson when restoring item and Android.
  • Use dictionaryWithObjectsAndKeys in NSDictionary to fetch product values. This will prevent from NSInvalidArgumentException in ios which rarely occurs.
  • Fixed wrong npe in android when getAvailablePurchases.
  • Only parse orderId when exists in Android to prevent crashing.
  • Add additional success purchase listener in iOS. Related #54

0.7.1 #

  • Implemented receiptValidation for both android and ios.
    • In Android, you need own backend to get your accessToken.

0.7.0 #

  • Addition of Amazon In-App Purchases.

0.6.9 #

  • Prevent nil element exception when getting products.

0.6.8 #

  • Prevent nil exception in ios when fetching products.

0.6.7 #

  • Fix broken images on pub.

0.6.6 #

  • Added missing introductory fields in ios.

0.6.5 #

  • convert dynamic objects to PurchasedItems.
  • Fix return type for getAvailablePurchases().
  • Fix ios null value if optional operator.

0.6.3 #

  • Update readme.

0.6.2 #

  • Fixed failing when there is no introductory price in ios.

0.6.1 #

  • Fixed checkSubscribed that can interrupt billing lifecycle.

0.6.0 #

  • Major code refactoring by lukepighetti. Unify PlatformException, cleanup new, DateTime instead of string.

0.5.9 #

  • Fix getSubscription json encoding problem in ios.

0.5.8 #

  • Avoid crashing on android caused by IllegalStateException.

0.5.7 #

  • Avoid possible memory leak in android by deleting static declaration of activity and context.

0.5.6 #

  • Few types fixed.

0.5.4 #

  • Fixed error parsing IAPItem.

0.5.3 #

  • Fixed error parsing purchaseHistory.

0.5.2 #

  • Fix crashing on error.

0.5.1 #

  • Give better error message on ios.

0.5.0 #

  • Code migration.
  • Support subscription period.
  • There was parameter renaming in 0.5.0 to identify different parameters sent from the device. Please check the readme.

0.4.3 #

  • Fixed subscription return types.

0.4.0 #

  • Well formatted code.

0.3.3 #

  • Code formatted
  • Updated missing data types

0.3.1 #

  • Upgraded readme for ease of usage.
  • Enabled strong mode.

0.3.0 #

  • Moved dynamic return type away and instead give PurchasedItem.

0.2.3 #

  • Quickly fixed purchase bug out there in issue. Need much more improvement currently.

0.2.2 #

  • Migrated packages from FlutterInApp to FlutterInAppPurchase because pub won't get it.

0.1.0 #

example/README.md

flutter_inapp_purchase_example #

Demonstrates how to use the flutter_inapp_purchase plugin.

Getting Started #

For help getting started with Flutter, view our online documentation.

Example #

Below code is just a cp from example project. You can test this in real example project.

class InApp extends StatefulWidget {
  @override
  _InAppState createState() => new _InAppState();
}

class _InAppState extends State<InApp> {
  StreamSubscription _purchaseUpdatedSubscription;
  StreamSubscription _purchaseErrorSubscription;
  final List<String> _productLists = Platform.isAndroid
      ? [
          'android.test.purchased',
          'point_1000',
          '5000_point',
          'android.test.canceled',
        ]
      : ['com.cooni.point1000', 'com.cooni.point5000'];

  String _platformVersion = 'Unknown';
  List<IAPItem> _items = [];
  List<PurchasedItem> _purchases = [];

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      platformVersion = await FlutterInappPurchase.instance.platformVersion;
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // prepare
    var result = await FlutterInappPurchase.instance.initConnection;
    print('result: $result');

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });

    // refresh items for android
    try {
      String msg = await FlutterInappPurchase.instance.consumeAllItems;
      print('consumeAllItems: $msg');
    } catch (err) {
      print('consumeAllItems error: $err');
    }

    _purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((productItem) {
      print('purchase-updated: $productItem');
    });

    _purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen((purchaseError) {
      print('purchase-error: $purchaseError');
    });
  }

  void _requestPurchase(IAPItem item) {
    FlutterInappPurchase.instance.requestPurchase(item.productId);
  }

  Future<Null> _getProduct() async {
    List<IAPItem> items = await FlutterInappPurchase.instance.getProducts(_productLists);
    for (var item in items) {
      print('${item.toString()}');
      this._items.add(item);
    }

    setState(() {
      this._items = items;
      this._purchases = [];
    });
  }

  Future<Null> _getPurchases() async {
    List<PurchasedItem> items =
        await FlutterInappPurchase.instance.getAvailablePurchases();
    for (var item in items) {
      print('${item.toString()}');
      this._purchases.add(item);
    }

    setState(() {
      this._items = [];
      this._purchases = items;
    });
  }

  Future<Null> _getPurchaseHistory() async {
    List<PurchasedItem> items = await FlutterInappPurchase.instance.getPurchaseHistory();
    for (var item in items) {
      print('${item.toString()}');
      this._purchases.add(item);
    }

    setState(() {
      this._items = [];
      this._purchases = items;
    });
  }

  List<Widget> _renderInApps() {
    List<Widget> widgets = this
        ._items
        .map((item) => Container(
              margin: EdgeInsets.symmetric(vertical: 10.0),
              child: Container(
                child: Column(
                  children: <Widget>[
                    Container(
                      margin: EdgeInsets.only(bottom: 5.0),
                      child: Text(
                        item.toString(),
                        style: TextStyle(
                          fontSize: 18.0,
                          color: Colors.black,
                        ),
                      ),
                    ),
                    FlatButton(
                      color: Colors.orange,
                      onPressed: () {
                        print("---------- Buy Item Button Pressed");
                        this._requestPurchase(item);
                      },
                      child: Row(
                        children: <Widget>[
                          Expanded(
                            child: Container(
                              height: 48.0,
                              alignment: Alignment(-1.0, 0.0),
                              child: Text('Buy Item'),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ))
        .toList();
    return widgets;
  }

  List<Widget> _renderPurchases() {
    List<Widget> widgets = this
        ._purchases
        .map((item) => Container(
              margin: EdgeInsets.symmetric(vertical: 10.0),
              child: Container(
                child: Column(
                  children: <Widget>[
                    Container(
                      margin: EdgeInsets.only(bottom: 5.0),
                      child: Text(
                        item.toString(),
                        style: TextStyle(
                          fontSize: 18.0,
                          color: Colors.black,
                        ),
                      ),
                    )
                  ],
                ),
              ),
            ))
        .toList();
    return widgets;
  }

  @override
  Widget build(BuildContext context) {
    double screenWidth = MediaQuery.of(context).size.width-20;
    double buttonWidth=(screenWidth/3)-20;

    return Container(
      padding: EdgeInsets.all(10.0),
      child: ListView(
        children: <Widget>[
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Container(
                child: Text(
                  'Running on: $_platformVersion\n',
                  style: TextStyle(fontSize: 18.0),
                ),
              ),
              Column(
                children: <Widget>[
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: <Widget>[
                      Container(
                        width: buttonWidth,
                        height: 60.0,
                        margin: EdgeInsets.all(7.0),
                        child: FlatButton(
                          color: Colors.amber,
                          padding: EdgeInsets.all(0.0),
                          onPressed: () async {
                            print("---------- Connect Billing Button Pressed");
                            await FlutterInappPurchase.instance.initConnection;
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(horizontal: 20.0),
                            alignment: Alignment(0.0, 0.0),
                            child: Text(
                              'Connect Billing',
                              style: TextStyle(
                                fontSize: 16.0,
                              ),
                            ),
                          ),
                        ),
                      ),
                      Container(
                        width: buttonWidth,
                        height: 60.0,
                        margin: EdgeInsets.all(7.0),
                        child: FlatButton(
                          color: Colors.amber,
                          padding: EdgeInsets.all(0.0),
                          onPressed: () async {
                            print("---------- End Connection Button Pressed");
                            await FlutterInappPurchase.instance.endConnection;
                            _purchaseUpdatedSubscription.cancel();
                            _purchaseUpdatedSubscription = null;
                            _purchaseErrorSubscription.cancel();
                            _purchaseErrorSubscription = null;
                            setState(() {
                              this._items = [];
                              this._purchases = [];
                            });
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(horizontal: 20.0),
                            alignment: Alignment(0.0, 0.0),
                            child: Text(
                              'End Connection',
                              style: TextStyle(
                                fontSize: 16.0,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        Container(
                            width: buttonWidth,
                            height: 60.0,
                            margin: EdgeInsets.all(7.0),
                            child: FlatButton(
                              color: Colors.green,
                              padding: EdgeInsets.all(0.0),
                              onPressed: () {
                                print("---------- Get Items Button Pressed");
                                this._getProduct();
                              },
                              child: Container(
                                padding: EdgeInsets.symmetric(horizontal: 20.0),
                                alignment: Alignment(0.0, 0.0),
                                child: Text(
                                  'Get Items',
                                  style: TextStyle(
                                    fontSize: 16.0,
                                  ),
                                ),
                              ),
                            )),
                        Container(
                            width: buttonWidth,
                            height: 60.0,
                            margin: EdgeInsets.all(7.0),
                            child: FlatButton(
                              color: Colors.green,
                              padding: EdgeInsets.all(0.0),
                              onPressed: () {
                                print(
                                    "---------- Get Purchases Button Pressed");
                                this._getPurchases();
                              },
                              child: Container(
                                padding: EdgeInsets.symmetric(horizontal: 20.0),
                                alignment: Alignment(0.0, 0.0),
                                child: Text(
                                  'Get Purchases',
                                  style: TextStyle(
                                    fontSize: 16.0,
                                  ),
                                ),
                              ),
                            )),
                        Container(
                            width: buttonWidth,
                            height: 60.0,
                            margin: EdgeInsets.all(7.0),
                            child: FlatButton(
                              color: Colors.green,
                              padding: EdgeInsets.all(0.0),
                              onPressed: () {
                                print(
                                    "---------- Get Purchase History Button Pressed");
                                this._getPurchaseHistory();
                              },
                              child: Container(
                                padding: EdgeInsets.symmetric(horizontal: 20.0),
                                alignment: Alignment(0.0, 0.0),
                                child: Text(
                                  'Get Purchase History',
                                  style: TextStyle(
                                    fontSize: 16.0,
                                  ),
                                ),
                              ),
                            )),
                      ]),
                ],
              ),
              Column(
                children: this._renderInApps(),
              ),
              Column(
                children: this._renderPurchases(),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_inapp_purchase: ^2.0.2

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
92
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
96
Learn more about scoring.

We analyzed this package on Oct 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.5.1
  • pana: 0.12.21
  • Flutter: 1.9.1+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Health suggestions

Format lib/flutter_inapp_purchase.dart.

Run flutter format to format lib/flutter_inapp_purchase.dart.

Format lib/modules.dart.

Run flutter format to format lib/modules.dart.

Format lib/utils.dart.

Run flutter format to format lib/utils.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.20.1 <3.0.0
flutter 0.0.0
http >=0.12.0 <1.0.0 0.12.0+2
meta >=1.0.0 <2.0.0 1.1.7
platform ^2.2.1 2.2.1
Transitive dependencies
async 2.4.0
charcode 1.1.2
collection 1.14.11 1.14.12
http_parser 3.1.3
path 1.6.4
pedantic 1.8.0+1
sky_engine 0.0.99
source_span 1.5.5
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test
mockito ^3.0.0
test ^1.3.0