Skip to content

Commit

Permalink
Crash on Amazon paywalls after purchasing (#1053)
Browse files Browse the repository at this point in the history
In `PurchaseCompleted` we are passing a Flutter's `StoreTransaction` in
the callback. This is very confusing but:

- In Android `StoreTransaction` is what's returned after a successful
purchase. This class has a nullable `orderId`
- In Android `Transaction` is the transactions in the CustomerInfo. This
class has a non-nullable `transactionIdentifier`

The issue we are having is that in Flutter we only have one
`StoreTransaction` with a non-nullable `transactionId`, and we are using
it in both places, the `PurchaseCompleted` and `CustomerInfo`.

I see several ways of fixing this:

- Making transactionIdentifier nullable. I don’t like this. It’s
breaking
- Making transactionIdentifier an empty string. Fixing it in next major
- Making transactionIdentifier an empty string, deprecating it and
creating orderId which is nullable and the same as
transactionIdentifier. We’ll have nullable orderIds in the customer info
transactions where this object is also used. In Android we have two
classes, one for CustomerInfo transactions (Transaction with
non-nullable transactionId ) and StoreTransaction which is used for
completed purchases
- Making a copy of StoreTransaction and name it CompletedPurchase , but
with a nullable transactionIdentifier. Also breaking since we need to
modify the PurchaseCompleted callback to receive this object. Making a
new callback won’t work because the broken `PurchaseCompleted will keep
crashing.

In this PR I am doing number 2, since it's the least breaking. This only
affects apps using Amazon paywalls, which is not many.

Will fix #1049
  • Loading branch information
vegaro authored Apr 29, 2024
1 parent 7df65c5 commit d73f31b
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 38 deletions.
4 changes: 2 additions & 2 deletions lib/models/introductory_price.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/models/period_wrapper.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/models/price_wrapper.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/models/pricing_phase_wrapper.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/models/promotional_offer.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/models/purchases_error.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions lib/models/store_product_discount.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions lib/models/store_transaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ class StoreTransaction with _$StoreTransaction {
/// Experimental. This factory method is subject to changes without
/// a major release.
const factory StoreTransaction.create(
/// RevenueCat Id associated to the transaction.
/// RevenueCat Id associated to the transaction. Empty for Amazon.
// ignore: invalid_annotation_target
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,

/// Deprecated: Use transactionIdentifier instead.
/// Deprecated: Use transactionIdentifier instead. Empty for Amazon.
@Deprecated('Use transactionIdentifier instead.')
// ignore: invalid_annotation_target
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,

/// Product Id associated with the transaction.
Expand Down Expand Up @@ -51,5 +53,6 @@ class StoreTransaction with _$StoreTransaction {
_$StoreTransactionFromJson(json);
}

Object? _readRevenueCatIdentifier(Map json, String key) =>
json['transactionIdentifier'];
// reads json or defaults to '' if not there (Amazon)
Object _readTransactionIdentifier(Map json, String key) =>
json['transactionIdentifier'] ?? '';
58 changes: 37 additions & 21 deletions lib/models/store_transaction.freezed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ StoreTransaction _$StoreTransactionFromJson(Map<String, dynamic> json) {

/// @nodoc
mixin _$StoreTransaction {
/// RevenueCat Id associated to the transaction.
/// RevenueCat Id associated to the transaction. Empty for Amazon.
// ignore: invalid_annotation_target
@JsonKey(readValue: _readTransactionIdentifier)
String get transactionIdentifier => throw _privateConstructorUsedError;

/// Deprecated: Use transactionIdentifier instead.
/// Deprecated: Use transactionIdentifier instead. Empty for Amazon.
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String get revenueCatIdentifier => throw _privateConstructorUsedError;

/// Product Id associated with the transaction.
Expand All @@ -36,9 +38,10 @@ mixin _$StoreTransaction {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate)
Expand All @@ -48,9 +51,10 @@ mixin _$StoreTransaction {
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate)?
Expand All @@ -60,9 +64,10 @@ mixin _$StoreTransaction {
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate)?
Expand Down Expand Up @@ -99,9 +104,10 @@ abstract class $StoreTransactionCopyWith<$Res> {
_$StoreTransactionCopyWithImpl<$Res, StoreTransaction>;
@useResult
$Res call(
{String transactionIdentifier,
{@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate});
Expand Down Expand Up @@ -155,9 +161,10 @@ abstract class _$$StoreTransactionImplCopyWith<$Res>
@override
@useResult
$Res call(
{String transactionIdentifier,
{@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate});
Expand Down Expand Up @@ -204,24 +211,27 @@ class __$$StoreTransactionImplCopyWithImpl<$Res>
@JsonSerializable()
class _$StoreTransactionImpl implements _StoreTransaction {
const _$StoreTransactionImpl(
@JsonKey(readValue: _readTransactionIdentifier)
this.transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
this.revenueCatIdentifier,
this.productIdentifier,
this.purchaseDate);

factory _$StoreTransactionImpl.fromJson(Map<String, dynamic> json) =>
_$$StoreTransactionImplFromJson(json);

/// RevenueCat Id associated to the transaction.
/// RevenueCat Id associated to the transaction. Empty for Amazon.
// ignore: invalid_annotation_target
@override
@JsonKey(readValue: _readTransactionIdentifier)
final String transactionIdentifier;

/// Deprecated: Use transactionIdentifier instead.
/// Deprecated: Use transactionIdentifier instead. Empty for Amazon.
@override
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
final String revenueCatIdentifier;

/// Product Id associated with the transaction.
Expand Down Expand Up @@ -268,9 +278,10 @@ class _$StoreTransactionImpl implements _StoreTransaction {
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate)
Expand All @@ -284,9 +295,10 @@ class _$StoreTransactionImpl implements _StoreTransaction {
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function(
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate)?
Expand All @@ -300,9 +312,10 @@ class _$StoreTransactionImpl implements _StoreTransaction {
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(
@JsonKey(readValue: _readTransactionIdentifier)
String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String revenueCatIdentifier,
String productIdentifier,
String purchaseDate)?
Expand Down Expand Up @@ -354,9 +367,10 @@ class _$StoreTransactionImpl implements _StoreTransaction {

abstract class _StoreTransaction implements StoreTransaction {
const factory _StoreTransaction(
@JsonKey(readValue: _readTransactionIdentifier)
final String transactionIdentifier,
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
final String revenueCatIdentifier,
final String productIdentifier,
final String purchaseDate) = _$StoreTransactionImpl;
Expand All @@ -366,13 +380,15 @@ abstract class _StoreTransaction implements StoreTransaction {

@override

/// RevenueCat Id associated to the transaction.
/// RevenueCat Id associated to the transaction. Empty for Amazon.
// ignore: invalid_annotation_target
@JsonKey(readValue: _readTransactionIdentifier)
String get transactionIdentifier;
@override

/// Deprecated: Use transactionIdentifier instead.
/// Deprecated: Use transactionIdentifier instead. Empty for Amazon.
@Deprecated('Use transactionIdentifier instead.')
@JsonKey(readValue: _readRevenueCatIdentifier)
@JsonKey(readValue: _readTransactionIdentifier)
String get revenueCatIdentifier;
@override

Expand Down
4 changes: 2 additions & 2 deletions lib/models/store_transaction.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d73f31b

Please sign in to comment.