Line data Source code
1 : // Copyright 2023 The terCAD team. All rights reserved.
2 : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.
3 :
4 : import 'dart:async';
5 :
6 : import 'package:flutter/foundation.dart';
7 : import 'package:in_app_purchase/in_app_purchase.dart';
8 :
9 : class PurchaseController {
10 : static const pCoffee = 'fin_consumable_coffee';
11 : static const pDinner = 'fin_consumable_dinner';
12 : static const pInitial = 'fin_consumable_init';
13 : // static const pSubApple = 'fin_subscription_tiny'; Restricted without extended functionality
14 : // static const pSubGoogle = 'fin-subscription-tiny';
15 :
16 0 : static InAppPurchase iap = InAppPurchase.instance;
17 :
18 0 : static bool get supportsPurchases =>
19 0 : defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.macOS;
20 :
21 : late StreamSubscription<List<PurchaseDetails>> _subscription;
22 : Function? callback;
23 :
24 0 : PurchaseController([this.callback]) {
25 0 : final purchaseUpdated = iap.purchaseStream;
26 0 : _subscription = purchaseUpdated.listen(
27 0 : _onUpdate,
28 0 : onDone: dispose,
29 0 : onError: _onError,
30 : );
31 : }
32 :
33 0 : dispose() {
34 0 : _subscription.cancel();
35 : }
36 :
37 0 : void _onError(dynamic error) {
38 : // ... trace error
39 : }
40 :
41 0 : Future<void> _onUpdate(List<PurchaseDetails> purchaseDetailsList) async {
42 0 : for (var purchaseDetails in purchaseDetailsList) {
43 0 : if (purchaseDetails.pendingCompletePurchase) {
44 0 : await iap.completePurchase(purchaseDetails);
45 : }
46 : }
47 0 : if (callback != null) {
48 0 : callback!(purchaseDetailsList);
49 : }
50 : }
51 :
52 0 : Future<List<ProductDetails>> load() async {
53 0 : if (!supportsPurchases) {
54 0 : return [];
55 : }
56 :
57 0 : final available = await iap.isAvailable();
58 : if (!available) {
59 0 : return [];
60 : }
61 0 : final response = await iap.queryProductDetails(<String>{
62 0 : pCoffee,
63 0 : pDinner,
64 0 : pInitial,
65 : // pSubApple,
66 : // pSubGoogle,
67 : });
68 0 : iap.restorePurchases();
69 0 : return response.productDetails;
70 : }
71 :
72 0 : static Future<bool> buy(ProductDetails product) async {
73 0 : if (!supportsPurchases) {
74 : return false;
75 : }
76 :
77 0 : final purchaseParam = PurchaseParam(productDetails: product);
78 0 : if (product.id.contains('subscription')) {
79 0 : await iap.buyNonConsumable(purchaseParam: purchaseParam);
80 : } else {
81 0 : await iap.buyConsumable(purchaseParam: purchaseParam);
82 : }
83 :
84 : return true;
85 : }
86 : }
|