diff --git a/lib/data/models/channel_app_model.dart b/lib/data/models/channel_app_model.dart index dac792f28..269dd9f5b 100644 --- a/lib/data/models/channel_app_model.dart +++ b/lib/data/models/channel_app_model.dart @@ -69,12 +69,17 @@ class AppInfo { @JsonKey(name: 'tourists') final bool tourists; + /// 支付渠道列表 + @JsonKey(name: 'Paychannels') + final String? paychannels; + const AppInfo({ this.address, required this.channel, required this.description, required this.version, this.tourists = false, + required this.paychannels, }); factory AppInfo.fromJson(Map json) => diff --git a/lib/data/models/channel_app_model.g.dart b/lib/data/models/channel_app_model.g.dart index 952f3fc41..fa2bd07e5 100644 --- a/lib/data/models/channel_app_model.g.dart +++ b/lib/data/models/channel_app_model.g.dart @@ -38,6 +38,7 @@ AppInfo _$AppInfoFromJson(Map json) => AppInfo( description: json['description'] as String, version: json['version'] as String, tourists: json['tourists'] as bool? ?? false, + paychannels: json['paychannels'] as String?, ); Map _$AppInfoToJson(AppInfo instance) => { @@ -46,4 +47,5 @@ Map _$AppInfoToJson(AppInfo instance) => { 'description': instance.description, 'version': instance.version, 'tourists': instance.tourists, + 'paychannels': instance.paychannels, }; diff --git a/lib/modules/goods/controllers/goods_base_controller.dart b/lib/modules/goods/controllers/goods_base_controller.dart index 79370527a..f2a0aec77 100644 --- a/lib/modules/goods/controllers/goods_base_controller.dart +++ b/lib/modules/goods/controllers/goods_base_controller.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:voitrans/data/models/user_Info.dart'; import '../../../routes/app_routes.dart'; import '../../../data/services/pay_service.dart'; +import '../../../data/services/version_update_service.dart'; import '../../../data/models/goods.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import '../../../data/services/network/dio_manager.dart'; @@ -39,10 +40,20 @@ abstract class GoodsBaseController extends GetxController { /// 子类实现:返回商品列表(统一使用 DBGoods) Future> fetchProducts(); - /// 统一入口:不指定支付方式时,跳转到支付页面交由用户选择 + /// 统一入口:根据后端配置决定是否弹出支付方式选择面板 Future purchase(DBGoods item) async { - final method = await _showPayMethodSheet(); - if (method == null) return; + // 读取渠道配置 + final enabled = _getEnabledPayMethods(); + + // 无配置或多个渠道:弹出选择面板 + _PayMethod? method; + if (enabled.length != 1) { + method = await _showPayMethodSheet(enabled); + if (method == null) return; + } else { + // 仅一个渠道:直接走对应支付 + method = enabled.first; + } bool ok = false; String failMsg = '支付失败,请重试'; @@ -75,8 +86,73 @@ abstract class GoodsBaseController extends GetxController { } } - /// 底部弹窗:选择支付方式 - Future<_PayMethod?> _showPayMethodSheet() async { + /// 解析后端 paychannels 并结合平台过滤可用支付方式 + List<_PayMethod> _getEnabledPayMethods() { + try { + final paychannels = + VersionUpdateService.to.cachedAppInfo?.paychannels ?? ''; + final raw = paychannels + .split(',') + .map((e) => e.trim().toLowerCase()) + .where((e) => e.isNotEmpty) + .toList(); + + final bool isIOS = GetPlatform.isIOS && !kIsWeb; + final bool isAndroid = GetPlatform.isAndroid && !kIsWeb; + + final List<_PayMethod> methods = []; + for (final ch in raw) { + switch (ch) { + case 'wxpay': + case 'wechat': + methods.add(_PayMethod.wechat); + break; + case 'alipay': + methods.add(_PayMethod.alipay); + break; + case 'paypal': + methods.add(_PayMethod.paypal); + break; + case 'apple': + if (isIOS) methods.add(_PayMethod.apple); + break; + case 'google': + if (isAndroid) methods.add(_PayMethod.google); + break; + default: + break; + } + } + + // 若后端未下发或全部被平台过滤,则回退为展示所有平台支持的方式 + if (methods.isEmpty) { + final fallback = <_PayMethod>[ + _PayMethod.wechat, + _PayMethod.alipay, + _PayMethod.paypal + ]; + if (isIOS) fallback.add(_PayMethod.apple); + if (isAndroid) fallback.add(_PayMethod.google); + return fallback; + } + return methods; + } catch (_) { + // 任意异常则回退为旧逻辑:展示所有 + final bool isIOS = GetPlatform.isIOS && !kIsWeb; + final bool isAndroid = GetPlatform.isAndroid && !kIsWeb; + final fallback = <_PayMethod>[ + _PayMethod.wechat, + _PayMethod.alipay, + _PayMethod.paypal + ]; + if (isIOS) fallback.add(_PayMethod.apple); + if (isAndroid) fallback.add(_PayMethod.google); + return fallback; + } + } + + /// 底部弹窗:选择支付方式(仅展示后端允许的渠道) + Future<_PayMethod?> _showPayMethodSheet(List<_PayMethod> allowed) async { final context = Get.context; final isDark = context != null && Theme.of(context).brightness == Brightness.dark; @@ -121,105 +197,111 @@ abstract class GoodsBaseController extends GetxController { 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( + if (allowed.contains(_PayMethod.wechat)) + 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.white24 + ? Colors.white10 : Colors.black12, + border: Border.all( + color: isDark + ? Colors.white24 + : Colors.black12, + ), ), + child: Icon(Icons.wechat, + color: Colors.green[600]), ), - child: Icon(Icons.wechat, - color: Colors.green[600]), - ), - const SizedBox(height: 8), - Text( - '微信支付', - style: TextStyle( - fontSize: 13, - color: isDark ? Colors.white : Colors.black, + 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( + if (allowed.contains(_PayMethod.alipay)) + 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.white24 + ? Colors.white10 : Colors.black12, + border: Border.all( + color: isDark + ? Colors.white24 + : Colors.black12, + ), ), + child: Icon(Icons.payment, + color: Colors.blue[600]), ), - child: Icon(Icons.payment, - color: Colors.blue[600]), - ), - const SizedBox(height: 8), - Text( - '支付宝', - style: TextStyle( - fontSize: 13, - color: isDark ? Colors.white : Colors.black, + 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( + if (allowed.contains(_PayMethod.paypal)) + 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.white24 + ? Colors.white10 : Colors.black12, + border: Border.all( + color: isDark + ? Colors.white24 + : Colors.black12, + ), + ), + child: Icon( + Icons.account_balance_wallet, + color: Colors.indigo[600], ), ), - 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: 8), + Text( + 'PayPal', + style: TextStyle( + fontSize: 13, + color: isDark ? Colors.white : Colors.black, + ), ), - ), - ], + ], + ), ), - ), - if (isIOS) + if (isIOS && allowed.contains(_PayMethod.apple)) GestureDetector( onTap: () => Get.back(result: _PayMethod.apple), child: Column( @@ -255,7 +337,7 @@ abstract class GoodsBaseController extends GetxController { ], ), ), - if (isAndroid) + if (isAndroid && allowed.contains(_PayMethod.google)) GestureDetector( onTap: () => Get.back(result: _PayMethod.google), child: Column(