Chad

替换内购插件,重新实现内购服务

1 +import 'package:flutter/material.dart';
2 +import 'package:flutter_easyloading/flutter_easyloading.dart';
3 +
4 +abstract class BaseState<T extends StatefulWidget> extends State<T> {
5 + bool _isFirstBuild = true;
6 +
7 + @override
8 + Widget build(BuildContext context) {
9 + if (_isFirstBuild) {
10 + onFirstBuildBody(context);
11 + _isFirstBuild = false;
12 + }
13 + return buildBody(context);
14 + }
15 +
16 + Widget buildBody(BuildContext context);
17 +
18 + void onFirstBuildBody(BuildContext context){
19 +
20 + }
21 +
22 +
23 + showLoading({String text = 'Loading...'}) {
24 + EasyLoading.show(status: text);
25 + }
26 +
27 + hideLoading() {
28 + EasyLoading.dismiss();
29 + }
30 +}
...@@ -8,4 +8,115 @@ extension WidgetExt on Widget { ...@@ -8,4 +8,115 @@ extension WidgetExt on Widget {
8 SafeArea safe() { 8 SafeArea safe() {
9 return SafeArea(child: this); 9 return SafeArea(child: this);
10 } 10 }
11 +
12 + ClipRRect round({double? radius, BorderRadius? borderRadius}) {
13 + return ClipRRect(
14 + borderRadius: borderRadius ?? BorderRadius.all(Radius.circular(radius ?? 5)),
15 + child: this,
16 + );
17 + }
18 +
19 + Container height(double height, {Alignment? alignment}) {
20 + return Container(height: height, alignment: alignment, child: this);
21 + }
22 +
23 + Container height48({Alignment? alignment}) {
24 + return Container(height: 48, alignment: alignment, child: this);
25 + }
26 +
27 + Container paddingALL(double padding) {
28 + return Container(child: this, padding: EdgeInsets.all(padding));
29 + }
30 +
31 + Container paddingTopBottom(double padding) {
32 + return Container(child: this, padding: EdgeInsets.only(bottom: padding, top: padding));
33 + }
34 +
35 + Container paddingBottom(double padding) {
36 + return Container(child: this, padding: EdgeInsets.only(bottom: padding));
37 + }
38 +
39 + Container paddingTop(double padding) {
40 + return Container(child: this, padding: EdgeInsets.only(top: padding));
41 + }
42 +
43 + Widget paddingLeftRight(double padding) {
44 + return Container(child: this, padding: EdgeInsets.only(left: padding, right: padding));
45 + }
46 +
47 + Container paddingLeft(double padding) {
48 + return Container(child: this, padding: EdgeInsets.only(left: padding));
49 + }
50 +
51 + Container paddingRight(double padding) {
52 + return Container(child: this, padding: EdgeInsets.only(right: padding));
53 + }
54 +
55 + Row rowRight() {
56 + return Row(mainAxisAlignment: MainAxisAlignment.end, children: [this]);
57 + }
58 +
59 + Row rowLeft() {
60 + return Row(mainAxisAlignment: MainAxisAlignment.start, children: [this]);
61 + }
62 +
63 + Row rowCenter() {
64 + return Row(mainAxisAlignment: MainAxisAlignment.center, children: [this]);
65 + }
66 +
67 + Widget click(
68 + GestureTapCallback? onTap, {
69 + Color? color,
70 + double? radius,
71 + BorderRadius? borderRadius,
72 + Color? bgColor,
73 + }) {
74 + if (color != null) {
75 + var border = radius == null ? null : BorderRadius.all(Radius.circular(radius));
76 + return getMaterialInkWell(
77 + this,
78 + onTap,
79 + color,
80 + borderRadius: borderRadius ?? border,
81 + bgColor: bgColor,
82 + );
83 + }
84 + return getWhiteInkWell(this, onTap);
85 + }
86 +
87 + ///当InkWell效果失效时,使用这个套件
88 + Widget getMaterialInkWell(
89 + Widget widget,
90 + GestureTapCallback? onTap,
91 + Color? color, {
92 + BorderRadius? borderRadius,
93 + Color? splashColor,
94 + Color? bgColor = Colors.white,
95 + }) {
96 + return Material(
97 + color: bgColor,
98 + child: Ink(
99 + decoration: BoxDecoration(
100 + color: color,
101 + borderRadius: borderRadius,
102 + ),
103 + child: InkWell(
104 + onTap: onTap,
105 + splashColor: splashColor,
106 + borderRadius: borderRadius,
107 + child: widget,
108 + ),
109 + ),
110 + );
111 + }
112 +
113 + ///当InkWell效果失效时,使用这个套件
114 + Widget getWhiteInkWell(Widget widget, GestureTapCallback? onTap, {BorderRadius? borderRadius}) {
115 + return Material(
116 + child: Ink(
117 + color: Colors.white,
118 + child: InkWell(onTap: onTap, child: widget),
119 + ),
120 + );
121 + }
11 } 122 }
......
...@@ -6,6 +6,7 @@ import 'package:dio/dio.dart'; ...@@ -6,6 +6,7 @@ import 'package:dio/dio.dart';
6 import 'package:flustars/flustars.dart'; 6 import 'package:flustars/flustars.dart';
7 import 'package:flutter/material.dart'; 7 import 'package:flutter/material.dart';
8 import 'package:flutter/services.dart'; 8 import 'package:flutter/services.dart';
9 +import 'package:flutter_easyloading/flutter_easyloading.dart';
9 import 'package:oktoast/oktoast.dart'; 10 import 'package:oktoast/oktoast.dart';
10 import 'package:provider/provider.dart'; 11 import 'package:provider/provider.dart';
11 import 'package:quick_actions/quick_actions.dart'; 12 import 'package:quick_actions/quick_actions.dart';
...@@ -60,8 +61,7 @@ Future<void> main() async { ...@@ -60,8 +61,7 @@ Future<void> main() async {
60 await SpUtil.getInstance(); 61 await SpUtil.getInstance();
61 62
62 WidgetsFlutterBinding.ensureInitialized(); 63 WidgetsFlutterBinding.ensureInitialized();
63 - SystemChrome.setPreferredOrientations( 64 + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
64 - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
65 65
66 /// 1.22 预览功能: 在输入频率与显示刷新率不匹配情况下提供平滑的滚动效果 66 /// 1.22 预览功能: 在输入频率与显示刷新率不匹配情况下提供平滑的滚动效果
67 // GestureBinding.instance?.resamplingEnabled = true; 67 // GestureBinding.instance?.resamplingEnabled = true;
...@@ -69,8 +69,7 @@ Future<void> main() async { ...@@ -69,8 +69,7 @@ Future<void> main() async {
69 handleError(() => runApp(MyApp())); 69 handleError(() => runApp(MyApp()));
70 70
71 /// 隐藏状态栏。为启动页、引导页设置。完成后修改回显示状态栏。 71 /// 隐藏状态栏。为启动页、引导页设置。完成后修改回显示状态栏。
72 - SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, 72 + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom]);
73 - overlays: [SystemUiOverlay.bottom]);
74 // TODO(weilu): 启动体验不佳。状态栏、导航栏在冷启动开始的一瞬间为黑色,且无法通过隐藏、修改颜色等方式进行处理。。。 73 // TODO(weilu): 启动体验不佳。状态栏、导航栏在冷启动开始的一瞬间为黑色,且无法通过隐藏、修改颜色等方式进行处理。。。
75 // 相关问题跟踪:https://github.com/flutter/flutter/issues/73351 74 // 相关问题跟踪:https://github.com/flutter/flutter/issues/73351
76 if (Platform.isAndroid) { 75 if (Platform.isAndroid) {
...@@ -133,8 +132,7 @@ class MyApp extends StatelessWidget { ...@@ -133,8 +132,7 @@ class MyApp extends StatelessWidget {
133 } 132 }
134 133
135 quickActions.setShortcutItems(<ShortcutItem>[ 134 quickActions.setShortcutItems(<ShortcutItem>[
136 - const ShortcutItem( 135 + const ShortcutItem(type: 'demo', localizedTitle: '发一言', icon: 'flutter_dash_black'),
137 - type: 'demo', localizedTitle: '发一言', icon: 'flutter_dash_black'),
138 ]); 136 ]);
139 } 137 }
140 } 138 }
...@@ -149,8 +147,7 @@ class MyApp extends StatelessWidget { ...@@ -149,8 +147,7 @@ class MyApp extends StatelessWidget {
149 ChangeNotifierProvider(create: (_) => MembershipViewProvider()) 147 ChangeNotifierProvider(create: (_) => MembershipViewProvider())
150 ], 148 ],
151 child: Consumer2<ThemeProvider, LocaleProvider>( 149 child: Consumer2<ThemeProvider, LocaleProvider>(
152 - builder: 150 + builder: (_, ThemeProvider provider, LocaleProvider localeProvider, __) {
153 - (_, ThemeProvider provider, LocaleProvider localeProvider, __) {
154 return _buildMaterialApp(provider, localeProvider); 151 return _buildMaterialApp(provider, localeProvider);
155 }, 152 },
156 ), 153 ),
...@@ -159,15 +156,13 @@ class MyApp extends StatelessWidget { ...@@ -159,15 +156,13 @@ class MyApp extends StatelessWidget {
159 /// Toast 配置 156 /// Toast 配置
160 return OKToast( 157 return OKToast(
161 backgroundColor: Colors.black54, 158 backgroundColor: Colors.black54,
162 - textPadding: 159 + textPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
163 - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
164 radius: 20.0, 160 radius: 20.0,
165 position: ToastPosition.bottom, 161 position: ToastPosition.bottom,
166 child: app); 162 child: app);
167 } 163 }
168 164
169 - Widget _buildMaterialApp( 165 + Widget _buildMaterialApp(ThemeProvider provider, LocaleProvider localeProvider) {
170 - ThemeProvider provider, LocaleProvider localeProvider) {
171 return MaterialApp( 166 return MaterialApp(
172 title: '一言', 167 title: '一言',
173 // showPerformanceOverlay: true, //显示性能标签 168 // showPerformanceOverlay: true, //显示性能标签
...@@ -185,7 +180,7 @@ class MyApp extends StatelessWidget { ...@@ -185,7 +180,7 @@ class MyApp extends StatelessWidget {
185 supportedLocales: ParlandoLocalizations.supportedLocales, 180 supportedLocales: ParlandoLocalizations.supportedLocales,
186 locale: localeProvider.locale, 181 locale: localeProvider.locale,
187 navigatorKey: navigatorKey, 182 navigatorKey: navigatorKey,
188 - builder: (BuildContext context, Widget? child) { 183 + builder: EasyLoading.init(builder: (context, child) {
189 /// 仅针对安卓 184 /// 仅针对安卓
190 if (Device.isAndroid) { 185 if (Device.isAndroid) {
191 /// 切换深色模式会触发此方法,这里设置导航栏颜色 186 /// 切换深色模式会触发此方法,这里设置导航栏颜色
...@@ -197,7 +192,7 @@ class MyApp extends StatelessWidget { ...@@ -197,7 +192,7 @@ class MyApp extends StatelessWidget {
197 data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), 192 data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
198 child: child!, 193 child: child!,
199 ); 194 );
200 - }, 195 + }),
201 196
202 /// 因为使用了fluro,这里设置主要针对Web 197 /// 因为使用了fluro,这里设置主要针对Web
203 onUnknownRoute: (_) { 198 onUnknownRoute: (_) {
......
This diff is collapsed. Click to expand it.
...@@ -122,7 +122,7 @@ class LoggingInterceptor extends Interceptor { ...@@ -122,7 +122,7 @@ class LoggingInterceptor extends Interceptor {
122 Log.e('ResponseCode: ${response.statusCode}'); 122 Log.e('ResponseCode: ${response.statusCode}');
123 } 123 }
124 // 输出结果 124 // 输出结果
125 - Log.json(response.data.toString()); 125 + // Log.json(response.data.toString());
126 Log.d('----------End: $duration 毫秒----------'); 126 Log.d('----------End: $duration 毫秒----------');
127 super.onResponse(response, handler); 127 super.onResponse(response, handler);
128 } 128 }
......
1 +import 'dart:async';
2 +
3 +import 'package:flutter/material.dart';
4 +import 'package:in_app_purchase/in_app_purchase.dart';
5 +
6 +class PaymentSdk {
7 + PaymentSdk._privateConstructor();
8 +
9 + static final PaymentSdk _instance = PaymentSdk._privateConstructor();
10 +
11 + static PaymentSdk get instance {
12 + return _instance;
13 + }
14 +
15 + static const Set<String> _kIds = <String>{'yearly_yiyan_vip', 'monthly_yiyan_vip', 'yearly-default'};
16 +
17 + StreamSubscription<List<PurchaseDetails>>? _subscription;
18 + List<ProductDetails> products = [];
19 +
20 + initState() {
21 + final Stream<List<PurchaseDetails>> purchaseUpdated = InAppPurchase.instance.purchaseStream;
22 + _subscription = purchaseUpdated.listen((purchaseDetailsList) {
23 + _listenToPurchaseUpdated(purchaseDetailsList);
24 + }, onDone: () {
25 + _subscription?.cancel();
26 + }, onError: (error) {
27 + // handle error here.
28 + });
29 + }
30 +
31 + Future<List<ProductDetails>> queryProducts() async {
32 + final bool available = await InAppPurchase.instance.isAvailable();
33 + if (!available) {
34 + print("####### isAvailable false");
35 + return [];
36 + }
37 + final ProductDetailsResponse response = await InAppPurchase.instance.queryProductDetails({
38 + 'yearly_yiyan_vip',
39 + 'monthly_yiyan_vip',
40 + 'yearly-default',
41 + 'test.yiyan.vip.1.month',
42 + });
43 + if (response.notFoundIDs.isNotEmpty) {
44 + // Handle the error.
45 + print("####### notFoundIDs");
46 + } else {
47 + }
48 + print(response.productDetails.length);
49 + return products = response.productDetails;
50 + }
51 +
52 + buy(ProductDetails details) {
53 + final PurchaseParam purchaseParam = PurchaseParam(productDetails: details);
54 + if (_isConsumable(details)) {
55 + InAppPurchase.instance.buyConsumable(purchaseParam: purchaseParam);
56 + } else {
57 + InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam);
58 + }
59 + }
60 +
61 + void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) async {
62 + for (var purchaseDetails in purchaseDetailsList) {
63 + if (purchaseDetails.status == PurchaseStatus.pending) {
64 + // _showPendingUI();
65 + } else {
66 + if (purchaseDetails.status == PurchaseStatus.error) {
67 + // _handleError(purchaseDetails.error!);
68 + } else if (purchaseDetails.status == PurchaseStatus.purchased || purchaseDetails.status == PurchaseStatus.restored) {
69 + bool valid = await _verifyPurchase(purchaseDetails);
70 + if (valid) {
71 + _deliverProduct(purchaseDetails);
72 + } else {
73 + _handleInvalidPurchase(purchaseDetails);
74 + }
75 + }
76 + if (purchaseDetails.pendingCompletePurchase) {
77 + await InAppPurchase.instance.completePurchase(purchaseDetails);
78 + }
79 + }
80 + }
81 + }
82 +
83 + _verifyPurchase(PurchaseDetails purchaseDetails) async {
84 + return true;
85 + }
86 +
87 + void _deliverProduct(PurchaseDetails purchaseDetails) {}
88 +
89 + void _handleInvalidPurchase(PurchaseDetails purchaseDetails) {}
90 +
91 + bool _isConsumable(ProductDetails details) {
92 + return true;
93 + }
94 +
95 + void dispose() {
96 + _subscription?.cancel();
97 + }
98 +}
...@@ -26,7 +26,7 @@ class PaymentService { ...@@ -26,7 +26,7 @@ class PaymentService {
26 late StreamSubscription<PurchaseResult?> _purchaseErrorSubscription; 26 late StreamSubscription<PurchaseResult?> _purchaseErrorSubscription;
27 27
28 /// List of product ids you want to fetch 28 /// List of product ids you want to fetch
29 - final List<String> _productIds = ['test.yiyan.vip.1.month']; 29 + final List<String> _productIds = ['yearly_yiyan_vip', 'monthly_yiyan_vip'];
30 30
31 /// All available products will be store in this list 31 /// All available products will be store in this list
32 late List<IAPItem> _products; 32 late List<IAPItem> _products;
...@@ -36,12 +36,12 @@ class PaymentService { ...@@ -36,12 +36,12 @@ class PaymentService {
36 36
37 /// view of the app will subscribe to this to get notified 37 /// view of the app will subscribe to this to get notified
38 /// when premium status of the user changes 38 /// when premium status of the user changes
39 - final ObserverList<Function> _proStatusChangedListeners = 39 + final ObserverList<Function> _proStatusChangedListeners = ObserverList<Function>();
40 - ObserverList<Function>();
41 40
42 /// view of the app will subscribe to this to get errors of the purchase 41 /// view of the app will subscribe to this to get errors of the purchase
43 - final ObserverList<Function(String)> _errorListeners = 42 + final ObserverList<Function(String)> _errorListeners = ObserverList<Function(String)>();
44 - ObserverList<Function(String)>(); 43 +
44 + final ObserverList<Function> _connectListeners = ObserverList<Function>();
45 45
46 /// logged in user's premium status 46 /// logged in user's premium status
47 bool _isProUser = false; 47 bool _isProUser = false;
...@@ -68,6 +68,20 @@ class PaymentService { ...@@ -68,6 +68,20 @@ class PaymentService {
68 _errorListeners.remove(callback); 68 _errorListeners.remove(callback);
69 } 69 }
70 70
71 + addConnectListener(Function? callback) {
72 + if (callback == null) {
73 + return;
74 + }
75 + _connectListeners.add(callback);
76 + }
77 +
78 + removeConnectListener(Function? callback) {
79 + if (callback == null) {
80 + return;
81 + }
82 + _connectListeners.remove(callback);
83 + }
84 +
71 /// Call this method to notify all the subsctibers of _proStatusChangedListeners 85 /// Call this method to notify all the subsctibers of _proStatusChangedListeners
72 void _callProStatusChangedListeners() { 86 void _callProStatusChangedListeners() {
73 for (var callback in _proStatusChangedListeners) { 87 for (var callback in _proStatusChangedListeners) {
...@@ -84,18 +98,19 @@ class PaymentService { ...@@ -84,18 +98,19 @@ class PaymentService {
84 98
85 /// Call this method at the startup of you app to initialize connection 99 /// Call this method at the startup of you app to initialize connection
86 /// with billing server and get all the necessary data 100 /// with billing server and get all the necessary data
87 - void initConnection() { 101 + void initConnection() async {
88 - var result = FlutterInappPurchase.instance.initialize(); 102 + var result = await FlutterInappPurchase.instance.initialize();
89 print("___________________________"); 103 print("___________________________");
90 print("result:$result"); 104 print("result:$result");
91 - _connectionSubscription = 105 + _connectionSubscription = FlutterInappPurchase.connectionUpdated.listen((connected) {
92 - FlutterInappPurchase.connectionUpdated.listen((connected) {}); 106 + for (var value in _connectListeners) {
107 + value.call();
108 + }
109 + });
93 110
94 - _purchaseUpdatedSubscription = 111 + _purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen(_handlePurchaseUpdate);
95 - FlutterInappPurchase.purchaseUpdated.listen(_handlePurchaseUpdate);
96 112
97 - _purchaseErrorSubscription = 113 + _purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen(_handlePurchaseError);
98 - FlutterInappPurchase.purchaseError.listen(_handlePurchaseError);
99 114
100 _getItems(); 115 _getItems();
101 _getPastPurchases(); 116 _getPastPurchases();
...@@ -191,14 +206,14 @@ class PaymentService { ...@@ -191,14 +206,14 @@ class PaymentService {
191 } 206 }
192 207
193 Future<void> _getItems() async { 208 Future<void> _getItems() async {
194 - List<IAPItem> items = 209 + List<IAPItem> items = await FlutterInappPurchase.instance.getSubscriptions(_productIds);
195 - await FlutterInappPurchase.instance.getSubscriptions(_productIds); 210 + print("############${items.length}");
196 _products = []; 211 _products = [];
197 for (var item in items) { 212 for (var item in items) {
198 _products.add(item); 213 _products.add(item);
199 } 214 }
200 print("############"); 215 print("############");
201 - print(_products); 216 + print("############${_products}");
202 } 217 }
203 218
204 void _getPastPurchases() async { 219 void _getPastPurchases() async {
...@@ -206,8 +221,7 @@ class PaymentService { ...@@ -206,8 +221,7 @@ class PaymentService {
206 if (Platform.isIOS) { 221 if (Platform.isIOS) {
207 return; 222 return;
208 } 223 }
209 - List<PurchasedItem>? purchasedItems = 224 + List<PurchasedItem>? purchasedItems = await FlutterInappPurchase.instance.getAvailablePurchases();
210 - await FlutterInappPurchase.instance.getAvailablePurchases();
211 225
212 for (var purchasedItem in purchasedItems!) { 226 for (var purchasedItem in purchasedItems!) {
213 bool isValid = false; 227 bool isValid = false;
...@@ -236,8 +250,7 @@ class PaymentService { ...@@ -236,8 +250,7 @@ class PaymentService {
236 250
237 Future<void> buyProduct(IAPItem item) async { 251 Future<void> buyProduct(IAPItem item) async {
238 try { 252 try {
239 - await FlutterInappPurchase.instance 253 + await FlutterInappPurchase.instance.requestSubscription(item.productId.toString());
240 - .requestSubscription(item.productId.toString());
241 } catch (error) { 254 } catch (error) {
242 Toast.show("购买失败!"); 255 Toast.show("购买失败!");
243 } 256 }
......
...@@ -417,6 +417,13 @@ packages: ...@@ -417,6 +417,13 @@ packages:
417 url: "https://pub.flutter-io.cn" 417 url: "https://pub.flutter-io.cn"
418 source: hosted 418 source: hosted
419 version: "1.1.2" 419 version: "1.1.2"
420 + flutter_easyloading:
421 + dependency: "direct main"
422 + description:
423 + name: flutter_easyloading
424 + url: "https://pub.flutter-io.cn"
425 + source: hosted
426 + version: "3.0.5"
420 flutter_facebook_auth: 427 flutter_facebook_auth:
421 dependency: "direct main" 428 dependency: "direct main"
422 description: 429 description:
...@@ -710,6 +717,34 @@ packages: ...@@ -710,6 +717,34 @@ packages:
710 url: "https://pub.flutter-io.cn" 717 url: "https://pub.flutter-io.cn"
711 source: hosted 718 source: hosted
712 version: "2.6.2" 719 version: "2.6.2"
720 + in_app_purchase:
721 + dependency: "direct main"
722 + description:
723 + name: in_app_purchase
724 + url: "https://pub.flutter-io.cn"
725 + source: hosted
726 + version: "3.0.8"
727 + in_app_purchase_android:
728 + dependency: transitive
729 + description:
730 + name: in_app_purchase_android
731 + url: "https://pub.flutter-io.cn"
732 + source: hosted
733 + version: "0.2.3+6"
734 + in_app_purchase_platform_interface:
735 + dependency: transitive
736 + description:
737 + name: in_app_purchase_platform_interface
738 + url: "https://pub.flutter-io.cn"
739 + source: hosted
740 + version: "1.3.2"
741 + in_app_purchase_storekit:
742 + dependency: transitive
743 + description:
744 + name: in_app_purchase_storekit
745 + url: "https://pub.flutter-io.cn"
746 + source: hosted
747 + version: "0.3.3"
713 integration_test: 748 integration_test:
714 dependency: "direct dev" 749 dependency: "direct dev"
715 description: flutter 750 description: flutter
......
...@@ -101,6 +101,8 @@ dependencies: ...@@ -101,6 +101,8 @@ dependencies:
101 101
102 # A Dart timer that can be paused, resumed and reset. 102 # A Dart timer that can be paused, resumed and reset.
103 pausable_timer: ^1.0.0+3 103 pausable_timer: ^1.0.0+3
104 +
105 + flutter_easyloading: ^3.0.0
104 email_validator: ^2.0.1 106 email_validator: ^2.0.1
105 107
106 getwidget: ^2.0.5 108 getwidget: ^2.0.5
...@@ -114,7 +116,10 @@ dependencies: ...@@ -114,7 +116,10 @@ dependencies:
114 animated_radial_menu: 116 animated_radial_menu:
115 path: plugins/animated_radial 117 path: plugins/animated_radial
116 118
119 + # 非官方库 暂时不删
117 flutter_inapp_purchase: ^5.3.0 120 flutter_inapp_purchase: ^5.3.0
121 + # Flutter官方支付支持库
122 + in_app_purchase: ^3.0.8
118 123
119 jpush_flutter: ^2.2.9 124 jpush_flutter: ^2.2.9
120 share_plus: ^4.0.10 125 share_plus: ^4.0.10
...@@ -125,6 +130,7 @@ dependencies: ...@@ -125,6 +130,7 @@ dependencies:
125 google_fonts: ^3.0.1 130 google_fonts: ^3.0.1
126 wakelock: ^0.6.1+2 131 wakelock: ^0.6.1+2
127 location: ^4.4.0 132 location: ^4.4.0
133 + # GoogleMap支持库
128 google_maps_flutter: ^2.2.1 134 google_maps_flutter: ^2.2.1
129 http: ^0.13.5 135 http: ^0.13.5
130 136
......