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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:in_app_purchase/src/channel.dart';
import 'package:json_annotation/json_annotation.dart';
Expand Down Expand Up @@ -214,7 +215,7 @@ enum SKPaymentTransactionStateWrapper {
/// Indicates the transaction is being processed in App Store.
///
/// You should update your UI to indicate the process and waiting for the transaction to update to the next state.
/// Never complte a transaction that is in purchasing state.
/// Never complete a transaction that is in purchasing state.
@JsonValue(0)
purchasing,

Expand Down Expand Up @@ -302,6 +303,24 @@ class SKPaymentTransactionWrapper {

/// 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;
}
final SKPaymentTransactionWrapper typedOther = other;
return typedOther.payment == payment &&
typedOther.transactionState == transactionState &&
typedOther.originalTransaction == originalTransaction &&
typedOther.transactionTimeStamp == transactionTimeStamp &&
typedOther.transactionIdentifier == transactionIdentifier &&
DeepCollectionEquality().equals(typedOther.downloads, downloads) &&
typedOther.error == error;
}
}

/// Dart wrapper around StoreKit's [SKDownloadState](https://developer.apple.com/documentation/storekit/skdownloadstate?language=objc).
Expand Down Expand Up @@ -403,6 +422,27 @@ class SKDownloadWrapper {

/// The error that prevented the downloading; 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;
}
final SKDownloadWrapper typedOther = other;
return typedOther.contentIdentifier == contentIdentifier &&
typedOther.state == state &&
typedOther.contentLength == contentLength &&
typedOther.contentURL == contentURL &&
typedOther.contentVersion == contentVersion &&
typedOther.transactionID == transactionID &&
typedOther.progress == progress &&
typedOther.timeRemaining == timeRemaining &&
typedOther.downloadTimeUnknown == downloadTimeUnknown &&
typedOther.error == error;
}
}

/// Dart wrapper around StoreKit's [NSError](https://developer.apple.com/documentation/foundation/nserror?language=objc).
Expand Down Expand Up @@ -430,6 +470,21 @@ class SKError {

/// A map that contains more detailed information about the error. Any key of the map must be one of the [NSErrorUserInfoKey](https://developer.apple.com/documentation/foundation/nserroruserinfokey?language=objc).
final Map<String, dynamic> userInfo;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SKError typedOther = other;
return typedOther.code == code &&
typedOther.domain == domain &&
DeepCollectionEquality.unordered()
.equals(typedOther.userInfo, userInfo);
}
}

/// Dart wrapper around StoreKit's [SKPayment](https://developer.apple.com/documentation/storekit/skpayment?language=objc).
Expand Down Expand Up @@ -474,7 +529,7 @@ class SKPaymentWrapper {
/// An opaque id for the user's account.
///
/// Used to help the store detect irregular activity. See https://developer.apple.com/documentation/storekit/skpayment/1506116-applicationusername?language=objc for more details.
/// For example, you can use a one-way hash of the user’s account name on your server. Don’t use the Apple ID for your developer account, the user’s Apple ID, or the user’s unhashed account name on your server.
/// For example, you can use a one-way hash of the user’s account name on your server. Don’t use the Apple ID for your developer account, the user’s Apple ID, or the user’s not hashed account name on your server.
final String applicationUsername;

/// Reserved for future use.
Expand All @@ -493,4 +548,20 @@ class SKPaymentWrapper {
///
/// For how to test in App Store sand box, see https://developer.apple.com/in-app-purchase/.
final bool simulatesAskToBuyInSandbox;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SKPaymentWrapper typedOther = other;
return typedOther.productIdentifier == productIdentifier &&
typedOther.applicationUsername == applicationUsername &&
typedOther.quantity == quantity &&
typedOther.simulatesAskToBuyInSandbox == simulatesAskToBuyInSandbox &&
typedOther.requestData == requestData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'package:flutter/foundation.dart';
import 'package:collection/collection.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:in_app_purchase/src/in_app_purchase_connection/product_details.dart';

Expand Down Expand Up @@ -41,14 +42,28 @@ class SkProductResponseWrapper {
/// found here https://developer.apple.com/documentation/storekit/skproductsresponse/1505985-invalidproductidentifiers?language=objc.
/// Will be empty if all the product identifiers are valid.
final List<String> invalidProductIdentifiers;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SkProductResponseWrapper typedOther = other;
return DeepCollectionEquality().equals(typedOther.products, products) &&
DeepCollectionEquality().equals(
typedOther.invalidProductIdentifiers, invalidProductIdentifiers);
}
}

/// Dart wrapper around StoreKit's [SKProductPeriodUnit](https://developer.apple.com/documentation/storekit/skproductperiodunit?language=objc).
///
/// Used as a property in the [SKProductSubscriptionPeriodWrapper]. Minium is a day and maxium is a year.
/// Used as a property in the [SKProductSubscriptionPeriodWrapper]. Minimum is a day and maximum is a year.
// The values of the enum options are matching the [SKProductPeriodUnit]'s values. Should there be an update or addition
// in the [SKProductPeriodUnit], this need to be updated to match.
enum SubscriptionPeriodUnit {
enum SKSubscriptionPeriodUnit {
@JsonValue(0)
day,
@JsonValue(1)
Expand Down Expand Up @@ -83,15 +98,27 @@ class SKProductSubscriptionPeriodWrapper {
final int numberOfUnits;

/// The time unit used to specify the length of this period.
final SubscriptionPeriodUnit unit;
final SKSubscriptionPeriodUnit unit;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SKProductSubscriptionPeriodWrapper typedOther = other;
return typedOther.numberOfUnits == numberOfUnits && typedOther.unit == unit;
}
}

/// Dart wrapper around StoreKit's [SKProductDiscountPaymentMode](https://developer.apple.com/documentation/storekit/skproductdiscountpaymentmode?language=objc).
///
/// This is used as a property in the [SKProductDiscountWrapper].
// The values of the enum options are matching the [SKProductDiscountPaymentMode]'s values. Should there be an update or addition
// in the [SKProductDiscountPaymentMode], this need to be updated to match.
enum ProductDiscountPaymentMode {
enum SKProductDiscountPaymentMode {
/// Allows user to pay the discounted price at each payment period.
@JsonValue(0)
payAsYouGo,
Expand Down Expand Up @@ -130,21 +157,37 @@ class SKProductDiscountWrapper {
final String price;

/// Includes locale information about the price, e.g. `$` as the currency symbol for US locale.
final PriceLocaleWrapper priceLocale;
final SKPriceLocaleWrapper priceLocale;

/// The object represent the discount period length.
///
/// The value must be >= 0.
final int numberOfPeriods;

/// The object indicates how the discount price is charged.
final ProductDiscountPaymentMode paymentMode;
final SKProductDiscountPaymentMode paymentMode;

/// The object represents the duration of single subscription period for the discount.
///
/// The [subscriptionPeriod] of the discount is independent of the product's [subscriptionPeriod],
/// and their units and duration do not have to be matched.
final SKProductSubscriptionPeriodWrapper subscriptionPeriod;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SKProductDiscountWrapper typedOther = other;
return typedOther.price == price &&
typedOther.priceLocale == priceLocale &&
typedOther.numberOfPeriods == numberOfPeriods &&
typedOther.paymentMode == paymentMode &&
typedOther.subscriptionPeriod == subscriptionPeriod;
}
}

/// Dart wrapper around StoreKit's [SKProduct](https://developer.apple.com/documentation/storekit/skproduct?language=objc).
Expand Down Expand Up @@ -190,7 +233,7 @@ class SKProductWrapper {
final String localizedDescription;

/// Includes locale information about the price, e.g. `$` as the currency symbol for US locale.
final PriceLocaleWrapper priceLocale;
final SKPriceLocaleWrapper priceLocale;

/// The version of the downloadable content.
///
Expand Down Expand Up @@ -226,12 +269,35 @@ class SKProductWrapper {
/// The object represents the duration of single subscription period.
///
/// This is only available if you set up the introductory price in the App Store Connect, otherwise it will be null.
/// Programmar is also responsible to determine if the user is eligible to receive it. See https://developer.apple.com/documentation/storekit/in-app_purchase/offering_introductory_pricing_in_your_app?language=objc
/// Programmer is also responsible to determine if the user is eligible to receive it. See https://developer.apple.com/documentation/storekit/in-app_purchase/offering_introductory_pricing_in_your_app?language=objc
/// for more details.
/// The [subscriptionPeriod] of the discount is independent of the product's [subscriptionPeriod],
/// and their units and duration do not have to be matched.
final SKProductDiscountWrapper introductoryPrice;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SKProductWrapper typedOther = other;
return typedOther.productIdentifier == productIdentifier &&
typedOther.localizedTitle == localizedTitle &&
typedOther.localizedDescription == localizedDescription &&
typedOther.priceLocale == priceLocale &&
typedOther.downloadContentVersion == downloadContentVersion &&
typedOther.subscriptionGroupIdentifier == subscriptionGroupIdentifier &&
typedOther.price == price &&
typedOther.downloadable == downloadable &&
DeepCollectionEquality.unordered().equals(
typedOther.downloadContentLengths, downloadContentLengths) &&
typedOther.subscriptionPeriod == subscriptionPeriod &&
typedOther.introductoryPrice == introductoryPrice;
}

/// Method to convert to the wrapper to the consolidated [ProductDetails] class.
ProductDetails toProductDetails() {
return ProductDetails(
Expand All @@ -250,18 +316,30 @@ class SKProductWrapper {
// Matching android to only get the currencySymbol for now.
// https://github.com/flutter/flutter/issues/26610
@JsonSerializable()
class PriceLocaleWrapper {
PriceLocaleWrapper({@required this.currencySymbol});
class SKPriceLocaleWrapper {
SKPriceLocaleWrapper({@required this.currencySymbol});

/// Constructing an instance from a map from the Objective-C layer.
///
/// This method should only be used with `map` values returned by [SKProductWrapper.fromJson] and [SKProductDiscountWrapper.fromJson].
/// The `map` parameter must not be null.
factory PriceLocaleWrapper.fromJson(Map map) {
factory SKPriceLocaleWrapper.fromJson(Map map) {
assert(map != null, 'Map must not be null.');
return _$PriceLocaleWrapperFromJson(map);
}

///The currency symbol for the locale, e.g. $ for US locale.
final String currencySymbol;

@override
bool operator ==(Object other) {
if (identical(other, this)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final SKPriceLocaleWrapper typedOther = other;
return typedOther.currencySymbol == currencySymbol;
}
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class SKReceiptManager {
/// There are 2 ways to do so. Either validate locally or validate with App Store.
/// For more details on how to validate the receipt data, you can refer to Apple's document about [`About Receipt Validation`](https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Introduction.html#//apple_ref/doc/uid/TP40010573-CH105-SW1).
/// If the receipt is invalid or missing, you can use [SKRequestMaker.startRefreshReceiptRequest] to request a new receipt.
Future<String> retrieveReceiptData() {
static Future<String> retrieveReceiptData() {
return channel
.invokeMethod('-[InAppPurchasePlugin retrieveReceiptData:result:]');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import 'sk_product_wrapper.dart';
class SKRequestMaker {
/// Fetches product information for a list of given product identifiers.
///
/// The `productIdentifiers` should contain legit product identifiers that you declared for the products in the Itunes Connect. invalid identifiers
/// Will be stored and returned in [SkProductResponseWrapper.invalidProductIdentifiers]. Duplicate values in `productIdentifiers` will be omitted.
/// The `productIdentifiers` should contain legitimate product identifiers that you declared for the products in the iTunes Connect. Invalid identifiers
/// will be stored and returned in [SkProductResponseWrapper.invalidProductIdentifiers]. Duplicate values in `productIdentifiers` will be omitted.
/// If `productIdentifiers` is null, an `storekit_invalid_argument` error will be returned. If `productIdentifiers` is empty, a [SkProductResponseWrapper]
/// will still be returned with [SkProductResponseWrapper.products] being null.
///
Expand Down
Loading