|
|
|
@ -9,14 +9,14 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
|
|
|
|
|
|
|
|
|
|
|
return Scaffold( |
|
|
|
backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], |
|
|
|
appBar: AppBar( |
|
|
|
backgroundColor: isDarkMode ? Colors.black : Colors.white, |
|
|
|
elevation: 0.5, |
|
|
|
title: Text( |
|
|
|
'微信支付测试', |
|
|
|
'支付测试', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
@ -39,6 +39,8 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
children: [ |
|
|
|
_buildTestInfoCard(isDarkMode), |
|
|
|
SizedBox(height: 20.h), |
|
|
|
_buildPaymentMethodSelector(isDarkMode), |
|
|
|
SizedBox(height: 20.h), |
|
|
|
_buildAmountSelector(isDarkMode), |
|
|
|
SizedBox(height: 20.h), |
|
|
|
_buildPaymentButton(isDarkMode), |
|
|
|
@ -51,7 +53,7 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 测试信息卡片 |
|
|
|
Widget _buildTestInfoCard(bool isDarkMode) { |
|
|
|
return Container( |
|
|
|
@ -79,16 +81,20 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 12.h), |
|
|
|
Obx(() => _buildInfoRow('订单ID', controller.testOrderId.value, isDarkMode)), |
|
|
|
Obx(() => _buildInfoRow( |
|
|
|
'商品ID', controller.testProductId.value, isDarkMode)), |
|
|
|
SizedBox(height: 8.h), |
|
|
|
_buildInfoRow('商品描述', '微信支付测试', isDarkMode), |
|
|
|
SizedBox(height: 8.h), |
|
|
|
Obx(() => _buildInfoRow('支付金额', '¥${controller.testAmount.value.toStringAsFixed(2)}', isDarkMode)), |
|
|
|
Obx(() => _buildInfoRow( |
|
|
|
'支付金额', |
|
|
|
'¥${controller.testAmount.value.toStringAsFixed(2)}', |
|
|
|
isDarkMode)), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 信息行 |
|
|
|
Widget _buildInfoRow(String label, String value, bool isDarkMode) { |
|
|
|
return Row( |
|
|
|
@ -116,11 +122,11 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 金额选择器 |
|
|
|
Widget _buildAmountSelector(bool isDarkMode) { |
|
|
|
final amounts = [0.01, 0.10, 1.00, 10.00]; |
|
|
|
|
|
|
|
|
|
|
|
return Container( |
|
|
|
padding: EdgeInsets.all(16.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
@ -151,95 +157,230 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
runSpacing: 8.h, |
|
|
|
children: amounts.map((amount) { |
|
|
|
return Obx(() => GestureDetector( |
|
|
|
onTap: () => controller.updateTestAmount(amount), |
|
|
|
child: Container( |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: controller.testAmount.value == amount |
|
|
|
? Colors.blue[600] |
|
|
|
: (isDarkMode ? Colors.grey[800] : Colors.grey[200]), |
|
|
|
borderRadius: BorderRadius.circular(20.r), |
|
|
|
), |
|
|
|
child: Text( |
|
|
|
'¥${amount.toStringAsFixed(2)}', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: controller.testAmount.value == amount |
|
|
|
? Colors.white |
|
|
|
: (isDarkMode ? Colors.white : Colors.black), |
|
|
|
onTap: () => controller.updateTestAmount(amount), |
|
|
|
child: Container( |
|
|
|
padding: |
|
|
|
EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: controller.testAmount.value == amount |
|
|
|
? Colors.blue[600] |
|
|
|
: (isDarkMode |
|
|
|
? Colors.grey[800] |
|
|
|
: Colors.grey[200]), |
|
|
|
borderRadius: BorderRadius.circular(20.r), |
|
|
|
), |
|
|
|
child: Text( |
|
|
|
'¥${amount.toStringAsFixed(2)}', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: controller.testAmount.value == amount |
|
|
|
? Colors.white |
|
|
|
: (isDarkMode ? Colors.white : Colors.black), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
)); |
|
|
|
)); |
|
|
|
}).toList(), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/// 支付按钮 |
|
|
|
Widget _buildPaymentButton(bool isDarkMode) { |
|
|
|
return Obx(() => SizedBox( |
|
|
|
width: double.infinity, |
|
|
|
height: 50.h, |
|
|
|
child: ElevatedButton( |
|
|
|
onPressed: controller.isLoading.value ? null : controller.testWechatPayment, |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: Colors.green[600], |
|
|
|
foregroundColor: Colors.white, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
|
|
|
|
/// 支付方式选择器 |
|
|
|
Widget _buildPaymentMethodSelector(bool isDarkMode) { |
|
|
|
return Container( |
|
|
|
padding: EdgeInsets.all(16.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.05), |
|
|
|
blurRadius: 10, |
|
|
|
offset: const Offset(0, 2), |
|
|
|
), |
|
|
|
elevation: 2, |
|
|
|
), |
|
|
|
child: controller.isLoading.value |
|
|
|
? Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
children: [ |
|
|
|
SizedBox( |
|
|
|
width: 20.w, |
|
|
|
height: 20.w, |
|
|
|
child: const CircularProgressIndicator( |
|
|
|
strokeWidth: 2, |
|
|
|
valueColor: AlwaysStoppedAnimation<Color>(Colors.white), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
const Text('处理中...'), |
|
|
|
], |
|
|
|
) |
|
|
|
: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
children: [ |
|
|
|
Icon(Icons.payment, size: 20.w), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Text( |
|
|
|
'发起微信支付', |
|
|
|
], |
|
|
|
), |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'选择支付方式', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
// 移除外层的 Obx,因为内部的 _buildPaymentMethodOption 已经有 Obx 了 |
|
|
|
Column( |
|
|
|
children: [ |
|
|
|
_buildPaymentMethodOption( |
|
|
|
method: 1, |
|
|
|
title: '微信支付', |
|
|
|
icon: Icons.wechat, |
|
|
|
iconColor: Colors.green, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
), |
|
|
|
SizedBox(height: 12.h), |
|
|
|
_buildPaymentMethodOption( |
|
|
|
method: 2, |
|
|
|
title: '支付宝支付', |
|
|
|
icon: Icons.account_balance_wallet, |
|
|
|
iconColor: Colors.blue, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/// 支付方式选项 |
|
|
|
Widget _buildPaymentMethodOption({ |
|
|
|
required int method, |
|
|
|
required String title, |
|
|
|
required IconData icon, |
|
|
|
required Color iconColor, |
|
|
|
required bool isDarkMode, |
|
|
|
}) { |
|
|
|
return Obx(() => GestureDetector( |
|
|
|
onTap: () => controller.selectPaymentMethod(method), |
|
|
|
child: Container( |
|
|
|
padding: EdgeInsets.all(12.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: controller.selectedPaymentMethod.value == method |
|
|
|
? (isDarkMode |
|
|
|
? Colors.blue.withOpacity(0.2) |
|
|
|
: Colors.blue.withOpacity(0.1)) |
|
|
|
: (isDarkMode ? Colors.grey[800] : Colors.grey[100]), |
|
|
|
borderRadius: BorderRadius.circular(8.r), |
|
|
|
border: Border.all( |
|
|
|
color: controller.selectedPaymentMethod.value == method |
|
|
|
? Colors.blue |
|
|
|
: Colors.transparent, |
|
|
|
width: 1.5, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
icon, |
|
|
|
color: iconColor, |
|
|
|
size: 24.sp, |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Expanded( |
|
|
|
child: Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
fontSize: 14.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
if (controller.selectedPaymentMethod.value == method) |
|
|
|
Icon( |
|
|
|
Icons.check_circle, |
|
|
|
color: Colors.blue, |
|
|
|
size: 20.sp, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
)); |
|
|
|
} |
|
|
|
|
|
|
|
/// 支付按钮 |
|
|
|
Widget _buildPaymentButton(bool isDarkMode) { |
|
|
|
return Obx(() => Container( |
|
|
|
width: double.infinity, |
|
|
|
height: 50.h, |
|
|
|
child: ElevatedButton( |
|
|
|
onPressed: controller.isLoading.value |
|
|
|
? null |
|
|
|
: () { |
|
|
|
controller.processPayment(); |
|
|
|
}, |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: controller.isLoading.value |
|
|
|
? Colors.grey |
|
|
|
: (controller.selectedPaymentMethod.value == 1 |
|
|
|
? Colors.green |
|
|
|
: Colors.blue), |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
), |
|
|
|
), |
|
|
|
)); |
|
|
|
elevation: 2, |
|
|
|
), |
|
|
|
child: controller.isLoading.value |
|
|
|
? Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
children: [ |
|
|
|
SizedBox( |
|
|
|
width: 20.w, |
|
|
|
height: 20.w, |
|
|
|
child: CircularProgressIndicator( |
|
|
|
strokeWidth: 2, |
|
|
|
valueColor: |
|
|
|
AlwaysStoppedAnimation<Color>(Colors.white), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Text( |
|
|
|
'支付中...', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
) |
|
|
|
: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
children: [ |
|
|
|
Icon( |
|
|
|
controller.selectedPaymentMethod.value == 1 |
|
|
|
? Icons.wechat |
|
|
|
: Icons.account_balance_wallet, |
|
|
|
color: Colors.white, |
|
|
|
size: 20.sp, |
|
|
|
), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Text( |
|
|
|
controller.selectedPaymentMethod.value == 1 |
|
|
|
? '微信支付 ¥${controller.testAmount.value.toStringAsFixed(2)}' |
|
|
|
: '支付宝支付 ¥${controller.testAmount.value.toStringAsFixed(2)}', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
color: Colors.white, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 状态卡片 |
|
|
|
Widget _buildStatusCard(bool isDarkMode) { |
|
|
|
return Obx(() { |
|
|
|
if (controller.paymentStatus.value.isEmpty) { |
|
|
|
return const SizedBox.shrink(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
final isError = controller.errorMessage.value.isNotEmpty; |
|
|
|
|
|
|
|
|
|
|
|
return Container( |
|
|
|
padding: EdgeInsets.all(16.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isError |
|
|
|
color: isError |
|
|
|
? (isDarkMode ? Colors.red[900] : Colors.red[50]) |
|
|
|
: (isDarkMode ? Colors.green[900] : Colors.green[50]), |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
@ -310,7 +451,7 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 使用说明 |
|
|
|
Widget _buildInstructions(bool isDarkMode) { |
|
|
|
return Container( |
|
|
|
@ -362,4 +503,4 @@ class PaymentView extends GetView<PaymentController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|