Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions packages/in_app_purchase/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,68 @@
## 0.1.0

Beta relase.

* Ability to list products, load previous purchases, and make purchases.
* Simplified Dart API that's been unified for ease of use.
* Platform specific APIs more directly exposing `StoreKit` and `BillingClient`.

Includes:

* 5ba657dc [in_app_purchase] Remove extraneous download logic (#1560)
* 01bb8796 [in_app_purchase] Minor doc updates (#1555)
* 1a4d493f [in_app_purchase] Only fetch owned purchases (#1540)
* d63c51cf [in_app_purchase] Add auto-consume errors to PurchaseDetails (#1537)
* 959da97f [in_app_purchase] Minor doc updates (#1536)
* b82ae1a6 [in_app_purchase] Rename the unified API (#1517)
* d1ad723a [in_app_purchase]remove SKDownloadWrapper and related code. (#1474)
* 7c1e8b8a [in_app_purchase]make payment unified APIs (#1421)
* 80233db6 [in_app_purchase] Add references to the original object for PurchaseDetails and ProductDetails (#1448)
* 8c180f0d [in_app_purchase]load purchase (#1380)
* e9f141bc [in_app_purchase] Iap refactor (#1381)
* d3b3d60c add driver test command to cirrus (#1342)
* aee12523 [in_app_purchase] refactoring and tests (#1322)
* 6d7b4592 [in_app_purchase] Adds Dart BillingClient APIs for loading purchases (#1286)
* 5567a9c8 [in_app_purchase]retrieve receipt (#1303)
* 3475f1b7 [in_app_purchase]restore purchases (#1299)
* a533148d [in_app_purchase] payment queue dart ios (#1249)
* 10030840 [in_app_purchase] Minor bugfixes and code cleanup (#1284)
* 347f508d [in_app_purchase] Fix CI formatting errors. (#1281)
* fad02d87 [in_app_purchase] Java API for querying purchases (#1259)
* bc501915 [In_app_purchase]SKProduct related fixes (#1252)
* f92ba3a1 IAP make payment objc (#1231)
* 62b82522 [IAP] Add the Dart API for launchBillingFlow (#1232)
* b40a4acf [IAP] Add Java call for launchBillingFlow (#1230)
* 4ff06cd1 [In_app_purchase]remove categories (#1222)
* 0e72ca56 [In_app_purchase]fix requesthandler crash (#1199)
* 81dff2be Iap getproductlist basic draft (#1169)
* db139b28 Iap iOS add payment dart wrappers (#1178)
* 2e5fbb9b Fix the param map passed down to the platform channel when calling querySkuDetails (#1194)
* 4a84bac1 Mark some packages as unpublishable (#1193)
* 51696552 Add a gradle warning to the AndroidX plugins (#1138)
* 832ab832 Iap add payment objc translators (#1172)
* d0e615cf Revert "IAP add payment translators in objc (#1126)" (#1171)
* 09a5a36e IAP add payment translators in objc (#1126)
* a100fbf9 Expose nslocale and expose currencySymbol instead of currencyCode to match android (#1162)
* 1c982efd Using json serializer for skproduct wrapper and related classes (#1147)
* 3039a261 Iap productlist ios (#1068)
* 2a1593da [IAP] Update dev deps to match flutter_driver (#1118)
* 9f87cbe5 [IAP] Update README (#1112)
* 59e84d85 Migrate independent plugins to AndroidX (#1103)
* a027ccd6 [IAP] Generate boilerplate serializers (#1090)
* 909cf1c2 [IAP] Fetch SkuDetails from Google Play (#1084)
* 6bbaa7e5 [IAP] Add missing license headers (#1083)
* 5347e877 [IAP] Clean up Dart unit tests (#1082)
* fe03e407 [IAP] Check if the payment processor is available (#1057)
* 43ee28cf Fix `Manifest versionCode not found` (#1076)
* 4d702ad7 Supress `strong_mode_implicit_dynamic_method` for `invokeMethod` calls. (#1065)
* 809ccde7 Doc and build script updates to the IAP plugin (#1024)
* 052b71a9 Update the IAP README (#933)
* 54f9c4e2 Upgrade Android Gradle Plugin to 3.2.1 (#916)
* ced3e99d Set all gradle-wrapper versions to 4.10.2 (#915)
* eaa1388b Reconfigure Cirrus to use clang 7 (#905)
* 9b153920 Update gradle dependencies. (#881)
* 1aef7d92 Enable lint unnecessary_new (#701)

## 0.0.2

* Added missing flutter_test package dependency.
Expand Down
160 changes: 132 additions & 28 deletions packages/in_app_purchase/README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,149 @@
# In App Purchase

A Flutter plugin for in-app purchases.
A Flutter plugin for in-app purchases. Exposes APIs for making in app purchases
through the App Store (on iOS) and Google Play (on Android).

## Getting Started
## Features

This plugin is not ready to be used yet. Follow
[flutter/flutter#9591](https://github.com/flutter/flutter/issues/9591) for more
updates.
Add this to your Flutter app to:

There's a significant amount of setup required for testing in app purchases
successfully, including registering new app IDs and store entries to use for
testing in both the Play Developer Console and App Store Connect. Both Google
Play and the App Store require developers to configure an app with in-app items
for purchase to call their in-app-purchase APIs. You can check out the [example
app](example/README.md) for an example on configuring both.
1. Show in app products that are available for sale from the underlying shop.
Includes consumables, permanent upgrades, and subscriptions.
2. Load in app products currently owned by the user according to the underlying
shop.
3. Send your user to the underlying store to purchase your products.

## Development
## Getting Started

This plugin uses
[json_serializable](https://pub.dartlang.org/packages/json_serializable) for the
many data structs passed between the underlying platform layers and Dart. After
editing any of the serialized data structs, rebuild the serializers by running
`flutter packages pub run build_runner build --delete-conflicting-outputs`.
`flutter packages pub run build_runner watch --delete-conflicting-outputs` will
watch the filesystem for changes.
This plugin is in beta. Please use with caution and file any potential issues
you see on our [issue tracker](https://github.com/flutter/flutter/issues/new/choose).

### Design
This plugin relies on the App Store and Google Play for making in app purchases.
It exposes a unified surface, but you'll still need to understand and configure
your app with each store to handle purchases using them. Both have extensive
guides:

The API surface is stacked into 2 main layers.
* [In-App Purchase (App Store)](https://developer.apple.com/in-app-purchase/)
* [Google Play Biling Overview](https://developer.android.com/google/play/billing/billing_overview)

You can check out the [example app README](example/README.md) for steps on how
to configure in app purchases in both stores.

Once you've configured your in app purchases in their respective stores, you're
able to start using the plugin. There's two basic options available to you to
use.

1. [in_app_purchase.dart](lib/src/in_app_purchase.dart),
the generic idiommatic Flutter API. This exposes the most basic IAP-related
functionality. The goal is that Flutter apps should be able to use this API
surface on its own for the vast majority of cases.
[google_play_connection.dart](lib/src/google_play_connection.dart) and
[app_store_connection.dart](lib/src/app_store_connection.dart) implement this
for the specific platforms.
surface on its own for the vast majority of cases. If you use this you should
be able to handle most use cases for loading and making purchases. If you would
like a more platform dependent approach, we also provide the second option as
below.

2. The dart wrappers around the platform specific IAP APIs and their platform
specific implementations of the generic interface. See
2. Dart APIs exposing the underlying platform APIs as directly as possible:
[store_kit_wrappers.dart](lib/src/store_kit_wrappers.dart) and
[billing_client_wrappers.dart](lib/src/billing_client_wrappers.dart). These
API surfaces should expose all the platform-specific behavior and allow for
more fine-tuned control when needed.
more fine-tuned control when needed. However if you use this you'll need to
code your purchase handling logic significantly differently depending on
which platform you're on.

### Initializing the plugin

```dart
// Subscribe to any incoming purchases at app initialization. These can
// propagate from either storefront so it's important to listen as soon as
// possible to avoid losing events.
class _MyAppState extends State<MyApp> {
StreamSubscription<List<PurchaseDetails>> _subscription;

@override
void initState() {
final Stream purchaseUpdates =
InAppPurchaseConnection.instance.purchaseUpdatedStream;
_subscription = purchaseUpdates.listen((List<PurchaseDetails> purchases) {
_handlePurchaseUpdates(purchases);
});
super.initState();
}

@override
void dispose() {
_subscription.cancel();
super.dispose();
}
```

### Connecting to the Storefront

```dart
final bool available = await InAppPurchaseConnection.instance.isAvailable();
if (!available) {
// The store cannot be reached or accessed. Update the UI accordingly.
}
```

### Loading products for sale

```dart
const Set<String> _kIds = <String>['product1', 'product2'].toSet();
final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(_kIds);
if (!response.notFoundIds.isEmpty()) {
// Handle the error.
}
List<ProductDetails> products = response.productDetails;
```

### Loading previous purchases

```dart
final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
if (response.error != null) {
// Handle the error.
}
for (PurchaseDetails purchase : repsonse.pastPurchases) {
_verifyPurchase(purchase); // Verify the purchase following the best practices for each storefront.
_deliverPurchase(purchase); // Deliver the purchase to the user in your app.
if (Platform.isIOS) {
// Mark that you've delivered the purchase. Only the App Store requires
// this final confirmation.
InAppPurchaseConnection.instance.completePurchase(purchase);
}
}
```

Note that the App Store does not have any APIs for querying consummable
products, and Google Play considers consummable products to no longer be owned
once they're marked as consumed and fails to return them here. For restoring
these across devices you'll need to persist them on your own server and query
that as well.

### Making a purchase

Both storefronts handle consummable and non-consummable products differently. If
you're using `InAppPurchaseConnection`, you need to make a distinction here and
call the right purchase method for each type.

```dart
final ProductDetails productDetails = ... // Saved earlier from queryPastPurchases().
final PurchaseParam purchaseParam = PurchaseParam(productDetails: productDetails);
if (_isConsumable(productDetails)) {
InAppPurchaseConnection.instance.buyConsumable(purchaseParam: purchaseParam);
} else {
InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam);
}

// From here the purchase flow will be handled by the underlying storefront.
// Updates will be delivered to the `InAppPurchaseConnection.instance.purchaseUpdatedStream`.
```

## Development

This plugin uses
[json_serializable](https://pub.dartlang.org/packages/json_serializable) for the
many data structs passed between the underlying platform layers and Dart. After
editing any of the serialized data structs, rebuild the serializers by running
`flutter packages pub run build_runner build --delete-conflicting-outputs`.
`flutter packages pub run build_runner watch --delete-conflicting-outputs` will
watch the filesystem for changes.
13 changes: 8 additions & 5 deletions packages/in_app_purchase/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ Demonstrates how to use the In App Purchase (IAP) Plugin.

## Getting Started

WARNING: This plugin and example are not ready to be used. Right now the example
app doesn't actually demonstrate any IAP functionality yet. Follow
[flutter/flutter#9591](https://github.com/flutter/flutter/issues/9591) for more
updates.
This plugin is in beta. Please use with caution and file any potential issues
you see on our [issue tracker](https://github.com/flutter/flutter/issues/new/choose).

There's a significant amount of setup required for testing in app purchases
successfully, including registering new app IDs and store entries to use for
testing in both the Play Developer Console and App Store Connect. Both Google
Play and the App Store require developers to configure an app with in-app items
for purchase to call their in-app-purchase APIs.
for purchase to call their in-app-purchase APIs. Both stores have extensive
documentation on how to do this, and we've also included a high level guide
below.

* [In-App Purchase (App Store)](https://developer.apple.com/in-app-purchase/)
* [Google Play Biling Overview](https://developer.android.com/google/play/billing/billing_overview)

### Android

Expand Down
4 changes: 2 additions & 2 deletions packages/in_app_purchase/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ name: in_app_purchase
description: A Flutter plugin for in-app purchases.
author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase
version: 0.0.2
publish_to: none # Not ready to be uploaded
version: 0.1.0

dependencies:
async: ^2.0.8
collection: ^1.14.11
flutter:
sdk: flutter
json_annotation: ^2.0.0
Expand Down