Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[in_app_purchase]load purchase #1380

Merged
merged 44 commits into from
Apr 4, 2019
Merged

Conversation

cyanglaz
Copy link
Contributor

Description

Adding unified IAP load purchase api.
Updated the example app to have indicators on already purchased items.
No pubspec and CHANGELOG.md is updated since this plugin is still under development.

Related Issues

flutter/flutter#26326

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

@cyanglaz cyanglaz closed this Mar 22, 2019
@cyanglaz cyanglaz reopened this Mar 22, 2019
Copy link
Contributor

@mklim mklim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

@@ -10,7 +10,7 @@ This example initially uses a default project for CI purposes. You must
replace the default project with your own so that you can review the error
reports submitted to the Firebase console.

See [docs](https://firebase.google.com/docs/flutter/setup) for how to add
See [docs](https://firebase.google.com/docs/flutter/setup) for how to add
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all the changes under packages/firebase_crashlytics should be split out into their own changes.

@@ -118,6 +117,31 @@ class _MyAppState extends State<MyApp> {
'This app needs special configuration to run. Please see example/README.md for instructions.')));
}

print('xyzzy about to query past purchases');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These debug logs should be removed.


/// Triggered when any transactions are updated.
void updatedTransactions({List<SKPaymentTransactionWrapper> transactions}) {
assert(_restoreCompleter != null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we call cleanUpRestoredTransactions() and then this triggers from a new purchase?


/// The original purchase data of this purchase.
///
/// It is only available when this purchase is a restored purchase in iOS.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to nest the originalPurchase here? I think it would be cleaner if the structure of this was the same across all our platforms.

/// The response object for fetching the past purchases.
///
/// An instance of this class is returned in [InAppPurchaseConnection.queryPastPurchases].
class QueryPastPurchaseResponse {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think QueryPurchaseDetails makes a little more sense as a name here since it matches what this is returning.

@@ -16,6 +128,18 @@ abstract class InAppPurchaseConnection {
/// Query product details list that match the given set of identifiers.
Future<ProductDetailsResponse> queryProductDetails(Set<String> identifiers);

/// Query all the past purchases.
///
/// The `applicationUserName` is used for iOS only and it is optional. It does not have any effects on Android.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thoughts above about asking people to case on this. Even if this isn't really used in Play I think it would probably be cleaner for users to just always pass this in if they also passed it in for originally making a purchase. I think it would be clearer here if we said that it is required in cases where this was passed in with the original transaction.

Future<QueryPastPurchaseResponse> queryPastPurchases(
{String applicationUserName});

/// Get a refreshed purchase verification data.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sort of rephrases the method name. Maybe mention that this is a utility in case there's an issue with getting the verification data originally, and as long as that's not null this doesn't need to be called?

Chris Yang and others added 8 commits March 26, 2019 14:09
…ase_wrapper.dart

Co-Authored-By: cyanglaz <ychris@google.com>
…ogle_play_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
…_app_purchase_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
…_app_purchase_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
…_app_purchase_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
Copy link
Contributor

@mklim mklim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking pretty good. The only thing left that I'd really like to see updated is the param type on restoreCompletedTransactionsFailed.

packages/in_app_purchase/example/lib/main.dart Outdated Show resolved Hide resolved
packages/in_app_purchase/example/lib/main.dart Outdated Show resolved Hide resolved
packages/in_app_purchase/example/lib/main.dart Outdated Show resolved Hide resolved
return wrapper.transactionState ==
SKPaymentTransactionStateWrapper.restored;
}).toList();
if (_restoreCompleter != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subjective: I think an early return/guard clause would make this more readable.

https://testing.googleblog.com/2017/06/code-health-reduce-nesting-reduce.html

/// on Android, all purchase information should also be verified manually, with your
/// server if at all possible. See [`Verify a purchase`](https://developer.android.com/google/play/billing/billing_library_overview#Verify).
/// On Android, all purchase information should also be verified manually. See [`Verify a purchase`](https://developer.android.com/google/play/billing/billing_library_overview#Verify).
///
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This line can be deleted.

final Map<String, dynamic> message;
}

/// Represents the transaction details of a purchase.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still think this one is worth adding. "Transactions" on iOS can have multiple statuses so I think it's worth pointing out which one this is.

void restoreCompletedTransactions({Error error});
///
/// The error is represented in a Map. The map contains `errorCode` and `message`
void restoreCompletedTransactionsFailed({Map<String, String> error});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably define a class with these props on it instead of using a map. The Map leaves this open to a bunch of dynamic typing kinds of bugs.

Michael Klimushyn and others added 9 commits March 27, 2019 13:57
Co-Authored-By: cyanglaz <ychris@google.com>
Co-Authored-By: cyanglaz <ychris@google.com>
Co-Authored-By: cyanglaz <ychris@google.com>
…_app_purchase_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
…_app_purchase_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
…_app_purchase_connection.dart

Co-Authored-By: cyanglaz <ychris@google.com>
Copy link
Contributor

@mklim mklim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@cyanglaz cyanglaz closed this Mar 28, 2019
@cyanglaz cyanglaz deleted the iap_load_purchase branch March 28, 2019 18:49
@cyanglaz cyanglaz restored the iap_load_purchase branch April 4, 2019 23:19
@cyanglaz cyanglaz reopened this Apr 4, 2019
@cyanglaz cyanglaz merged commit 8c180f0 into flutter:master Apr 4, 2019
@cyanglaz cyanglaz deleted the iap_load_purchase branch April 4, 2019 23:21
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants