| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:json_annotation/json_annotation.dart'; |
| |
| import 'enum_converters.dart'; |
| import 'sk_payment_queue_wrapper.dart'; |
| import 'sk_product_wrapper.dart'; |
| |
| part 'sk_payment_transaction_wrappers.g.dart'; |
| |
| /// Callback handlers for transaction status changes. |
| /// |
| /// Must be subclassed. Must be instantiated and added to the |
| /// [SKPaymentQueueWrapper] via [SKPaymentQueueWrapper.setTransactionObserver] |
| /// at app launch. |
| /// |
| /// This class is a Dart wrapper around [SKTransactionObserver](https://developer.apple.com/documentation/storekit/skpaymenttransactionobserver?language=objc). |
| abstract class SKTransactionObserverWrapper { |
| /// Triggered when any transactions are updated. |
| void updatedTransactions( |
| {required List<SKPaymentTransactionWrapper> transactions}); |
| |
| /// Triggered when any transactions are removed from the payment queue. |
| void removedTransactions( |
| {required List<SKPaymentTransactionWrapper> transactions}); |
| |
| /// Triggered when there is an error while restoring transactions. |
| void restoreCompletedTransactionsFailed({required SKError error}); |
| |
| /// Triggered when payment queue has finished sending restored transactions. |
| void paymentQueueRestoreCompletedTransactionsFinished(); |
| |
| /// Triggered when a user initiates an in-app purchase from App Store. |
| /// |
| /// Return `true` to continue the transaction in your app. If you have |
| /// multiple [SKTransactionObserverWrapper]s, the transaction will continue if |
| /// any [SKTransactionObserverWrapper] returns `true`. Return `false` to defer |
| /// or cancel the transaction. For example, you may need to defer a |
| /// transaction if the user is in the middle of onboarding. You can also |
| /// continue the transaction later by calling [addPayment] with the |
| /// `payment` param from this method. |
| bool shouldAddStorePayment( |
| {required SKPaymentWrapper payment, required SKProductWrapper product}); |
| } |
| |
| /// The state of a transaction. |
| /// |
| /// Dart wrapper around StoreKit's |
| /// [SKPaymentTransactionState](https://developer.apple.com/documentation/storekit/skpaymenttransactionstate?language=objc). |
| enum SKPaymentTransactionStateWrapper { |
| /// Indicates the transaction is being processed in App Store. |
| /// |
| /// You should update your UI to indicate that you are waiting for the |
| /// transaction to update to another state. Never complete a transaction that |
| /// is still in a purchasing state. |
| @JsonValue(0) |
| purchasing, |
| |
| /// The user's payment has been succesfully processed. |
| /// |
| /// You should provide the user the content that they purchased. |
| @JsonValue(1) |
| purchased, |
| |
| /// The transaction failed. |
| /// |
| /// Check the [SKPaymentTransactionWrapper.error] property from |
| /// [SKPaymentTransactionWrapper] for details. |
| @JsonValue(2) |
| failed, |
| |
| /// This transaction is restoring content previously purchased by the user. |
| /// |
| /// The previous transaction information can be obtained in |
| /// [SKPaymentTransactionWrapper.originalTransaction] from |
| /// [SKPaymentTransactionWrapper]. |
| @JsonValue(3) |
| restored, |
| |
| /// The transaction is in the queue but pending external action. Wait for |
| /// another callback to get the final state. |
| /// |
| /// You should update your UI to indicate that you are waiting for the |
| /// transaction to update to another state. |
| @JsonValue(4) |
| deferred, |
| |
| /// Indicates the transaction is in an unspecified state. |
| @JsonValue(-1) |
| unspecified, |
| } |
| |
| /// Created when a payment is added to the [SKPaymentQueueWrapper]. |
| /// |
| /// Transactions are delivered to your app when a payment is finished |
| /// processing. Completed transactions provide a receipt and a transaction |
| /// identifier that the app can use to save a permanent record of the processed |
| /// payment. |
| /// |
| /// Dart wrapper around StoreKit's |
| /// [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction?language=objc). |
| @JsonSerializable(createToJson: true) |
| @immutable |
| class SKPaymentTransactionWrapper { |
| /// Creates a new [SKPaymentTransactionWrapper] with the provided information. |
| // TODO(stuartmorgan): Temporarily ignore const warning in other parts of the |
| // federated package, and remove this. |
| // ignore: prefer_const_constructors_in_immutables |
| SKPaymentTransactionWrapper({ |
| required this.payment, |
| required this.transactionState, |
| this.originalTransaction, |
| this.transactionTimeStamp, |
| this.transactionIdentifier, |
| this.error, |
| }); |
| |
| /// Constructs an instance of this from a key value map of data. |
| /// |
| /// The map needs to have named string keys with values matching the names and |
| /// types of all of the members on this class. The `map` parameter must not be |
| /// null. |
| factory SKPaymentTransactionWrapper.fromJson(Map<String, dynamic> map) { |
| return _$SKPaymentTransactionWrapperFromJson(map); |
| } |
| |
| /// Current transaction state. |
| @SKTransactionStatusConverter() |
| final SKPaymentTransactionStateWrapper transactionState; |
| |
| /// The payment that has been created and added to the payment queue which |
| /// generated this transaction. |
| final SKPaymentWrapper payment; |
| |
| /// The original Transaction. |
| /// |
| /// Only available if the [transactionState] is [SKPaymentTransactionStateWrapper.restored]. |
| /// Otherwise the value is `null`. |
| /// |
| /// When the [transactionState] |
| /// is [SKPaymentTransactionStateWrapper.restored], the current transaction |
| /// object holds a new [transactionIdentifier]. |
| final SKPaymentTransactionWrapper? originalTransaction; |
| |
| /// The timestamp of the transaction. |
| /// |
| /// Seconds since epoch. It is only defined when the [transactionState] is |
| /// [SKPaymentTransactionStateWrapper.purchased] or |
| /// [SKPaymentTransactionStateWrapper.restored]. |
| /// Otherwise, the value is `null`. |
| final double? transactionTimeStamp; |
| |
| /// The unique string identifer of the transaction. |
| /// |
| /// It is only defined when the [transactionState] is |
| /// [SKPaymentTransactionStateWrapper.purchased] or |
| /// [SKPaymentTransactionStateWrapper.restored]. You may wish to record this |
| /// string as part of an audit trail for App Store purchases. The value of |
| /// this string corresponds to the same property in the receipt. |
| /// |
| /// The value is `null` if it is an unsuccessful transaction. |
| final String? transactionIdentifier; |
| |
| /// The error object |
| /// |
| /// Only available if the [transactionState] is |
| /// [SKPaymentTransactionStateWrapper.failed]. |
| final SKError? error; |
| |
| @override |
| bool operator ==(Object other) { |
| if (identical(other, this)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| return other is SKPaymentTransactionWrapper && |
| other.payment == payment && |
| other.transactionState == transactionState && |
| other.originalTransaction == originalTransaction && |
| other.transactionTimeStamp == transactionTimeStamp && |
| other.transactionIdentifier == transactionIdentifier && |
| other.error == error; |
| } |
| |
| @override |
| int get hashCode => Object.hash(payment, transactionState, |
| originalTransaction, transactionTimeStamp, transactionIdentifier, error); |
| |
| @override |
| String toString() => _$SKPaymentTransactionWrapperToJson(this).toString(); |
| |
| /// The payload that is used to finish this transaction. |
| Map<String, String?> toFinishMap() => <String, String?>{ |
| 'transactionIdentifier': transactionIdentifier, |
| 'productIdentifier': payment.productIdentifier, |
| }; |
| } |