Skip to content

Commit

Permalink
Merge 9bba544 into 55a3f87
Browse files Browse the repository at this point in the history
  • Loading branch information
mk-dev-1 committed Oct 14, 2020
2 parents 55a3f87 + 9bba544 commit efcf4fa
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 66 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,10 @@
## 3.0.0
+ Upgrade android billing client to `2.1.0` from `3.0.0`.
+ Removed `deveoperId` and `accountId` when requesting `purchase` or `subscription` in `android`.
+ Added `obfuscatedAccountIdAndroid` and `obfuscatedProfileIdAndroid` when requesting `purchase` or `subscription` in `android`.
+ Removed `developerPayload` in `android`.
+ Added `purchaseTokenAndroid` as an optional parameter to `requestPurchase` and `requestSubscription`.

## 2.3.1
Republishing since sourcode seems not merged correctly.

Expand Down
13 changes: 6 additions & 7 deletions README.md
Expand Up @@ -45,12 +45,12 @@ For help on editing plugin code, view the [documentation](https://flutter.io/dev
| getPurchaseHistory | | `List<IAPItem>` | Gets an invetory of purchases made by the user regardless of consumption status (where possible) |
| getAvailablePurchases | | `List<PurchasedItem>` | (aka restore purchase) Get all purchases made by the user (either non-consumable, or haven't been consumed yet)
| getAppStoreInitiatedProducts | | `List<IAPItem>` | If the user has initiated a purchase directly on the App Store, the products that the user is attempting to purchase will be returned here. (iOS only) Note: On iOS versions earlier than 11.0 this method will always return an empty list, as the functionality was introduced in v11.0. [See Apple Docs for more info](https://developer.apple.com/documentation/storekit/skpaymenttransactionobserver/2877502-paymentqueue) Always returns an empty list on Android.
| requestSubscription | `String` sku, `String` oldSkuAndroid?, `int` prorationModeAndroid?, `String` developerIdAndroid, `String` accountIdAndroid | Null | Create (request) a subscription to a sku. For upgrading/downgrading subscription on Android pass second parameter with current subscription ID, on iOS this is handled automatically by store. `purchaseUpdatedListener` will receive the result. |
| requestPurchase | `String` sku, `String` developerIdAndroid, `String` accoundIdAndroid | Null | Request a purchase. `purchaseUpdatedListener` will receive the result. |
| finishTransactionIOS | `String` purchaseToken | `PurchaseResult` | Send finishTransaction call to Apple IAP server. Call this function after receipt validation process |
| acknowledgePurchaseAndroid | `String` purchaseToken, `String` developerPayload? | `PurchaseResult` | Acknowledge a product (on Android) for `non-consumable` and `subscription` purchase. No-op on iOS. |
| consumePurchaseAndroid | `String` purchaseToken, `String` developerPayload? | `PurchaseResult` | Consume a product (on Android) for `consumable` purchase. No-op on iOS. |
| finishTransaction | `String` purchaseToken, `String` developerPayloadAndroid?, `bool` isConsumable? } | `PurchaseResult` | Send finishTransaction call that abstracts all `acknowledgePurchaseAndroid`, `finishTransactionIOS`, `consumePurchaseAndroid` methods. |
| requestSubscription | `String` sku, `String` oldSkuAndroid?, `int` prorationModeAndroid?, `String` obfuscatedAccountIdAndroid?, `String` obfuscatedProfileIdAndroid?, `String` purchaseTokenAndroid? | Null | Create (request) a subscription to a sku. For upgrading/downgrading subscription on Android pass second parameter with current subscription ID, on iOS this is handled automatically by store. `purchaseUpdatedListener` will receive the result. |
| requestPurchase | `String` sku, `String` obfuscatedAccountIdAndroid?, `String` obfuscatedProfileIdAndroid?, `String` purchaseToken? | Null | Request a purchase. `purchaseUpdatedListener` will receive the result. |
| finishTransactionIOS | `String` purchaseTokenAndroid | `PurchaseResult` | Send finishTransaction call to Apple IAP server. Call this function after receipt validation process |
| acknowledgePurchaseAndroid | `String` purchaseToken | `PurchaseResult` | Acknowledge a product (on Android) for `non-consumable` and `subscription` purchase. No-op on iOS. |
| consumePurchaseAndroid | `String` purchaseToken | `PurchaseResult` | Consume a product (on Android) for `consumable` purchase. No-op on iOS. |
| finishTransaction | `String` purchaseToken, `bool` isConsumable? } | `PurchaseResult` | Send finishTransaction call that abstracts all `acknowledgePurchaseAndroid`, `finishTransactionIOS`, `consumePurchaseAndroid` methods. |
| endConnection | | `String` | End billing connection. |
| consumeAllItems | | `String` | Manually consume all items in android. Do NOT call if you have any non-consumables (one time purchase items). No-op on iOS. |
| validateReceiptIos | `Map<String,String>` receiptBody, `bool` isTest | `http.Response` | Validate receipt for ios. |
Expand Down Expand Up @@ -106,7 +106,6 @@ Purchase flow in `flutter_inapp_purchase@2.0.0+
final bool autoRenewingAndroid;
final bool isAcknowledgedAndroid;
final int purchaseStateAndroid;
final String developerPayloadAndroid;
final String originalJsonAndroid;
// iOS only
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Expand Up @@ -34,7 +34,7 @@ android {
}

dependencies {
implementation 'com.android.billingclient:billing:2.1.0'
implementation 'com.android.billingclient:billing:3.0.0'
implementation files('jars/in-app-purchasing-2.0.76.jar')
}

Expand Up @@ -99,8 +99,8 @@ public void onMethodCall(final MethodCall call, final Result result) {
result.success("[]");
} else if (call.method.equals("buyItemByType")) {
final String type = call.argument("type");
final String accountId = call.argument("accountId");
final String developerId = call.argument("developerId");
final String obfuscatedAccountId = call.argument("obfuscatedAccountId");
final String obfuscatedProfileId = call.argument("obfuscatedProfileId");
final String sku = call.argument("sku");
final String oldSku = call.argument("oldSku");
final int prorationMode = call.argument("prorationMode");
Expand Down
Expand Up @@ -148,7 +148,6 @@ else if (call.method.equals("consumeAllItems")) {
for (Purchase purchase : purchases) {
final ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.setDeveloperPayload(purchase.getDeveloperPayload())
.build();

final ConsumeResponseListener listener = new ConsumeResponseListener() {
Expand Down Expand Up @@ -267,7 +266,6 @@ else if (call.method.equals("getAvailableItemsByType")) {
item.put("transactionReceipt", purchase.getOriginalJson());
item.put("orderId", purchase.getOrderId());
item.put("purchaseToken", purchase.getPurchaseToken());
item.put("developerPayloadAndroid", purchase.getDeveloperPayload());
item.put("signatureAndroid", purchase.getSignature());
item.put("purchaseStateAndroid", purchase.getPurchaseState());

Expand Down Expand Up @@ -314,7 +312,6 @@ public void onPurchaseHistoryResponse(BillingResult billingResult, List<Purchase
item.put("purchaseToken", purchase.getPurchaseToken());
item.put("dataAndroid", purchase.getOriginalJson());
item.put("signatureAndroid", purchase.getSignature());
item.put("developerPayload", purchase.getDeveloperPayload());
items.put(item);
}
result.success(items.toString());
Expand All @@ -327,7 +324,7 @@ public void onPurchaseHistoryResponse(BillingResult billingResult, List<Purchase

/*
* buyItemByType
* arguments: type, accountId, developerId, sku, oldSku, prorationMode
* arguments: type, obfuscatedAccountId, obfuscatedProfileId, sku, oldSku, prorationMode, purchaseToken
*/
else if (call.method.equals("buyItemByType")) {
if (billingClient == null || !billingClient.isReady()) {
Expand All @@ -336,32 +333,33 @@ else if (call.method.equals("buyItemByType")) {
}

final String type = call.argument("type");
final String accountId = call.argument("accountId");
final String developerId = call.argument("developerId");
final String obfuscatedAccountId = call.argument("obfuscatedAccountId");
final String obfuscatedProfileId = call.argument("obfuscatedProfileId");
final String sku = call.argument("sku");
final String oldSku = call.argument("oldSku");
final int prorationMode = call.argument("prorationMode");
final String purchaseToken = call.argument("purchaseToken");

BillingFlowParams.Builder builder = BillingFlowParams.newBuilder();

if (type.equals(BillingClient.SkuType.SUBS) && oldSku != null && !oldSku.isEmpty()) {
// Subscription upgrade/downgrade
builder.setOldSku(oldSku);
builder.setOldSku(oldSku, purchaseToken);
}

if (type.equals(BillingClient.SkuType.SUBS) && oldSku != null && !oldSku.isEmpty()) {
// Subscription upgrade/downgrade
if (prorationMode != -1) {
builder.setOldSku(oldSku);
builder.setOldSku(oldSku, purchaseToken);
if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE) {
builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_AND_CHARGE_PRORATED_PRICE);
} else if (prorationMode == BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION) {
builder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITHOUT_PRORATION);
} else {
builder.setOldSku(oldSku);
builder.setOldSku(oldSku, purchaseToken);
}
} else {
builder.setOldSku(oldSku);
builder.setOldSku(oldSku, purchaseToken);
}
}

Expand All @@ -382,11 +380,11 @@ else if (call.method.equals("buyItemByType")) {
return;
}

if (accountId != null) {
builder.setAccountId(accountId);
if (obfuscatedAccountId != null) {
builder.setObfuscatedAccountId(obfuscatedAccountId);
}
if (developerId != null) {
builder.setDeveloperId(developerId);
if (obfuscatedProfileId != null) {
builder.setObfuscatedProfileId(obfuscatedProfileId);
}

builder.setSkuDetails(selectedSku);
Expand All @@ -396,11 +394,10 @@ else if (call.method.equals("buyItemByType")) {

/*
* acknowledgePurchase (For non-consumable purchases)
* arguments: token, developerPayload
* arguments: token
*/
else if (call.method.equals("acknowledgePurchase")) {
final String token = call.argument("token");
final String developerPayload = call.argument("developerPayload");

if (billingClient == null || !billingClient.isReady()) {
result.error(call.method, "IAP not prepared. Check if Google Play service is available.", "");
Expand All @@ -410,7 +407,6 @@ else if (call.method.equals("acknowledgePurchase")) {
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(token)
.setDeveloperPayload(developerPayload)
.build();
billingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {
@Override
Expand All @@ -437,7 +433,7 @@ public void onAcknowledgePurchaseResponse(BillingResult billingResult) {

/*
* consumeProduct (For consumable purchases)
* arguments: token, developerPayload
* arguments: token
*/
else if (call.method.equals("consumeProduct")) {
if (billingClient == null || !billingClient.isReady()) {
Expand All @@ -446,11 +442,9 @@ else if (call.method.equals("consumeProduct")) {
}

final String token = call.argument("token");
final String developerPayload = call.argument("developerPayload");

final ConsumeParams params = ConsumeParams.newBuilder()
.setPurchaseToken(token)
.setDeveloperPayload(developerPayload)
.build();
billingClient.consumeAsync(params, new ConsumeResponseListener() {
@Override
Expand Down Expand Up @@ -515,7 +509,6 @@ public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purch
item.put("autoRenewingAndroid", purchase.isAutoRenewing());
item.put("isAcknowledgedAndroid", purchase.isAcknowledged());
item.put("purchaseStateAndroid", purchase.getPurchaseState());
item.put("developerPayloadAndroid", purchase.getDeveloperPayload());
item.put("originalJsonAndroid", purchase.getOriginalJson());


Expand Down
38 changes: 19 additions & 19 deletions lib/flutter_inapp_purchase.dart
@@ -1,13 +1,13 @@
import 'dart:async';
import 'dart:convert';
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';
import 'package:http/http.dart' as http;

import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';
import 'package:platform/platform.dart';

import 'utils.dart';
import 'modules.dart';
import 'utils.dart';

export 'modules.dart';

Expand Down Expand Up @@ -222,17 +222,19 @@ class FlutterInappPurchase {
///
/// Identical to [requestSubscription] on `iOS`.
Future requestPurchase(String sku, {
String developerIdAndroid,
String accountIdAndroid,
String obfuscatedAccountIdAndroid,
String obfuscatedProfileIdAndroid,
String purchaseTokenAndroid,
}) async {
if (_platform.isAndroid) {
return await _channel.invokeMethod('buyItemByType', <String, dynamic>{
'type': EnumUtil.getValueString(_TypeInApp.inapp),
'sku': sku,
'oldSku': null,
'prorationMode': -1,
'developerId': developerIdAndroid,
'accountId': accountIdAndroid,
'obfuscatedAccountId': obfuscatedAccountIdAndroid,
'obfuscatedProfileId': obfuscatedProfileIdAndroid,
'purchaseToken': purchaseTokenAndroid,
});
} else if (_platform.isIOS) {
return await _channel.invokeMethod(
Expand All @@ -254,8 +256,9 @@ class FlutterInappPurchase {
{
String oldSkuAndroid,
int prorationModeAndroid,
String developerIdAndroid,
String accountIdAndroid,
String obfuscatedAccountIdAndroid,
String obfuscatedProfileIdAndroid,
String purchaseTokenAndroid,
}) async {
if (_platform.isAndroid) {
return await _channel
Expand All @@ -264,8 +267,9 @@ class FlutterInappPurchase {
'sku': sku,
'oldSku': oldSkuAndroid,
'prorationMode': prorationModeAndroid ?? -1,
'developerId': developerIdAndroid,
'accountId': accountIdAndroid,
'obfuscatedAccountId': obfuscatedAccountIdAndroid,
'obfuscatedProfileId': obfuscatedProfileIdAndroid,
'purchaseToken': purchaseTokenAndroid,
});
} else if (_platform.isIOS) {
return await _channel.invokeMethod(
Expand Down Expand Up @@ -349,11 +353,10 @@ class FlutterInappPurchase {
/// Acknowledge a purchase on `Android`.
///
/// No effect on `iOS`, whose iap purchases are consumed at the time of purchase.
Future<String> acknowledgePurchaseAndroid(String token, { String developerPayload }) async {
Future<String> acknowledgePurchaseAndroid(String token) async {
if (_platform.isAndroid) {
String result = await _channel.invokeMethod('acknowledgePurchase', <String, dynamic>{
'token': token,
'developerPayload': developerPayload,
});

return result;
Expand All @@ -377,12 +380,11 @@ class FlutterInappPurchase {
/// errorData[0] = E_ALREADY_OWNED;
/// errorData[1] = "You already own this item.";
/// break;
Future<String> consumePurchaseAndroid(String token, { String developerPayload }) async {
Future<String> consumePurchaseAndroid(String token) async {
if (_platform.isAndroid) {
String result =
await _channel.invokeMethod('consumeProduct', <String, dynamic>{
'token': token,
'developerPayload': developerPayload,
});
return result;
} else if (_platform.isIOS) {
Expand Down Expand Up @@ -431,18 +433,16 @@ class FlutterInappPurchase {
///
/// Call this after finalizing server-side validation of the reciept.
Future<String> finishTransaction(PurchasedItem purchasedItem,
{ String developerPayloadAndroid = '', bool isConsumable = false }) async {
{ bool isConsumable = false }) async {
if (_platform.isAndroid) {
if (isConsumable) {
String result = await _channel.invokeMethod('consumeProduct', <String, dynamic>{
'token': purchasedItem.purchaseToken,
'developerPayload': developerPayloadAndroid,
});
return result;
} else {
String result = await _channel.invokeMethod('acknowledgePurchase', <String, dynamic>{
'token': purchasedItem.purchaseToken,
'developerPayload': developerPayloadAndroid,
});
return result;
}
Expand Down
7 changes: 2 additions & 5 deletions lib/modules.dart
Expand Up @@ -32,7 +32,7 @@ class IAPItem {

/// android only
final String subscriptionPeriodAndroid;
final String introductoryPriceCyclesAndroid;
final int introductoryPriceCyclesAndroid;
final String introductoryPricePeriodAndroid;
final String freeTrialPeriodAndroid;
final String signatureAndroid;
Expand Down Expand Up @@ -62,7 +62,7 @@ class IAPItem {
subscriptionPeriodUnitIOS = json['subscriptionPeriodUnitIOS'] as String,
subscriptionPeriodAndroid = json['subscriptionPeriodAndroid'] as String,
introductoryPriceCyclesAndroid =
json['introductoryPriceCyclesAndroid'] as String,
json['introductoryPriceCyclesAndroid'] as int,
introductoryPricePeriodAndroid =
json['introductoryPricePeriodAndroid'] as String,
freeTrialPeriodAndroid = json['freeTrialPeriodAndroid'] as String,
Expand Down Expand Up @@ -214,7 +214,6 @@ class PurchasedItem {
final bool autoRenewingAndroid;
final bool isAcknowledgedAndroid;
final int purchaseStateAndroid;
final String developerPayloadAndroid;
final String originalJsonAndroid;

// iOS only
Expand All @@ -236,7 +235,6 @@ class PurchasedItem {
isAcknowledgedAndroid = json['isAcknowledgedAndroid'] as bool,
autoRenewingAndroid = json['autoRenewingAndroid'] as bool,
purchaseStateAndroid = json['purchaseStateAndroid'] as int,
developerPayloadAndroid = json['developerPayloadAndroid'] as String,
originalJsonAndroid = json['originalJsonAndroid'] as String,

originalTransactionDateIOS =
Expand All @@ -261,7 +259,6 @@ class PurchasedItem {
'isAcknowledgedAndroid: $isAcknowledgedAndroid, '
'autoRenewingAndroid: $autoRenewingAndroid, '
'purchaseStateAndroid: $purchaseStateAndroid, '
'developerPayloadAndroid: $developerPayloadAndroid, '
'originalJsonAndroid: $originalJsonAndroid, '
/// ios specific
'originalTransactionDateIOS: ${originalTransactionDateIOS?.toIso8601String()}, '
Expand Down

0 comments on commit efcf4fa

Please sign in to comment.