From 153a2f07cc154800e712d9846222bf528f1bb9fe Mon Sep 17 00:00:00 2001 From: CYH <13923927013@163.com> Date: Tue, 15 Aug 2023 16:18:57 +0800 Subject: [PATCH] =?UTF-8?q?1.1.0=E7=89=88=E6=9C=AC=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=EF=BC=8C=E5=A2=9E=E5=8A=A0iOS=E5=86=85?= =?UTF-8?q?=E8=B4=AD=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=B8=83?= =?UTF-8?q?=E7=89=9B=E4=BA=91=E6=B7=BB=E5=8A=A0=E6=B0=B4=E5=8D=B0=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=97=A0=E6=B3=95=E4=B8=8A=E4=BC=A0=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- circle_app/lib/app/call_out/logic.dart | 23 +- circle_app/lib/app/circle/logic.dart | 3 + .../app/circle/widgets/info_list_view.dart | 10 +- .../lib/app/dialog/UnlockCallDialog.dart | 9 +- .../app/login/complete_material/logic.dart | 3 +- circle_app/lib/app/login/login/logic.dart | 13 +- circle_app/lib/app/login/login/view.dart | 10 +- circle_app/lib/app/minefragment/view.dart | 14 +- .../tim_uikit_conversation_last_msg.dart | 8 +- circle_app/lib/app/util/paymentUtil.dart | 248 ++++++++++++++++++ .../lib/common/Widgets/base_tip_widget.dart | 8 +- .../common/Widgets/open_vip_tip/logic.dart | 2 +- .../lib/common/Widgets/open_vip_tip/view.dart | 13 +- circle_app/lib/main.dart | 17 +- circle_app/lib/network/api.dart | 7 +- circle_app/lib/util/qiniu.dart | 60 ++--- circle_app/pubspec.yaml | 3 +- 17 files changed, 362 insertions(+), 89 deletions(-) create mode 100644 circle_app/lib/app/util/paymentUtil.dart diff --git a/circle_app/lib/app/call_out/logic.dart b/circle_app/lib/app/call_out/logic.dart index 15ecb8b..30efb70 100644 --- a/circle_app/lib/app/call_out/logic.dart +++ b/circle_app/lib/app/call_out/logic.dart @@ -184,17 +184,17 @@ class Call_outLogic extends GetxController { // showDialog(); print(numbers[0].id); - showJoinCiclePiker(numbers[0].id.toString(),callOutBean.data.amount.toString(),callOutBean.data.oldAmount.toString(),0,(payResult){ - final logic = Get.put(CircleLogic()); - logic.circle.lists.forEach((element) { - if(element.id == numbers[0].id){ - element.is_limit = false; - } - }); - // widget.bean.is_limit = false; - }); + // showJoinCiclePiker(numbers[0].id.toString(),callOutBean.data.amount.toString(),callOutBean.data.oldAmount.toString(),0,(payResult){ + // final logic = Get.put(CircleLogic()); + // logic.circle.lists.forEach((element) { + // if(element.id == numbers[0].id){ + // element.is_limit = false; + // } + // }); + // // widget.bean.is_limit = false; + // }); - UnlockCallDialog().showUnlockBottomSheet(numbers[0].id); + UnlockCallDialog().showUnlockBottomSheet(numbers[0].id,callOutBean.data.amount.toString(),callOutBean.data.oldAmount.toString(),iositem: callOutBean.data.ios_item); // tipWdiget() } else { showOKToast(beandata.msg); @@ -414,12 +414,14 @@ class ThumbnailResult { class CirclePaymentBean { final int id; final String title; + final String ios_item; final double amount; final double oldAmount; CirclePaymentBean({ required this.id, required this.title, + required this.ios_item, required this.amount, required this.oldAmount, }); @@ -427,6 +429,7 @@ class CirclePaymentBean { factory CirclePaymentBean.fromJson(Map json) { return CirclePaymentBean( id: json['id'] as int, + ios_item: json['ios_item'] ?? '', title: json['title'] as String, amount: json['amount'] as double, oldAmount: json['old_amount'] as double, diff --git a/circle_app/lib/app/circle/logic.dart b/circle_app/lib/app/circle/logic.dart index f7126d4..ad8c71a 100644 --- a/circle_app/lib/app/circle/logic.dart +++ b/circle_app/lib/app/circle/logic.dart @@ -170,6 +170,7 @@ class Circle { String image; String title; String intro; + String ios_item; double amount; bool is_limit; double oldAmount; @@ -184,6 +185,7 @@ class Circle { required this.id, required this.is_limit, required this.image, + required this.ios_item, required this.title, required this.intro, required this.amount, @@ -205,6 +207,7 @@ class Circle { id: json['id'], is_limit: json['is_limit'] ?? false, image: json['image'], + ios_item: json['ios_item'] ?? '', title: json['title'], intro: json['intro'], amount: json['amount'].toDouble(), diff --git a/circle_app/lib/app/circle/widgets/info_list_view.dart b/circle_app/lib/app/circle/widgets/info_list_view.dart index 48d042b..4451ce2 100644 --- a/circle_app/lib/app/circle/widgets/info_list_view.dart +++ b/circle_app/lib/app/circle/widgets/info_list_view.dart @@ -26,7 +26,7 @@ class InfoListView extends StatefulWidget { var logic; Circle bean; int index; - //MyListViewback back; + // Function updateBeanCall; InfoListView(this.index, this.bean, this.logic,{super.key}); @@ -194,7 +194,7 @@ class InfoListViewState extends State with AutomaticKeepAliveClien if (widget.bean.is_limit&&widget.bean.amount>0) { showJoinCiclePiker(cicleId,widget.bean.amount.toString(),widget.bean.oldAmount.toString(),2,(payResult){ widget.bean.is_limit = false; - }); + },widget.bean.ios_item); return; } @@ -661,7 +661,7 @@ class InfoListViewState extends State with AutomaticKeepAliveClien if (widget.bean.is_limit&&widget.bean.amount>0) { showJoinCiclePiker(widget.bean.id.toString(),widget.bean.amount.toString(),widget.bean.oldAmount.toString(),1,(payResult){ widget.bean.is_limit = false; - }); + },widget.bean.ios_item); return; } pushHomePage(lists, lists.id.toString()); @@ -840,7 +840,7 @@ class InfoListViewState extends State with AutomaticKeepAliveClien )), GestureDetector( onTap: () { - pushMsgPage(lists, widget.bean.id.toString()); + pushMsgPage(lists, widget.bean.id.toString(),); // pushHomePage( // lists, widget.bean.id.toString()); }, @@ -956,7 +956,7 @@ class InfoListViewState extends State with AutomaticKeepAliveClien if (widget.bean.is_limit&&widget.bean.amount > 0) { showJoinCiclePiker(widget.bean.id.toString(),widget.bean.amount.toString(),widget.bean.oldAmount.toString(),1,(payResult){ widget.bean.is_limit = false; - }); + },widget.bean.ios_item); return; } pushHomePage(lists, lists.id.toString()); diff --git a/circle_app/lib/app/dialog/UnlockCallDialog.dart b/circle_app/lib/app/dialog/UnlockCallDialog.dart index a55bf67..ec01360 100644 --- a/circle_app/lib/app/dialog/UnlockCallDialog.dart +++ b/circle_app/lib/app/dialog/UnlockCallDialog.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:circle_app/app/util/paymentUtil.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -16,7 +17,7 @@ class UnlockCallDialog extends GetxController { RxBool isZfbPrice = true.obs; String circleId = ""; - void showUnlockBottomSheet(String id) { + void showUnlockBottomSheet(String id,String amount,String oldAmount,{String iositem= ''}) { circleId = id; Get.bottomSheet( Scaffold( @@ -167,8 +168,10 @@ class UnlockCallDialog extends GetxController { Positioned( bottom: 18.sp, child: GestureDetector( + behavior: HitTestBehavior.opaque, onTap: () { if (Platform.isIOS) { + IOSPayment.instance.iosPay(iositem, circleId, 1); } else { startPayment(); // unlockingPayment(numbers[0].id, (payResult) {}); @@ -200,7 +203,7 @@ class UnlockCallDialog extends GetxController { child: Row( children: [ Text( - '¥18', + '¥$amount', style: TextStyle( color: Color(0xffE845FF), fontSize: 16.sp, @@ -210,7 +213,7 @@ class UnlockCallDialog extends GetxController { width: 2.sp, ), Text( - '(原价60)', + '(原价$oldAmount)', style: TextStyle( color: Colors.white70, fontSize: 16.sp, diff --git a/circle_app/lib/app/login/complete_material/logic.dart b/circle_app/lib/app/login/complete_material/logic.dart index d876059..bfe21e6 100644 --- a/circle_app/lib/app/login/complete_material/logic.dart +++ b/circle_app/lib/app/login/complete_material/logic.dart @@ -111,7 +111,7 @@ class Complete_materialLogic extends GetxController { if(null==pickedFile){ return; } - SmartDialog.showLoading(); + SmartDialog.showLoading(msg: '上传中'); uploadImage(quToken,pickedFile!,CONFIG.USER_INFO_AVATAR,(result){ SmartDialog.dismiss(force: true); headUrl = result; @@ -119,6 +119,7 @@ class Complete_materialLogic extends GetxController { }); } catch (e) { + SmartDialog.dismiss(); print(e); } } diff --git a/circle_app/lib/app/login/login/logic.dart b/circle_app/lib/app/login/login/logic.dart index 7af4980..dc8163a 100644 --- a/circle_app/lib/app/login/login/logic.dart +++ b/circle_app/lib/app/login/login/logic.dart @@ -17,6 +17,8 @@ import 'state.dart'; class LoginLogic extends GetxController { bool check = false; + bool isGetCode = false; + @override void onReady() { // TODO: implement onReady @@ -35,12 +37,12 @@ class LoginLogic extends GetxController { print(loginPhone); phoneEditingController.text = loginPhone; if (GetUtils.isPhoneNumber(loginPhone) && loginPhone.length == 11) { - isPhoto = true; + isPhone = true; } update(); } - bool isPhoto = false; + bool isPhone = false; final LoginState state = LoginState(); TextEditingController phoneEditingController = TextEditingController(); TextEditingController codeEditingController = TextEditingController(); @@ -52,12 +54,14 @@ class LoginLogic extends GetxController { //倒计时 starDownTimer() { if (sendCodeBtn == false && seconds == 60) { - isPhoto = true; + sendCodeBtn = true; + isPhone = true; getCode(); } } Future getCode() async { + var data = await DioManager.instance.post( url: Api.sendCode, params: {"phone": phoneEditingController.text}); var bean = BaseResponse.fromJson(data, (data) => Data.fromJson(data)); @@ -69,7 +73,7 @@ class LoginLogic extends GetxController { // codeEditingController.text = bean.data!.code.toString(); // update(); } - sendCodeBtn = true; + t = Timer.periodic(const Duration(milliseconds: 1000), (timer) { seconds--; if (seconds == 0) { @@ -80,6 +84,7 @@ class LoginLogic extends GetxController { update(); }); } else { + sendCodeBtn = false; showOKToast(bean.msg); } } diff --git a/circle_app/lib/app/login/login/view.dart b/circle_app/lib/app/login/login/view.dart index ea6f835..957d74f 100644 --- a/circle_app/lib/app/login/login/view.dart +++ b/circle_app/lib/app/login/login/view.dart @@ -82,9 +82,9 @@ class LoginPage extends StatelessWidget { child: TextField( onChanged: (msg){ if (GetUtils.isPhoneNumber(msg)&& msg.length==11) { - logic.isPhoto = true; + logic.isPhone = true; }else{ - logic.isPhoto = false; + logic.isPhone = false; } logic.update(); }, @@ -168,7 +168,7 @@ class LoginPage extends StatelessWidget { right: 0, child: GestureDetector( onTap: () { - if(logic.isPhoto){ + if(logic.isPhone){ logic.starDownTimer(); } }, @@ -177,12 +177,12 @@ class LoginPage extends StatelessWidget { width: 76.sp, height: 29.sp, decoration: BoxDecoration( - color:logic.isPhoto ? logic.sendCodeBtn? Colors.white30:const Color(0xff0AFCFF) : Colors.white30, + color:logic.isPhone ? logic.sendCodeBtn? Colors.white30:const Color(0xff0AFCFF) : Colors.white30, borderRadius: BorderRadius.circular( 29.sp / 2) ), child: Text(logic.sendCodeBtn ? '${logic.seconds}s' : '获取验证码', style: TextStyle( - color: logic.isPhoto ? logic.sendCodeBtn? Colors.white:Colors.black : Colors.white, fontSize: 12.sp),), + color: logic.isPhone ? logic.sendCodeBtn? Colors.white:Colors.black : Colors.white, fontSize: 12.sp),), ), )), diff --git a/circle_app/lib/app/minefragment/view.dart b/circle_app/lib/app/minefragment/view.dart index 6ec1a30..9e03cf2 100644 --- a/circle_app/lib/app/minefragment/view.dart +++ b/circle_app/lib/app/minefragment/view.dart @@ -50,10 +50,9 @@ class MinefragmentPage extends StatelessWidget { children: [ _buildAvatarRow(logic), _friendsRow(logic), - if (Platform.isAndroid) GestureDetector( onTap: () { - showRechargeDialog(); + showRechargeDialog(logic); }, child: Stack(children: [ Image( @@ -527,7 +526,7 @@ class MinefragmentPage extends StatelessWidget { SizedBox(width: 6.sp), Obx(() { return logic.isVip.value > 0 ? Image( - image: AssetImage(getBaseImage("vip")), + image: AssetImage(getBaseImage(logic.isVip.value == 2 ? 'year_vip' : "vip")), width: 44.sp, height: 18.sp, ) : Container(); @@ -544,14 +543,17 @@ class MinefragmentPage extends StatelessWidget { ); } - showRechargeDialog(){ + showRechargeDialog(MinefragmentLogic ctr) async { Get.bottomSheet( Scaffold( backgroundColor: Colors.transparent, - body: Open_vip_tipPage(true), + body: Open_vip_tipPage(false), ), isScrollControlled: true, - enableDrag: false); + enableDrag: false).then((value) { + ctr.getMode(); + }); + } } diff --git a/circle_app/lib/app/msg/TIMUIKitConversation/tim_uikit_conversation_last_msg.dart b/circle_app/lib/app/msg/TIMUIKitConversation/tim_uikit_conversation_last_msg.dart index 98ec644..85019fa 100644 --- a/circle_app/lib/app/msg/TIMUIKitConversation/tim_uikit_conversation_last_msg.dart +++ b/circle_app/lib/app/msg/TIMUIKitConversation/tim_uikit_conversation_last_msg.dart @@ -78,7 +78,7 @@ class _TIMLastMsgState extends TIMUIKitState { return message.customElem!.desc!; } } - return TIM_t("[自定义]"); + return "[自定义]"; case MessageElemType.V2TIM_ELEM_TYPE_SOUND: return "[语音]"; case MessageElemType.V2TIM_ELEM_TYPE_TEXT: @@ -97,11 +97,11 @@ class _TIMLastMsgState extends TIMUIKitState { case MessageElemType.V2TIM_ELEM_TYPE_VIDEO: return "[视频]"; case MessageElemType.V2TIM_ELEM_TYPE_LOCATION: - return TIM_t("[位置]"); + return "[位置]"; case MessageElemType.V2TIM_ELEM_TYPE_MERGER: - return TIM_t("[聊天记录]"); + return "[聊天记录]"; default: - return TIM_t("未知消息"); + return "未知消息"; } } diff --git a/circle_app/lib/app/util/paymentUtil.dart b/circle_app/lib/app/util/paymentUtil.dart new file mode 100644 index 0000000..3430d0e --- /dev/null +++ b/circle_app/lib/app/util/paymentUtil.dart @@ -0,0 +1,248 @@ +import 'dart:async'; +import 'package:circle_app/app/circle/logic.dart'; +import 'package:circle_app/network/api.dart'; +import 'package:circle_app/network/dio_manager.dart'; +import 'package:circle_app/util/eventBus.dart'; +import 'package:circle_app/util/util.dart'; +import 'package:event_bus/event_bus.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; +import 'package:in_app_purchase/in_app_purchase.dart'; +import 'package:in_app_purchase_storekit/src/types/app_store_purchase_details.dart'; + +// iOS支付单一实例 +// final iOSPayment = IOSPayment(); + +class IOSPayment { + IOSPayment._(); + + static IOSPayment? _instance; + + /// The instance of the [InAppPurchase] to use. + static IOSPayment get instance => _getOrCreateInstance(); + + static IOSPayment _getOrCreateInstance() { + if (_instance != null) { + return _instance!; + } + _instance = IOSPayment._(); + return _instance!; + } + + // 应用内支付实例 + InAppPurchase _inAppPurchase = InAppPurchase.instance; + + // iOS订阅监听 + StreamSubscription>? subscription; + + //1圈子 2会员 + int type = 0; + //可以为解锁圈子ID、会员标识ID + String typeId = ''; + + /// 判断是否可以使用支付 + Future isAvailable() async => await _inAppPurchase.isAvailable(); + + // 开始订阅 + void startSubscription() async { + if (subscription != null) return; + print('>>> start subscription'); + // 支付消息订阅 + // Stream purchaseUpdates = _inAppPurchase.purchaseStream; + Stream> purchaseUpdated = + _inAppPurchase.purchaseStream; + subscription = + purchaseUpdated.listen((List purchaseDetailsList) { + _listenToPurchaseUpdated(purchaseDetailsList); + }, onDone: () { + SmartDialog.dismiss(); + // subscription!.cancel(); + }, onError: (Object error) { + SmartDialog.dismiss(); + showOKToast('出错了,请重新支付'); + // handle error here. + }); + } + + // ListAppStorePurchaseDetails + + Future _listenToPurchaseUpdated( + List purchaseDetailsList) async { + for (final PurchaseDetails purchaseDetails in purchaseDetailsList) { + if (purchaseDetails.status == PurchaseStatus.pending) { + SmartDialog.showLoading(msg: '正在处理'); + } else { + if (purchaseDetails.status == PurchaseStatus.error) { + showOKToast('支付发生错误'); + } else if (purchaseDetails.status == PurchaseStatus.purchased) { + var result = await DioManager.getInstance() + .post(url: Api.applePayCallBack, params: { + 'payload': purchaseDetails.verificationData.serverVerificationData, + 'transaction_id': purchaseDetails.purchaseID, + 'type': type, + 'product_id': int.parse(typeId) + }); + SmartDialog.dismiss(); + if (result['code'] == 200) { + + try { + Get.back(); + } catch (e) {} + + if (type == 1) { + showOKToast('解锁圈子成功'); + if (Get.isRegistered()) { + var logic = Get.find(); + for (var element in logic.circle.lists) { + if (element.id == int.parse(typeId)) { + element.is_limit = false; + } + } + logic.update(); + } + } else { + showOKToast('开通会员成功'); + } + } + await _inAppPurchase.completePurchase(purchaseDetails); + } else if (purchaseDetails.status == PurchaseStatus.canceled || + purchaseDetails.status == PurchaseStatus.error) { + SmartDialog.dismiss(); + if (purchaseDetails.status == PurchaseStatus.canceled) { + showOKToast('取消支付'); + } else { + showOKToast('支付超时了'); + } + } + + await _inAppPurchase.completePurchase(purchaseDetails); + } + } + } + + // Future deliverProduct(PurchaseDetails purchaseDetails) async { + // // IMPORTANT!! Always verify purchase details before delivering the product. + // if (purchaseDetails.productID == _kConsumableId) { + // await ConsumableStore.save(purchaseDetails.purchaseID!); + // final List consumables = await ConsumableStore.load(); + // setState(() { + // _purchasePending = false; + // _consumables = consumables; + // }); + // } else { + // setState(() { + // _purchases.add(purchaseDetails); + // _purchasePending = false; + // }); + // } + // } + + // void handleError(IAPError error) { + // setState(() { + // _purchasePending = false; + // }); + // } + + Future _verifyPurchase(PurchaseDetails purchaseDetails) { + // IMPORTANT!! Always verify a purchase before delivering the product. + // For the purpose of an example, we directly return true. + return Future.value(true); + } + + /// 启动支付 + void iosPay(String skuInfo, String typeID, int productType) async { + if (!await isAvailable()) { + SmartDialog.dismiss(); + showOKToast('无法连接AppStore,请稍后再试'); + return; + } + + // 获取商品列表month_member_3 + var set = [skuInfo].toSet(); + ProductDetailsResponse appStoreProducts = + await _inAppPurchase.queryProductDetails(set); + String orderId = DateTime.now().millisecondsSinceEpoch.toString(); + + if (appStoreProducts.notFoundIDs.isNotEmpty) { + // Handle the error. + SmartDialog.dismiss(); + showOKToast('获取内购产品失败'); + + return; + } + + type = productType; + typeId = typeID; + + List products = appStoreProducts.productDetails; + + // 发起支付 + _inAppPurchase + .buyNonConsumable( + purchaseParam: PurchaseParam( + productDetails: products.last, + applicationUserName: orderId, + ), + ) + .then((value) { + if (value) { + // dismissLoading(); + // showLoading(tip: '正在处理订单'); + // 只要能发起,就写入 + // writeStorage(sku, orderId, 'pending'); + } + }).catchError((err) async { + SmartDialog.dismiss(); + showOKToast('当前商品您有未完成的交易,请等待iOS系统核验后再次发起购买。'); + // if (err['details'] != null) { + // Map details = err['details']; + // // "productIdentifier" -> "12rmb" + // var data = await _inAppPurchase.queryProductDetails(details['productIdentifier']); + // if (data.productDetails.isNotEmpty) { + // // await _inAppPurchase.buyConsumable(purchaseParam: purchaseParam) + // } + // } + + // onError?.call('当前商品您有未完成的交易,请等待iOS系统核验后再次发起购买。'); + print(err); + }); + } + + writeStorage(String key, String value, String status) { + // storage.write(key: key, value: '$value¥$status'); + } + + // 关闭交易 + void finalTransaction(PurchaseDetails purchaseDetails) async { + await _inAppPurchase.completePurchase(purchaseDetails); + // 每完成一张订单进行缓存的清除 + // if (!await checkStorage()) { + // stopListen(); + // } + } + + // 凑单机制 + Future foundRecentOrder(String sku) async { + String orderId = ''; + // String values = await storage.read(key: sku); + // + // if (values != null) { + // orderId = values.split('¥')[0]; + // } + return orderId; + } + + // 校验是否还有缓存 + Future checkStorage() async { + // Map remainingValues = await storage.readAll(); + return false; + } + + // 关闭监听 + stopListen() async { + // subscription!.cancel(); + // subscription = null; + } +} diff --git a/circle_app/lib/common/Widgets/base_tip_widget.dart b/circle_app/lib/common/Widgets/base_tip_widget.dart index d0dc9e7..ac04998 100644 --- a/circle_app/lib/common/Widgets/base_tip_widget.dart +++ b/circle_app/lib/common/Widgets/base_tip_widget.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:circle_app/app/util/paymentUtil.dart'; import 'package:circle_app/util/util.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -14,7 +15,7 @@ import 'open_vip_tip/logic.dart'; bool isZfbPrice = true; joiinCircileTipWdiget(String cicleId, String pirce, String oldPrice, - String title, MyCallback myCallback) { + String title, MyCallback myCallback,{String iosItem = ''}) { return StatefulBuilder(builder: (BuildContext context, StateSetter setState) { return Scaffold( backgroundColor: Colors.transparent, @@ -162,6 +163,7 @@ joiinCircileTipWdiget(String cicleId, String pirce, String oldPrice, behavior: HitTestBehavior.opaque, onTap: () { if (Platform.isIOS) { + IOSPayment.instance.iosPay(iosItem, cicleId, 1); } else { unlockingPayment(cicleId, myCallback); } @@ -256,10 +258,10 @@ unlockingPayment(String cicleId, MyCallback myCallback) async { typedef void MyCallback(bool payResult); showJoinCiclePiker(String cicleId, String pirce, String oldPrice, int type, - MyCallback payResult) { + MyCallback payResult,String iosItem) { String title = ['解锁圈子才能发布喊话', '解锁圈子才能查看主页', '解锁圈子才能主动私聊'][type]; return Get.bottomSheet( - joiinCircileTipWdiget(cicleId, pirce, oldPrice, title, payResult), + joiinCircileTipWdiget(cicleId, pirce, oldPrice, title, payResult,iosItem: iosItem), isScrollControlled: true, enableDrag: false); } diff --git a/circle_app/lib/common/Widgets/open_vip_tip/logic.dart b/circle_app/lib/common/Widgets/open_vip_tip/logic.dart index 8f47da6..952c87d 100644 --- a/circle_app/lib/common/Widgets/open_vip_tip/logic.dart +++ b/circle_app/lib/common/Widgets/open_vip_tip/logic.dart @@ -43,7 +43,7 @@ class Open_vip_tipLogic extends GetxController { update(); } - int index = 0; + int index = 2; final Open_vip_tipState state = Open_vip_tipState(); startPayment() async { diff --git a/circle_app/lib/common/Widgets/open_vip_tip/view.dart b/circle_app/lib/common/Widgets/open_vip_tip/view.dart index 7e29379..dbf9dda 100644 --- a/circle_app/lib/common/Widgets/open_vip_tip/view.dart +++ b/circle_app/lib/common/Widgets/open_vip_tip/view.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:circle_app/app/util/paymentUtil.dart'; import 'package:circle_app/util/util.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -44,11 +45,11 @@ class Open_vip_tipPage extends StatelessWidget { // for (int i = 1; i < 10; i++) { // // } - + if(isYean){ + logic.setYean(); + } return GetBuilder(builder: (Open_vip_tipLogic controller) { - if(isYean){ - controller.setYean(); - } + return Scaffold( backgroundColor: Colors.transparent, body: SizedBox( @@ -208,7 +209,7 @@ class Open_vip_tipPage extends StatelessWidget { behavior: HitTestBehavior.opaque, onTap: (){ if( Platform.isIOS){ - + IOSPayment.instance.iosPay(controller.priceBean[controller.index].iosItem,controller.priceBean[controller.index].id.toString(), 2); }else{ controller.startPayment(); } @@ -252,7 +253,7 @@ class Open_vip_tipPage extends StatelessWidget { navigateToPartnerAgreement(); }, child: Text( - '《合伙人协议》', + '《会员协议》', style: TextStyle( color: const Color(0xff00FFF4), fontSize: 11.sp, diff --git a/circle_app/lib/main.dart b/circle_app/lib/main.dart index b502e9c..5dd5204 100644 --- a/circle_app/lib/main.dart +++ b/circle_app/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'dart:convert'; import 'package:circle_app/app/splash/binding.dart'; +import 'package:circle_app/app/util/paymentUtil.dart'; import 'package:circle_app/common/values/pushconfig.dart'; import 'package:circle_app/network/api.dart'; import 'package:circle_app/network/dio_manager.dart'; @@ -32,11 +33,11 @@ final TUIChatSeparateViewModel chatSeparateViewModel = TUIChatSeparateViewModel(); void main() { - FlutterError.onError = (FlutterErrorDetails details) { - FlutterError.dumpErrorToConsole(details); - // if (kReleaseMode) - // //处理线上错误,如统计上传 - }; + // FlutterError.onError = (FlutterErrorDetails details) { + // FlutterError.dumpErrorToConsole(details); + // // if (kReleaseMode) + // // //处理线上错误,如统计上传 + // }; WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); runApp(const MyApp()); @@ -275,7 +276,7 @@ class _MyAppState extends State with WidgetsBindingObserver { // uploadBuzIDAndToken(); loadBgImage(); super.initState(); - // getLoginStyle(); + addPayNotifi(); } @override void didChangeAppLifecycleState(AppLifecycleState state) async{ @@ -445,4 +446,8 @@ class _MyAppState extends State with WidgetsBindingObserver { }); } + void addPayNotifi() { + IOSPayment.instance.startSubscription(); + } + } diff --git a/circle_app/lib/network/api.dart b/circle_app/lib/network/api.dart index ee403e2..bc6461b 100644 --- a/circle_app/lib/network/api.dart +++ b/circle_app/lib/network/api.dart @@ -1,9 +1,7 @@ import 'package:flutter/foundation.dart'; class Api { - static const baseUrl = !kDebugMode ? 'http://192.168.3.55:2000/' : 'https://leyuan666.com/zuul-service/'; - - // static const baseUrl = 'https://leyuan666.com/zuul-service/'; + static const baseUrl = 'https://leyuan666.com/zuul-service/'; // 获取验证码 static const sendCode = 'msg-service/sms/code/send'; @@ -240,4 +238,7 @@ class Api { //敏感词-屏蔽词 校验 static const shieldWordCheck = 'msg-service/word/check'; + //苹果支付 + static const applePayCallBack = 'mall-service/payment/apple/notify'; + } \ No newline at end of file diff --git a/circle_app/lib/util/qiniu.dart b/circle_app/lib/util/qiniu.dart index 7b06bc4..d315984 100644 --- a/circle_app/lib/util/qiniu.dart +++ b/circle_app/lib/util/qiniu.dart @@ -16,9 +16,9 @@ import 'package:image/image.dart' as img; typedef void MyCallback(String result); - //上传七牛云 -void uploadQiniu(String filePath,String name,String path ,String quToken,MyCallback myCallback) { +void uploadQiniu(String filePath, String name, String path, String quToken, + MyCallback myCallback) { var storage = Storage(); DateTime now = DateTime.now(); String yearMonth = DateFormat('yyyyMM').format(now); @@ -28,40 +28,37 @@ void uploadQiniu(String filePath,String name,String path ,String quToken,MyCallb if (status == StorageStatus.Success) { var headUrl = CONFIG.IMAGE_HEAD + imgPath; myCallback(headUrl); - } print('状态变化: 当前任务状态:$status'); }); putController.addProgressListener((double status) { - print('上传进度: $status'); }); storage.putFile(File(filePath), quToken, options: PutOptions(controller: putController, key: imgPath)); - } -const List jpgSuffix = ["jpg", "jpeg", "JPG", "JPEG","png", "PNG"]; - +const List jpgSuffix = ["jpg", "jpeg", "JPG", "JPEG", "png", "PNG"]; bool isImageJpgOrPng(String imagePath) { String extension = imagePath.split('.').last.toLowerCase(); - return jpgSuffix.contains(extension) ; + return jpgSuffix.contains(extension); } -//封装上传图片 -void uploadImage(String quToken ,XFile pickedFile,String updataRoute,MyCallback myCallback) async{ - // print(quToken); - if(quToken.isEmpty){ +//封装上传图片 +void uploadImage(String quToken, XFile pickedFile, String updataRoute, + MyCallback myCallback) async { + // print(quToken); + if (quToken.isEmpty) { var data = - await DioManager.instance.get(url: Api.getqiniuToken, params: {}); + await DioManager.instance.get(url: Api.getqiniuToken, params: {}); var bean = BaseResponse.fromJson( data, (data) => QnTokenData.fromJson(data)); - if(bean.isSuccess()){ + if (bean.isSuccess()) { quToken = bean.data!.token.toString(); - }else{ + } else { showOKToast("图片上传失败"); SmartDialog.dismiss(force: true); return; @@ -69,17 +66,18 @@ void uploadImage(String quToken ,XFile pickedFile,String updataRoute,MyCallback } //if(isImageJpgOrPng(pickedFile.path)){ - if(false){ - var path = await getApplicationSupportDirectoryPath(); + if (false) { + var path = await getApplicationSupportDirectoryPath(); CompressObject compressObject = CompressObject( - imageFile:File(pickedFile.path), - path:path, + imageFile: File(pickedFile.path), + path: path, quality: 80, step: 6, mode: CompressMode.AUTO, ); Luban.compressImage(compressObject).then((_path) { - uploadQiniu(_path.toString(),pickedFile.name,updataRoute,quToken,(result){ + uploadQiniu(_path.toString(), pickedFile.name, updataRoute, quToken, + (result) { myCallback(result); }); }).catchError((error) { @@ -87,18 +85,17 @@ void uploadImage(String quToken ,XFile pickedFile,String updataRoute,MyCallback showOKToast("图片上传失败"); SmartDialog.dismiss(force: true); }); - }else{ - var path = await getApplicationSupportDirectoryPath(); - String outputPath = path+"ceshishuiyin"; - uploadQiniu(outputPath,pickedFile.name,updataRoute,quToken,(result){ + } else { + // var path = await getApplicationSupportDirectoryPath(); + // String outputPath = path; + uploadQiniu(pickedFile.path, pickedFile.name, updataRoute, quToken, (result) { myCallback(result); - }); } - } -void convertImageFormat(String imagePath, String outputPath, String outputFormat) { +void convertImageFormat( + String imagePath, String outputPath, String outputFormat) { // 读取原始图像文件 final File inputFile = File(imagePath); final List inputBytes = inputFile.readAsBytesSync(); @@ -107,18 +104,19 @@ void convertImageFormat(String imagePath, String outputPath, String outputFormat final img.Image image = img.decodeImage(inputBytes)!; // 转换图像格式 - final img.Image convertedImage = img.copyResize(image, width: image.width, height: image.height); - final List? outputBytes = img.encodeNamedImage(convertedImage, outputFormat); + final img.Image convertedImage = + img.copyResize(image, width: image.width, height: image.height); + final List? outputBytes = + img.encodeNamedImage(convertedImage, outputFormat); // 写入转换后的图像文件 final File outputFile = File(outputPath); outputFile.writeAsBytesSync(outputBytes!); } - String generateRandomString(int length) { var random = Random.secure(); var values = List.generate(length, (index) => random.nextInt(256)); var randomString = base64Url.encode(values); return randomString.substring(0, length); -} \ No newline at end of file +} diff --git a/circle_app/pubspec.yaml b/circle_app/pubspec.yaml index 6d08e91..e7dd8e2 100644 --- a/circle_app/pubspec.yaml +++ b/circle_app/pubspec.yaml @@ -98,7 +98,8 @@ dependencies: flutter_native_splash: 2.2.16 #腾讯离线推送 tencent_chat_push_for_china: ^2.6.2+1 - + #苹果内购 + in_app_purchase: ^3.0.8 dev_dependencies: flutter_test: