import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../routes/app_routes.dart'; import '../../../data/services/pay_service.dart'; import '../../../data/models/goods.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import '../../../data/services/network/dio_manager.dart'; /// goods 模块基础控制器,封装通用的商品加载与支付流程 abstract class GoodsBaseController extends GetxController { final RxList items = [].obs; final RxBool loading = false.obs; final RxString error = ''.obs; late final PayService _payService = Get.find(); @override void onInit() { super.onInit(); _init(); } Future _init() async { loading.value = true; error.value = ''; try { final list = await fetchProducts(); items.assignAll(list); } catch (e) { error.value = e.toString(); } finally { loading.value = false; } } /// 子类实现:返回商品列表(统一使用 DBGoods) Future> fetchProducts(); /// 统一入口:不指定支付方式时,跳转到支付页面交由用户选择 Future purchase(DBGoods item) async { final method = await _showPayMethodSheet(); if (method == null) return; bool ok = false; String failMsg = '支付失败,请重试'; if (method == _PayMethod.wechat) { ok = await payWechat(item, onResult: (success, msg) { if (!success) failMsg = msg ?? failMsg; }); } else if (method == _PayMethod.alipay) { ok = await payAlipay(item, onResult: (success, msg) { if (!success) failMsg = msg ?? failMsg; }); } else if (method == _PayMethod.paypal) { ok = await payPaypal(item, onResult: (success, msg) { if (!success) failMsg = msg ?? failMsg; }); } if (!ok) { Get.snackbar('提示', failMsg, snackPosition: SnackPosition.BOTTOM, margin: const EdgeInsets.all(12)); } } /// 底部弹窗:选择支付方式 Future<_PayMethod?> _showPayMethodSheet() async { final context = Get.context; final isDark = context != null && Theme.of(context).brightness == Brightness.dark; return await Get.bottomSheet<_PayMethod>( SafeArea( child: Container( decoration: BoxDecoration( color: isDark ? Colors.grey[900] : Colors.white, borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 12), child: Container( width: 40, height: 4, decoration: BoxDecoration( color: isDark ? Colors.white24 : Colors.black12, borderRadius: BorderRadius.circular(2), ), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( '选择支付方式', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: isDark ? Colors.white : Colors.black, ), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ GestureDetector( onTap: () => Get.back(result: _PayMethod.wechat), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 56, height: 56, decoration: BoxDecoration( shape: BoxShape.circle, color: isDark ? Colors.white10 : Colors.black12, border: Border.all( color: isDark ? Colors.white24 : Colors.black12, ), ), child: Icon(Icons.wechat, color: Colors.green[600]), ), const SizedBox(height: 8), Text( '微信支付', style: TextStyle( fontSize: 13, color: isDark ? Colors.white : Colors.black, ), ), ], ), ), GestureDetector( onTap: () => Get.back(result: _PayMethod.alipay), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 56, height: 56, decoration: BoxDecoration( shape: BoxShape.circle, color: isDark ? Colors.white10 : Colors.black12, border: Border.all( color: isDark ? Colors.white24 : Colors.black12, ), ), child: Icon(Icons.payment, color: Colors.blue[600]), ), const SizedBox(height: 8), Text( '支付宝', style: TextStyle( fontSize: 13, color: isDark ? Colors.white : Colors.black, ), ), ], ), ), GestureDetector( onTap: () => Get.back(result: _PayMethod.paypal), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 56, height: 56, decoration: BoxDecoration( shape: BoxShape.circle, color: isDark ? Colors.white10 : Colors.black12, border: Border.all( color: isDark ? Colors.white24 : Colors.black12, ), ), child: Icon( Icons.account_balance_wallet, color: Colors.indigo[600], ), ), const SizedBox(height: 8), Text( 'PayPal', style: TextStyle( fontSize: 13, color: isDark ? Colors.white : Colors.black, ), ), ], ), ), ], ), const SizedBox(height: 12), ], ), ), ], ), ), ), isScrollControlled: false, ignoreSafeArea: false, backgroundColor: Colors.transparent, ); } /// 指定微信支付(直接下单并拉起微信) Future payWechat(DBGoods item, {PaymentResultCallback? onResult}) async { final cents = item.price; // DBGoods.price 单位:分 final serverUrl = dotenv.env['SERVER_URL'] ?? DioManager().baseUrl; final paymentData = await _payService.createWechatPayOrder( productId: item.id, productName: item.name, productDesc: item.desc, amount: cents, notifyUrl: '$serverUrl/api/home/pay_wechatnotify', ); if (paymentData == null) { onResult?.call(false, '创建微信订单失败'); return false; } return _payService.wechatPay(paymentData: paymentData, onResult: onResult); } /// 指定支付宝支付(直接下单并拉起支付宝) Future payAlipay(DBGoods item, {PaymentResultCallback? onResult}) async { final cents = item.price; // DBGoods.price 单位:分 final orderInfo = await _payService.createAlipayOrder( productId: item.id, productName: item.name, productDesc: item.desc, amount: cents, notifyUrl: 'https://api.ideapsound.com/api/home/pay_alipaynotify', ); if (orderInfo == null) { onResult?.call(false, '创建支付宝订单失败'); return false; } return _payService.alipay(orderInfo: orderInfo, onResult: onResult); } /// 指定 PayPal 支付(创建订单并打开授权链接) Future payPaypal(DBGoods item, {PaymentResultCallback? onResult}) async { final cents = item.price; // DBGoods.price 单位:分 final approvalUrl = await _payService.createPaypalOrder( productId: item.id, productName: item.name, productDesc: item.desc, amount: cents, notifyUrl: 'https://api.ideapsound.com/api/home/pay_paypalnotify', ); if (approvalUrl == null) { onResult?.call(false, '创建 PayPal 订单失败'); return false; } return _payService.paypalPay(approvalUrl: approvalUrl, onResult: onResult); } } enum _PayMethod { wechat, alipay, paypal }