1.1.0版本代码提交,增加iOS内购功能,修改七牛云添加水印导致无法上传头像问题
This commit is contained in:
parent
9f981d3269
commit
153a2f07cc
@ -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<String, dynamic> 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,
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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<InfoListView> 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<InfoListView> 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<InfoListView> 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<InfoListView> 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());
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<void> getCode() async {
|
||||
|
||||
var data = await DioManager.instance.post(
|
||||
url: Api.sendCode, params: {"phone": phoneEditingController.text});
|
||||
var bean = BaseResponse<Data>.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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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),),
|
||||
),
|
||||
)),
|
||||
|
||||
|
||||
@ -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();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ class _TIMLastMsgState extends TIMUIKitState<TIMLastMsg> {
|
||||
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<TIMLastMsg> {
|
||||
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 "未知消息";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
248
circle_app/lib/app/util/paymentUtil.dart
Normal file
248
circle_app/lib/app/util/paymentUtil.dart
Normal file
@ -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<List<PurchaseDetails>>? subscription;
|
||||
|
||||
//1圈子 2会员
|
||||
int type = 0;
|
||||
//可以为解锁圈子ID、会员标识ID
|
||||
String typeId = '';
|
||||
|
||||
/// 判断是否可以使用支付
|
||||
Future<bool> isAvailable() async => await _inAppPurchase.isAvailable();
|
||||
|
||||
// 开始订阅
|
||||
void startSubscription() async {
|
||||
if (subscription != null) return;
|
||||
print('>>> start subscription');
|
||||
// 支付消息订阅
|
||||
// Stream purchaseUpdates = _inAppPurchase.purchaseStream;
|
||||
Stream<List<PurchaseDetails>> purchaseUpdated =
|
||||
_inAppPurchase.purchaseStream;
|
||||
subscription =
|
||||
purchaseUpdated.listen((List<PurchaseDetails> purchaseDetailsList) {
|
||||
_listenToPurchaseUpdated(purchaseDetailsList);
|
||||
}, onDone: () {
|
||||
SmartDialog.dismiss();
|
||||
// subscription!.cancel();
|
||||
}, onError: (Object error) {
|
||||
SmartDialog.dismiss();
|
||||
showOKToast('出错了,请重新支付');
|
||||
// handle error here.
|
||||
});
|
||||
}
|
||||
|
||||
// List<ProductDetails>AppStorePurchaseDetails
|
||||
|
||||
Future<void> _listenToPurchaseUpdated(
|
||||
List<PurchaseDetails> 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<CircleLogic>()) {
|
||||
var logic = Get.find<CircleLogic>();
|
||||
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<void> deliverProduct(PurchaseDetails purchaseDetails) async {
|
||||
// // IMPORTANT!! Always verify purchase details before delivering the product.
|
||||
// if (purchaseDetails.productID == _kConsumableId) {
|
||||
// await ConsumableStore.save(purchaseDetails.purchaseID!);
|
||||
// final List<String> consumables = await ConsumableStore.load();
|
||||
// setState(() {
|
||||
// _purchasePending = false;
|
||||
// _consumables = consumables;
|
||||
// });
|
||||
// } else {
|
||||
// setState(() {
|
||||
// _purchases.add(purchaseDetails);
|
||||
// _purchasePending = false;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// void handleError(IAPError error) {
|
||||
// setState(() {
|
||||
// _purchasePending = false;
|
||||
// });
|
||||
// }
|
||||
|
||||
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 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<ProductDetails> 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<String> foundRecentOrder(String sku) async {
|
||||
String orderId = '';
|
||||
// String values = await storage.read(key: sku);
|
||||
//
|
||||
// if (values != null) {
|
||||
// orderId = values.split('¥')[0];
|
||||
// }
|
||||
return orderId;
|
||||
}
|
||||
|
||||
// 校验是否还有缓存
|
||||
Future<bool> checkStorage() async {
|
||||
// Map<String, String> remainingValues = await storage.readAll();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 关闭监听
|
||||
stopListen() async {
|
||||
// subscription!.cancel();
|
||||
// subscription = null;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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<MyApp> with WidgetsBindingObserver {
|
||||
// uploadBuzIDAndToken();
|
||||
loadBgImage();
|
||||
super.initState();
|
||||
// getLoginStyle();
|
||||
addPayNotifi();
|
||||
}
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) async{
|
||||
@ -445,4 +446,8 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||
});
|
||||
}
|
||||
|
||||
void addPayNotifi() {
|
||||
IOSPayment.instance.startSubscription();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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';
|
||||
|
||||
}
|
||||
@ -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<String> jpgSuffix = ["jpg", "jpeg", "JPG", "JPEG","png", "PNG"];
|
||||
|
||||
const List<String> 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<QnTokenData>.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<int> 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<int>? outputBytes = img.encodeNamedImage(convertedImage, outputFormat);
|
||||
final img.Image convertedImage =
|
||||
img.copyResize(image, width: image.width, height: image.height);
|
||||
final List<int>? outputBytes =
|
||||
img.encodeNamedImage(convertedImage, outputFormat);
|
||||
|
||||
// 写入转换后的图像文件
|
||||
final File outputFile = File(outputPath);
|
||||
outputFile.writeAsBytesSync(outputBytes!);
|
||||
}
|
||||
|
||||
|
||||
String generateRandomString(int length) {
|
||||
var random = Random.secure();
|
||||
var values = List<int>.generate(length, (index) => random.nextInt(256));
|
||||
var randomString = base64Url.encode(values);
|
||||
return randomString.substring(0, length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user