Flutter 商城结算页面开发:地址选择、支付方式选择和订单提交
Flutter 商城结算页面开发:地址选择、支付方式选择和订单提交
本教程将带你使用 Flutter 开发一个完整的商城结算页面,包含地址选择、支付方式选择和订单提交功能。我们将使用 API 接口进行数据交互,并提供完整的代码示例。
页面功能:
- 地址选择:
- 获取用户地址列表,展示地址信息。
- 支持默认地址标识。
- 新增地址功能,通过 API 接口提交地址信息。
- 支付方式选择:
- 支持支付宝和微信支付方式选择。
- 订单提交:
- 提交选择的地址和支付方式信息。
- 生成支付二维码。
- 轮询订单状态,并根据状态展示支付结果。
代码示例:
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:your_app_name/api_service.dart';
import 'package:your_app_name/models/address.dart';
class CheckoutPage extends StatefulWidget {
@override
_CheckoutPageState createState() => _CheckoutPageState();
}
class _CheckoutPageState extends State<CheckoutPage> {
List<Address> _addresses = [];
Address _selectedAddress;
String _paymentMethod = '支付宝';
@override
void initState() {
super.initState();
_getAddresses();
}
Future<void> _getAddresses() async {
try {
final addresses = await ApiService.getAddresses();
setState(() {
_addresses = addresses;
_selectedAddress = _addresses.firstWhere(
(address) => address.isDefault == 1,
orElse: () => null);
});
} catch (e) {
Fluttertoast.showToast(msg: '获取地址失败');
}
}
Future<void> _addAddress() async {
try {
final address = await ApiService.addAddress(
addressId: '',
provience: '黑龙江省',
city: '哈尔滨市',
district: '五常市',
addressLine: '五常镇广场小区',
phone: '12345678',
isDefault: 1,
name: '宋涛',
);
setState(() {
_addresses.add(address);
_selectedAddress = address;
});
} catch (e) {
Fluttertoast.showToast(msg: '新增地址失败');
}
}
Future<void> _submitOrder() async {
try {
final result = await ApiService.submitOrder(
_selectedAddress.id, _paymentMethod);
final response = json.decode(result);
final qrCodeUrl = response[0];
final orderId = response[1];
_pollOrderStatus(orderId);
// TODO: 显示支付二维码
} catch (e) {
Fluttertoast.showToast(msg: '提交订单失败');
}
}
Future<void> _pollOrderStatus(int orderId) async {
while (true) {
try {
final status = await ApiService.queryOrderStatus(orderId);
if (status == '支付成功') {
Fluttertoast.showToast(msg: '支付成功');
// TODO: 跳转回订单列表页面
break;
} else if (status == '查询返回该订单支付失败或被关闭') {
Fluttertoast.showToast(msg: '支付失败');
break;
} else {
await Future.delayed(Duration(seconds: 5));
}
} catch (e) {
Fluttertoast.showToast(msg: '查询订单状态失败');
break;
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('结算'),
),
body: _buildBody(),
);
}
Widget _buildBody() {
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(16),
child: Text(
'选择收货地址',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
_buildAddressList(),
Padding(
padding: EdgeInsets.all(16),
child: Text(
'选择支付方式',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
_buildPaymentMethod(),
SizedBox(height: 16),
_buildCheckoutButton(),
],
),
);
}
Widget _buildAddressList() {
if (_addresses.isEmpty) {
return Padding(
padding: EdgeInsets.all(16),
child: Text('您还没有添加收货地址'),
);
} else {
return ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: _addresses.length + 1,
separatorBuilder: (context, index) => Divider(height: 1),
itemBuilder: (context, index) {
if (index == _addresses.length) {
return ListTile(
title: Text('新增地址'),
trailing: Icon(Icons.keyboard_arrow_right),
onTap: _addAddress,
);
} else {
final address = _addresses[index];
return ListTile(
title: Text(address.toString()),
subtitle: address.isDefault == 1 ? Text('默认地址') : null,
trailing: _selectedAddress == address
? Icon(Icons.check_circle, color: Colors.green)
: null,
onTap: () {
setState(() {
_selectedAddress = address;
});
},
);
}
},
);
}
}
Widget _buildPaymentMethod() {
return Row(
children: [
Radio(
value: '支付宝',
groupValue: _paymentMethod,
onChanged: (value) {
setState(() {
_paymentMethod = value;
});
},
),
Text('支付宝'),
Radio(
value: '微信',
groupValue: _paymentMethod,
onChanged: (value) {
setState(() {
_paymentMethod = value;
});
},
),
Text('微信'),
],
);
}
Widget _buildCheckoutButton() {
return Padding(
padding: EdgeInsets.all(16),
child: SizedBox(
width: double.infinity,
height: 48,
child: RaisedButton(
child: Text('结算'),
onPressed: _selectedAddress == null
? null
: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('确认支付'),
content: Text('确定要支付吗?'),
actions: [
FlatButton(
child: Text('取消'),
onPressed: () {
Navigator.pop(context);
},
),
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context);
_submitOrder();
},
),
],
),
);
},
),
),
);
}
}
Address类的代码:
class Address {
int id;
String name;
String phone;
String provience;
String city;
String district;
String addressLine;
int isDefault;
Address.fromJson(Map<String, dynamic> json)
: id = json['id'],
name = json['name'],
phone = json['phone'],
provience = json['provience'],
city = json['city'],
district = json['district'],
addressLine = json['addressLine'],
isDefault = json['isDefault'];
@override
String toString() {
return '$provience $city $district $addressLine $name $phone';
}
}
API 接口:
-
获取用户地址列表:
- GET 请求:
http://book.musecloud.tech/getaddresses - 返回数据格式:[{"addressLine":"五常市","city":"天津市","country":"中国","district":"和平区","id":1012,"isDefault":0,"name":"宋涛","phone":"15678880290","provience":"天津市","userId":624971778},{"addressLine":"dsadsa","city":"天津市","country":"中国","district":"和平区","id":1013,"isDefault":1,"name":"dsadsa","phone":"dasda","provience":"天津市","userId":624971778}]
- GET 请求:
-
新增地址:
- GET 请求:
http://book.musecloud.tech/?addressId=&provience=%E9%BB%91%E9%BE%99%E6%B1%9F%E7%9C%81&city=%E5%93%88%E5%B0%94%E6%BB%A8%E5%B8%82&district=%E4%BA%94%E5%B8%B8%E5%B8%82&address_line=%E4%BA%94%E5%B8%B8%E9%95%87%E5%B9%BF%E5%9C%BA%E5%B0%8F%E5%8C%BA&phone=12345678&isdefault=1&name=%E5%AE%8B%E6%B6%9B
- GET 请求:
-
提交订单:
- GET 请求:
http://book.musecloud.tech/submitorder?addressId=1013&paymentMethod=支付宝 - 返回数据格式:["https://qr.alipay.com/bax00504ukzmhjvoztnv0088",178812488]
- GET 请求:
-
查询订单状态:
- GET 请求:
http://book.musecloud.tech/order/queryOrderStatus?orderSn=178812488 - 返回数据格式:查询返回该订单支付成功/失败/被关闭
- GET 请求:
ApiService 代码:
// 提交订单
static Future<String> submitOrder(int addressId, String paymentMethod) async {
try {
Response response = await dioWithCookie.get(
'$baseUrl/submitorder',
queryParameters: {
'addressId': addressId,
'paymentMethod': paymentMethod,
},
);
String result = response.data;
return result;
} catch (e) {
throw e;
}
}
注意:
your_app_name请替换为你的应用名称。dioWithCookie是你的网络请求库实例。baseUrl是你的 API 接口地址。- 代码中的
// TODO部分需要根据实际情况进行补充。
本教程仅提供了一个简单的结算页面开发示例,你可以根据自己的需求进行扩展和修改。
原文地址: https://www.cveoy.top/t/topic/oi40 著作权归作者所有。请勿转载和采集!