Skip to content

Commit

Permalink
Obfuscated account id (#299)
Browse files Browse the repository at this point in the history
* ObfuscatedAccountId

* HF

* Version bump (5.0.2)

* Changelog update
  • Loading branch information
bohdan1krokhmaliuk committed Jul 21, 2021
1 parent 3a3d5a5 commit 09ef387
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 56 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 5.0.2
+ Replaced obfuscatedAccountIdAndroid with obfuscatedAccountId in request purchase method [#299](https://github.com/dooboolab/flutter_inapp_purchase/pull/299)

## 5.0.1
+ Add AndroidProrationMode values [#273](https://github.com/dooboolab/flutter_inapp_purchase/pull/273)

Expand Down
2 changes: 2 additions & 0 deletions ios/Classes/FlutterInappPurchasePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
}
} else if ([@"buyProduct" isEqualToString:call.method]) {
NSString* identifier = (NSString*)call.arguments[@"sku"];
NSString* usernameHash = (NSString*)call.arguments[@"forUser"];
SKProduct *product;

for (SKProduct *p in validProducts) {
Expand All @@ -80,6 +81,7 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
}
if (product) {
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.applicationUsername = usernameHash;
[[SKPaymentQueue defaultQueue] addPayment:payment];
} else {
NSDictionary *err = [NSDictionary dictionaryWithObjectsAndKeys:
Expand Down
28 changes: 9 additions & 19 deletions lib/flutter_inapp_purchase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ class FlutterInappPurchase {
///
/// `iOS` also returns subscriptions.
Future<List<IAPItem>> getProducts(List<String> skus) async {
if (skus == null || skus.contains(null)) return [];
skus = skus.toList();
if (_platform.isAndroid) {
dynamic result = await _channel.invokeMethod(
Expand Down Expand Up @@ -128,7 +127,6 @@ class FlutterInappPurchase {
///
/// `iOS` also returns non-subscription products.
Future<List<IAPItem>> getSubscriptions(List<String> skus) async {
if (skus == null || skus.contains(null)) return [];
skus = skus.toList();
if (_platform.isAndroid) {
dynamic result = await _channel.invokeMethod(
Expand Down Expand Up @@ -219,28 +217,29 @@ class FlutterInappPurchase {

/// Request a purchase on `Android` or `iOS`.
/// Result will be received in `purchaseUpdated` listener or `purchaseError` listener.
///
///
/// Check [AndroidProrationMode] for valid proration values
/// Identical to [requestSubscription] on `iOS`.
Future requestPurchase(
String sku, {
String? obfuscatedAccountIdAndroid,
String? obfuscatedProfileIdAndroid,
String? obfuscatedAccountId,
String? purchaseTokenAndroid,
String? obfuscatedProfileIdAndroid,
}) async {
if (_platform.isAndroid) {
return await _channel.invokeMethod('buyItemByType', <String, dynamic>{
'type': EnumUtil.getValueString(_TypeInApp.inapp),
'sku': sku,
'oldSku': null,
'prorationMode': -1,
'obfuscatedAccountId': obfuscatedAccountIdAndroid,
'obfuscatedAccountId': obfuscatedAccountId,
'obfuscatedProfileId': obfuscatedProfileIdAndroid,
'purchaseToken': purchaseTokenAndroid,
});
} else if (_platform.isIOS) {
return await _channel.invokeMethod('buyProduct', <String, dynamic>{
'sku': sku,
'forUser': obfuscatedAccountId,
});
}
throw PlatformException(
Expand All @@ -251,7 +250,7 @@ class FlutterInappPurchase {
/// Result will be received in `purchaseUpdated` listener or `purchaseError` listener.
///
/// **NOTICE** second parameter is required on `Android`.
///
///
/// Check [AndroidProrationMode] for valid proration values
/// Identical to [requestPurchase] on `iOS`.
Future requestSubscription(
Expand Down Expand Up @@ -506,7 +505,6 @@ class FlutterInappPurchase {
Duration duration: const Duration(days: 30),
Duration grace: const Duration(days: 3),
}) async {
assert(sku != null);
if (_platform.isIOS) {
var history =
await (getPurchaseHistory() as FutureOr<List<PurchasedItem>>);
Expand Down Expand Up @@ -548,9 +546,6 @@ class FlutterInappPurchase {
required Map<String, String> receiptBody,
bool isTest = true,
}) async {
assert(receiptBody != null);
assert(isTest != null);

final String url = isTest
? 'https://sandbox.itunes.apple.com/verifyReceipt'
: 'https://buy.itunes.apple.com/verifyReceipt';
Expand Down Expand Up @@ -587,11 +582,6 @@ class FlutterInappPurchase {
required String accessToken,
bool isSubscription = false,
}) async {
assert(packageName != null);
assert(productId != null);
assert(productToken != null);
assert(accessToken != null);

final String type = isSubscription ? 'subscriptions' : 'products';
final String url =
'https://www.googleapis.com/androidpublisher/v3/applications/$packageName/purchases/$type/$productId/tokens/$productToken?access_token=$accessToken';
Expand Down Expand Up @@ -642,7 +632,7 @@ class FlutterInappPurchase {
throw new ArgumentError('Unknown method ${call.method}');
}
return Future.value(null);
} as Future<dynamic> Function(MethodCall)?);
});
}

Future _removePurchaseListener() async {
Expand All @@ -663,7 +653,7 @@ class FlutterInappPurchase {

/// A list of valid values for ProrationMode parameter
/// https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.ProrationMode
class AndroidProrationMode{
class AndroidProrationMode {
/// Replacement takes effect when the old plan expires, and the new price will be charged at the same time.
/// https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.ProrationMode#DEFERRED
static const int DEFERRED = 4;
Expand All @@ -682,4 +672,4 @@ class AndroidProrationMode{

/// https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.ProrationMode#unknown_subscription_upgrade_downgrade_policy
static const int UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY = 0;
}
}
63 changes: 33 additions & 30 deletions lib/modules.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,14 @@ class IAPItem {
json['introductoryPriceNumberOfPeriodsIOS'] as String?,
introductoryPriceSubscriptionPeriodIOS =
json['introductoryPriceSubscriptionPeriodIOS'] as String?,
introductoryPriceNumberIOS = json['introductoryPriceNumberIOS'] as String?,
introductoryPriceNumberIOS =
json['introductoryPriceNumberIOS'] as String?,
subscriptionPeriodNumberIOS =
json['subscriptionPeriodNumberIOS'] as String?,
subscriptionPeriodUnitIOS = json['subscriptionPeriodUnitIOS'] as String?,
subscriptionPeriodAndroid = json['subscriptionPeriodAndroid'] as String?,
subscriptionPeriodUnitIOS =
json['subscriptionPeriodUnitIOS'] as String?,
subscriptionPeriodAndroid =
json['subscriptionPeriodAndroid'] as String?,
introductoryPriceCyclesAndroid =
json['introductoryPriceCyclesAndroid'] as int?,
introductoryPricePeriodAndroid =
Expand Down Expand Up @@ -93,13 +96,18 @@ class IAPItem {

data['subscriptionPeriodNumberIOS'] = this.subscriptionPeriodNumberIOS;
data['subscriptionPeriodUnitIOS'] = this.subscriptionPeriodUnitIOS;
data['introductoryPricePaymentModeIOS'] = this.introductoryPricePaymentModeIOS;
data['introductoryPriceNumberOfPeriodsIOS'] = this.introductoryPriceNumberOfPeriodsIOS;
data['introductoryPriceSubscriptionPeriodIOS'] = this.introductoryPriceSubscriptionPeriodIOS;
data['introductoryPricePaymentModeIOS'] =
this.introductoryPricePaymentModeIOS;
data['introductoryPriceNumberOfPeriodsIOS'] =
this.introductoryPriceNumberOfPeriodsIOS;
data['introductoryPriceSubscriptionPeriodIOS'] =
this.introductoryPriceSubscriptionPeriodIOS;

data['subscriptionPeriodAndroid'] = this.subscriptionPeriodAndroid;
data['introductoryPriceCyclesAndroid'] = this.introductoryPriceCyclesAndroid;
data['introductoryPricePeriodAndroid'] = this.introductoryPricePeriodAndroid;
data['introductoryPriceCyclesAndroid'] =
this.introductoryPriceCyclesAndroid;
data['introductoryPricePeriodAndroid'] =
this.introductoryPricePeriodAndroid;
data['freeTrialPeriodAndroid'] = this.freeTrialPeriodAndroid;
data['signatureAndroid'] = this.signatureAndroid;

Expand Down Expand Up @@ -133,8 +141,7 @@ class IAPItem {
'iconUrl: $iconUrl, '
'originalJson: $originalJson, '
'originalPrice: $originalPrice, '
'discounts: $discountsIOS, '
;
'discounts: $discountsIOS, ';
}

static List<DiscountIOS>? _extractDiscountIOS(dynamic json) {
Expand All @@ -144,12 +151,12 @@ class IAPItem {
if (list != null) {
discounts = list
.map<DiscountIOS>(
(dynamic discount) => DiscountIOS.fromJSON(discount as Map<String, dynamic>),
)
(dynamic discount) =>
DiscountIOS.fromJSON(discount as Map<String, dynamic>),
)
.toList();
}


return discounts;
}
}
Expand Down Expand Up @@ -194,8 +201,7 @@ class DiscountIOS {
'price: $price, '
'localizedPrice: $localizedPrice, '
'paymentMode: $paymentMode, '
'subscriptionPeriod: $subscriptionPeriod, '
;
'subscriptionPeriod: $subscriptionPeriod, ';
}
}

Expand Down Expand Up @@ -229,15 +235,13 @@ class PurchasedItem {
transactionReceipt = json['transactionReceipt'] as String?,
purchaseToken = json['purchaseToken'] as String?,
orderId = json['orderId'] as String?,

dataAndroid = json['dataAndroid'] as String?,
signatureAndroid = json['signatureAndroid'] as String?,
isAcknowledgedAndroid = json['isAcknowledgedAndroid'] as bool?,
autoRenewingAndroid = json['autoRenewingAndroid'] as bool?,
purchaseStateAndroid =
_decodePurchaseStateAndroid(json['purchaseStateAndroid'] as int?),
originalJsonAndroid = json['originalJsonAndroid'] as String?,

originalTransactionDateIOS =
_extractDate(json['originalTransactionDateIOS']),
originalTransactionIdentifierIOS =
Expand All @@ -254,13 +258,15 @@ class PurchasedItem {
'transactionReceipt: $transactionReceipt, '
'purchaseToken: $purchaseToken, '
'orderId: $orderId, '

/// android specific
'dataAndroid: $dataAndroid, '
'signatureAndroid: $signatureAndroid, '
'isAcknowledgedAndroid: $isAcknowledgedAndroid, '
'autoRenewingAndroid: $autoRenewingAndroid, '
'purchaseStateAndroid: $purchaseStateAndroid, '
'originalJsonAndroid: $originalJsonAndroid, '

/// ios specific
'originalTransactionDateIOS: ${originalTransactionDateIOS?.toIso8601String()}, '
'originalTransactionIdentifierIOS: $originalTransactionIdentifierIOS, '
Expand All @@ -286,7 +292,7 @@ class PurchaseResult {
this.responseCode,
this.debugMessage,
this.code,
this.message
this.message,
});

PurchaseResult.fromJSON(Map<String, dynamic> json)
Expand All @@ -296,23 +302,21 @@ class PurchaseResult {
message = json['message'] as String?;

Map<String, dynamic> toJson() => {
"responseCode": responseCode ?? 0,
"debugMessage": debugMessage ?? '',
"code": code ?? '',
"message": message ?? '',
};
"responseCode": responseCode ?? 0,
"debugMessage": debugMessage ?? '',
"code": code ?? '',
"message": message ?? '',
};

@override
String toString() {
return 'responseCode: $responseCode, '
'debugMessage: $debugMessage, '
'code: $code, '
'message: $message'
;
'message: $message';
}
}


class ConnectionResult {
final bool? connected;

Expand All @@ -324,13 +328,12 @@ class ConnectionResult {
: connected = json['connected'] as bool?;

Map<String, dynamic> toJson() => {
"connected": connected ?? false,
};
"connected": connected ?? false,
};

@override
String toString() {
return 'connected: $connected'
;
return 'connected: $connected';
}
}

Expand Down
7 changes: 2 additions & 5 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: flutter_inapp_purchase
description: In App Purchase plugin for flutter. This project has been forked by react-native-iap and we are willing to share same experience with that on react-native.
version: 5.0.1
version: 5.0.2
homepage: https://github.com/dooboolab/flutter_inapp_purchase/blob/master/pubspec.yaml
environment:
sdk: '>=2.12.0 <3.0.0'
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0 <3.0.0"

dependencies:
Expand All @@ -20,7 +20,6 @@ dev_dependencies:
flutter_test:
sdk: flutter


# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec

Expand All @@ -33,7 +32,6 @@ flutter:
pluginClass: FlutterInappPurchasePlugin
ios:
pluginClass: FlutterInappPurchasePlugin

# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
Expand All @@ -44,7 +42,6 @@ flutter:
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.

# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
Expand Down
14 changes: 12 additions & 2 deletions test/flutter_inapp_purchase_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,7 @@ void main() {
};

final String sku = "testsku";
final String forUser = "testObfuscatedUser";

setUp(() {
FlutterInappPurchase(FlutterInappPurchase.private(
Expand All @@ -927,12 +928,16 @@ void main() {
});

test('invokes correct method', () async {
await FlutterInappPurchase.instance.requestPurchase(sku);
await FlutterInappPurchase.instance.requestPurchase(
sku,
obfuscatedAccountId: forUser,
);
expect(log, <Matcher>[
isMethodCall(
'buyProduct',
arguments: <String, dynamic>{
'sku': sku,
'forUser': forUser,
},
),
]);
Expand Down Expand Up @@ -1063,6 +1068,7 @@ void main() {
group('for iOS', () {
final List<MethodCall> log = <MethodCall>[];
final String sku = "testsku";
final String forUser = "testObfuscatedUser";
final dynamic result = {
"transactionDate": "1552824902000",
"transactionId": "testTransactionId",
Expand Down Expand Up @@ -1093,12 +1099,16 @@ void main() {
});

test('invokes correct method', () async {
await FlutterInappPurchase.instance.requestPurchase(sku);
await FlutterInappPurchase.instance.requestPurchase(
sku,
obfuscatedAccountId: forUser,
);
expect(log, <Matcher>[
isMethodCall(
'buyProduct',
arguments: <String, dynamic>{
'sku': sku,
'forUser': forUser,
},
),
]);
Expand Down

0 comments on commit 09ef387

Please sign in to comment.