Apple IAP
This commit is contained in:
parent
1ab508420d
commit
b69f7f6960
|
|
@ -7,6 +7,7 @@ import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_redux/flutter_redux.dart';
|
import 'package:flutter_redux/flutter_redux.dart';
|
||||||
|
import 'package:flutter_styled_toast/flutter_styled_toast.dart';
|
||||||
import 'package:in_app_purchase/in_app_purchase.dart';
|
import 'package:in_app_purchase/in_app_purchase.dart';
|
||||||
import 'package:in_app_purchase_android/billing_client_wrappers.dart';
|
import 'package:in_app_purchase_android/billing_client_wrappers.dart';
|
||||||
import 'package:in_app_purchase_android/in_app_purchase_android.dart';
|
import 'package:in_app_purchase_android/in_app_purchase_android.dart';
|
||||||
|
|
@ -14,8 +15,8 @@ import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';
|
||||||
import 'package:in_app_purchase_storekit/store_kit_wrappers.dart';
|
import 'package:in_app_purchase_storekit/store_kit_wrappers.dart';
|
||||||
import 'package:invoiceninja_flutter/constants.dart';
|
import 'package:invoiceninja_flutter/constants.dart';
|
||||||
import 'package:invoiceninja_flutter/data/web_client.dart';
|
import 'package:invoiceninja_flutter/data/web_client.dart';
|
||||||
import 'package:invoiceninja_flutter/main_app.dart';
|
|
||||||
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
|
||||||
|
import 'package:invoiceninja_flutter/utils/dialogs.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
|
@ -308,16 +309,6 @@ class _UpgradeDialogState extends State<UpgradeDialog> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) {
|
|
||||||
// IMPORTANT!! Always verify a purchase before delivering the product.
|
|
||||||
// For the purpose of an example, we directly return true.
|
|
||||||
return Future<bool>.value(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleInvalidPurchase(PurchaseDetails purchaseDetails) {
|
|
||||||
// handle invalid purchase here if _verifyPurchase` failed.
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _listenToPurchaseUpdated(
|
Future<void> _listenToPurchaseUpdated(
|
||||||
List<PurchaseDetails> purchaseDetailsList) async {
|
List<PurchaseDetails> purchaseDetailsList) async {
|
||||||
for (final PurchaseDetails purchaseDetails in purchaseDetailsList) {
|
for (final PurchaseDetails purchaseDetails in purchaseDetailsList) {
|
||||||
|
|
@ -328,13 +319,7 @@ class _UpgradeDialogState extends State<UpgradeDialog> {
|
||||||
handleError(purchaseDetails.error);
|
handleError(purchaseDetails.error);
|
||||||
} else if (purchaseDetails.status == PurchaseStatus.purchased ||
|
} else if (purchaseDetails.status == PurchaseStatus.purchased ||
|
||||||
purchaseDetails.status == PurchaseStatus.restored) {
|
purchaseDetails.status == PurchaseStatus.restored) {
|
||||||
final bool valid = await _verifyPurchase(purchaseDetails);
|
deliverProduct(purchaseDetails);
|
||||||
if (valid) {
|
|
||||||
deliverProduct(purchaseDetails);
|
|
||||||
} else {
|
|
||||||
_handleInvalidPurchase(purchaseDetails);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (purchaseDetails.pendingCompletePurchase) {
|
if (purchaseDetails.pendingCompletePurchase) {
|
||||||
await _inAppPurchase.completePurchase(purchaseDetails);
|
await _inAppPurchase.completePurchase(purchaseDetails);
|
||||||
|
|
@ -345,6 +330,7 @@ class _UpgradeDialogState extends State<UpgradeDialog> {
|
||||||
|
|
||||||
Future<void> confirmPriceChange(BuildContext context) async {
|
Future<void> confirmPriceChange(BuildContext context) async {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
|
final localization = AppLocalization.of(context);
|
||||||
final InAppPurchaseAndroidPlatformAddition androidAddition =
|
final InAppPurchaseAndroidPlatformAddition androidAddition =
|
||||||
_inAppPurchase
|
_inAppPurchase
|
||||||
.getPlatformAddition<InAppPurchaseAndroidPlatformAddition>();
|
.getPlatformAddition<InAppPurchaseAndroidPlatformAddition>();
|
||||||
|
|
@ -352,18 +338,15 @@ class _UpgradeDialogState extends State<UpgradeDialog> {
|
||||||
await androidAddition.launchPriceChangeConfirmationFlow(
|
await androidAddition.launchPriceChangeConfirmationFlow(
|
||||||
sku: 'purchaseId',
|
sku: 'purchaseId',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (priceChangeConfirmationResult.responseCode == BillingResponse.ok) {
|
if (priceChangeConfirmationResult.responseCode == BillingResponse.ok) {
|
||||||
ScaffoldMessenger.of(navigatorKey.currentContext)
|
showToast(localization.priceChangeAccepted);
|
||||||
.showSnackBar(const SnackBar(
|
|
||||||
content: Text('Price change accepted'),
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(navigatorKey.currentContext).showSnackBar(SnackBar(
|
showErrorDialog(
|
||||||
content: Text(
|
context: context,
|
||||||
priceChangeConfirmationResult.debugMessage ??
|
message: priceChangeConfirmationResult.debugMessage ??
|
||||||
'Price change failed with code ${priceChangeConfirmationResult.responseCode}',
|
localization.priceChangeFailed +
|
||||||
),
|
' ${priceChangeConfirmationResult.responseCode}');
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
// STARTER: lang key - do not remove comment
|
// STARTER: lang key - do not remove comment
|
||||||
|
'price_change_accepted': 'Price change accepted',
|
||||||
|
'price_change_failed': 'Price change failed with code',
|
||||||
'restore_purchases': 'Restore Purchases',
|
'restore_purchases': 'Restore Purchases',
|
||||||
'activate': 'Activate',
|
'activate': 'Activate',
|
||||||
'connect_apple': 'Connect Apple',
|
'connect_apple': 'Connect Apple',
|
||||||
|
|
@ -76192,12 +76194,17 @@ mixin LocalizationsProvider on LocaleCodeAware {
|
||||||
_localizedValues[localeCode]['activate'] ??
|
_localizedValues[localeCode]['activate'] ??
|
||||||
_localizedValues['en']['activate'];
|
_localizedValues['en']['activate'];
|
||||||
|
|
||||||
|
|
||||||
String get restorePurchases =>
|
String get restorePurchases =>
|
||||||
_localizedValues[localeCode]['restore_purchases'] ??
|
_localizedValues[localeCode]['restore_purchases'] ??
|
||||||
_localizedValues['en']['restore_purchases'];
|
_localizedValues['en']['restore_purchases'];
|
||||||
|
|
||||||
|
String get priceChangeAccepted =>
|
||||||
|
_localizedValues[localeCode]['price_change_accepted'] ??
|
||||||
|
_localizedValues['en']['price_change_accepted'];
|
||||||
|
|
||||||
|
String get priceChangeFailed =>
|
||||||
|
_localizedValues[localeCode]['price_change_failed'] ??
|
||||||
|
_localizedValues['en']['price_change_failed'];
|
||||||
|
|
||||||
// STARTER: lang field - do not remove comment
|
// STARTER: lang field - do not remove comment
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue