接入生活缴费支付功能

hmxc
张萌 3 years ago
parent 9f25d105c6
commit fd66b06c7e

@ -21,6 +21,7 @@ class API {
static _Market market = _Market(); static _Market market = _Market();
static _News news = _News(); static _News news = _News();
static _Search search = _Search(); static _Search search = _Search();
static _Pay pay = _Pay();
} }
class _Login { class _Login {
@ -419,3 +420,11 @@ class _Facility {
String get detailType => String get detailType =>
'/user/facilitiesAppointment/findFacilitiesByCategoryId'; '/user/facilitiesAppointment/findFacilitiesByCategoryId';
} }
class _Pay {
///
String get dailyPayMentAliPay => '/user/alipay/dailyPaymentAlipay';
///
String get dailPayMentCheck => '/user/alipay/dailyPaymentCheckAlipay';
}

@ -0,0 +1,69 @@
import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
part 'pay_model.g.dart';
@JsonSerializable()
class PayModel extends Equatable {
@JsonKey(name: 'alipay_trade_app_pay_response')
final AliPayTradeAppPayResponse aliPayTradeAppPayResponse;
final String sign;
@JsonKey(name: 'sign_type')
final String signType;
PayModel({
required this.aliPayTradeAppPayResponse,
required this.sign,
required this.signType,
});
factory PayModel.fromJson(Map<String, dynamic> json) =>
_$PayModelFromJson(json);
@override
List<Object> get props => [aliPayTradeAppPayResponse, sign, signType];
}
@JsonSerializable()
class AliPayTradeAppPayResponse extends Equatable {
final String code;
final String msg;
@JsonKey(name: 'app_id')
final String appId;
@JsonKey(name: 'out_trade_no')
final String outTradeNo;
@JsonKey(name: 'trade_no')
final String tradeNo;
@JsonKey(name: 'total_amount')
final String totalAmount;
@JsonKey(name: 'seller_id')
final String sellerId;
final String charset;
final String timestamp;
AliPayTradeAppPayResponse({
required this.code,
required this.msg,
required this.appId,
required this.outTradeNo,
required this.tradeNo,
required this.totalAmount,
required this.sellerId,
required this.charset,
required this.timestamp,
});
factory AliPayTradeAppPayResponse.fromJson(Map<String, dynamic> json) =>
_$AliPayTradeAppPayResponseFromJson(json);
@override
List<Object> get props {
return [
code,
msg,
appId,
outTradeNo,
tradeNo,
totalAmount,
sellerId,
charset,
timestamp,
];
}
}

@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'pay_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
PayModel _$PayModelFromJson(Map<String, dynamic> json) {
return PayModel(
aliPayTradeAppPayResponse: AliPayTradeAppPayResponse.fromJson(
json['alipay_trade_app_pay_response'] as Map<String, dynamic>),
sign: json['sign'] as String,
signType: json['sign_type'] as String,
);
}
AliPayTradeAppPayResponse _$AliPayTradeAppPayResponseFromJson(
Map<String, dynamic> json) {
return AliPayTradeAppPayResponse(
code: json['code'] as String,
msg: json['msg'] as String,
appId: json['app_id'] as String,
outTradeNo: json['out_trade_no'] as String,
tradeNo: json['trade_no'] as String,
totalAmount: json['total_amount'] as String,
sellerId: json['seller_id'] as String,
charset: json['charset'] as String,
timestamp: json['timestamp'] as String,
);
}

@ -1,3 +1,6 @@
import 'package:aku_community/pages/life_pay/pay_util.dart';
import 'package:aku_community/utils/network/base_model.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -17,7 +20,6 @@ import 'package:aku_community/provider/app_provider.dart';
import 'package:aku_community/ui/profile/house/pick_my_house_page.dart'; import 'package:aku_community/ui/profile/house/pick_my_house_page.dart';
import 'package:aku_community/utils/bee_parse.dart'; import 'package:aku_community/utils/bee_parse.dart';
import 'package:aku_community/utils/headers.dart'; import 'package:aku_community/utils/headers.dart';
import 'package:aku_community/utils/network/base_model.dart';
import 'package:aku_community/utils/network/net_util.dart'; import 'package:aku_community/utils/network/net_util.dart';
import 'package:aku_community/widget/bee_divider.dart'; import 'package:aku_community/widget/bee_divider.dart';
import 'package:aku_community/widget/bee_scaffold.dart'; import 'package:aku_community/widget/bee_scaffold.dart';
@ -49,6 +51,7 @@ class _LifePayPageState extends State<LifePayPage> {
bool get allSelect => bool get allSelect =>
((_models.length == _selectYears.length) && (_models.length != 0)); ((_models.length == _selectYears.length) && (_models.length != 0));
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -58,6 +61,7 @@ class _LifePayPageState extends State<LifePayPage> {
@override @override
void dispose() { void dispose() {
_controller?.dispose(); _controller?.dispose();
BotToast.closeAllLoading();
super.dispose(); super.dispose();
} }
@ -140,12 +144,6 @@ class _LifePayPageState extends State<LifePayPage> {
_selectPay[index].ids.forEach((element) { _selectPay[index].ids.forEach((element) {
_ids.remove(element); _ids.remove(element);
}); });
if (_count < 0) {
_count = 0;
}
if (_totalCost < 0) {
_totalCost = 0;
}
} else { } else {
_selectYears.add(index); _selectYears.add(index);
_totalCost += (_selectPay[index].payTotal); _totalCost += (_selectPay[index].payTotal);
@ -187,7 +185,8 @@ class _LifePayPageState extends State<LifePayPage> {
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
children: [ children: [
TextSpan( TextSpan(
text: '¥ ${_selectPay[index].payTotal}', text:
'¥ ${_selectPay[index].payTotal.toStringAsFixed(2)}',
style: TextStyle( style: TextStyle(
color: kDangerColor, color: kDangerColor,
fontSize: 28.sp, fontSize: 28.sp,
@ -201,11 +200,23 @@ class _LifePayPageState extends State<LifePayPage> {
children: [ children: [
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
if (_selectYears.contains(index)) {
_totalCost -= _selectPay[index].payTotal;
_count -= _selectPay[index].payCount;
_selectPay[index].ids.forEach((element) {
_ids.remove(element);
});
}
List payMent = await (Get.to( List payMent = await (Get.to(
() => LifePayDetailPage(model: _models[index]))); () => LifePayDetailPage(model: _models[index])));
_selectPay[index].payCount = payMent[0]; _selectPay[index].payCount = payMent[0];
_selectPay[index].payTotal = payMent[1]; _selectPay[index].payTotal = payMent[1];
_selectPay[index].ids = payMent[2]; _selectPay[index].ids = payMent[2];
if (_selectYears.contains(index)) {
_totalCost += _selectPay[index].payTotal;
_count += _selectPay[index].payCount;
}
setState(() {}); setState(() {});
}, },
child: Container( child: Container(
@ -257,6 +268,58 @@ class _LifePayPageState extends State<LifePayPage> {
return _list; return _list;
} }
_allSelectOption() {
//
if (_models.length == _selectYears.length) {
_selectYears.clear();
_ids.clear();
_totalCost = 0;
_count = 0;
} else {
for (var i = 0; i < _models.length; i++) {
if (!_selectYears.contains(i)) {
_selectYears.add(i);
}
}
_totalCost = 0;
_count = 0;
_ids.clear();
for (var item in _selectPay) {
_totalCost += item.payTotal;
_count += item.payCount;
_ids.addAll(item.ids);
}
}
setState(() {});
}
Widget _payButton() {
return MaterialButton(
elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(37.w)),
color: kPrimaryColor,
padding: EdgeInsets.symmetric(horizontal: 50.w, vertical: 15.w),
onPressed: () async {
Function cancel = BotToast.showLoading();
BaseModel baseModel =
await NetUtil().post('/user/alipay/dailyPaymentAlipay', params: {
"ids": _ids,
"payType": 1, //
"payPrice": _totalCost.toStringAsFixed(2)
});
if (baseModel.status ?? false) {
bool result = await PayUtil()
.callAliPay(baseModel.message!, API.pay.dailPayMentCheck);
if (result) {
Get.off(PayFinishPage());
}
}
cancel();
},
child: '去缴费'.text.black.size(32.sp).bold.make(),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final appProvider = Provider.of<AppProvider>(context); final appProvider = Provider.of<AppProvider>(context);
@ -322,28 +385,7 @@ class _LifePayPageState extends State<LifePayPage> {
children: [ children: [
GestureDetector( GestureDetector(
onTap: () { onTap: () {
// _allSelectOption();
if (_models.length == _selectYears.length) {
_selectYears.clear();
_ids.clear();
_totalCost = 0;
_count = 0;
} else {
for (var i = 0; i < _models.length; i++) {
if (!_selectYears.contains(i)) {
_selectYears.add(i);
}
}
_totalCost = 0;
_count = 0;
_ids.clear();
for (var item in _selectPay) {
_totalCost += item.payTotal;
_count += item.payCount;
_ids.addAll(item.ids);
}
}
setState(() {});
}, },
child: AnimatedContainer( child: AnimatedContainer(
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
@ -379,7 +421,7 @@ class _LifePayPageState extends State<LifePayPage> {
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
children: [ children: [
TextSpan( TextSpan(
text: '$_totalCost', text: _totalCost.toStringAsFixed(2),
style: TextStyle( style: TextStyle(
color: kDangerColor, color: kDangerColor,
fontSize: 32.sp, fontSize: 32.sp,
@ -389,25 +431,7 @@ class _LifePayPageState extends State<LifePayPage> {
], ],
), ),
24.w.widthBox, 24.w.widthBox,
MaterialButton( _payButton(),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(37.w)),
color: kPrimaryColor,
padding: EdgeInsets.symmetric(horizontal: 50.w, vertical: 15.w),
onPressed: () async {
BaseModel baseModel =
await NetUtil().post('/user/dailyPayment/pay', params: {
"ids": _ids,
"payType": 1, //
"payPrice": _totalCost
});
if (baseModel.status ?? false) {
Get.off(() => PayFinishPage());
}
},
child: '去缴费'.text.black.size(32.sp).bold.make(),
),
], ],
), ),
), ),

@ -0,0 +1,96 @@
import 'dart:convert';
import 'package:aku_community/models/pay/pay_model.dart';
import 'package:aku_community/utils/network/net_util.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:dio/dio.dart';
import 'package:power_logger/power_logger.dart';
import 'package:tobias/tobias.dart';
enum PAYTYPE {
///
ALI,
///
WX,
///
CASH,
///pos
POS
}
class PayUtil {
void resultSatus(String status) {
switch (status) {
case '8000':
BotToast.showText(text: '正在处理中');
break;
case '4000':
BotToast.showText(text: '订单支付失败');
break;
case '5000':
BotToast.showText(text: '重复请求');
break;
case '6001':
BotToast.showText(text: ' 用户中途取消');
break;
case '6002':
BotToast.showText(text: '网络连接出错');
break;
case '6004':
BotToast.showText(text: '支付结果未知,请查询商户订单列表中订单的支付状态');
break;
default:
BotToast.showText(text: '其他支付错误');
break;
}
}
String _resultStatus = '';
///
Future<bool> callAliPay(String order, String path) async {
Map<dynamic, dynamic> result = await aliPay(order);
_resultStatus = result['resultStatus'];
if (_resultStatus == '9000') {
String _res = result['result'];
PayModel _model = PayModel.fromJson(jsonDecode(_res));
bool _confirmResult = await _confirmPayResult(
path, _model.aliPayTradeAppPayResponse.outTradeNo);
return _confirmResult;
} else {
resultSatus(_resultStatus);
return false;
}
}
Future<bool> _confirmPayResult(String path, String code) async {
try {
int status = 0;
for (var i = 0; i < 3; i++) {
await Future.delayed(Duration(milliseconds: 1000), () async {
Response response = await NetUtil().dio!.get(path, queryParameters: {
"code": code,
});
status = response.data['status'] as int;
});
if (status == 2) {
break;
}
}
if (status == 2) {
BotToast.showText(text: '交易成功');
return true;
} else {
BotToast.showText(text: '交易失败 错误码${status}');
return false;
}
} catch (e) {
BotToast.showText(text: '网络请求错误');
LoggerData.addData(e);
return false;
}
}
}

@ -236,7 +236,7 @@ class _LifePayDetailPageState extends State<LifePayDetailPage> {
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
children: [ children: [
TextSpan( TextSpan(
text: '$_payTotal', text: '${_payTotal.toStringAsFixed(2)}',
style: TextStyle( style: TextStyle(
color: kDangerColor, color: kDangerColor,
fontSize: 32.sp, fontSize: 32.sp,

@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import 'package:flustars/flustars.dart'; import 'package:flustars/flustars.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jpush_flutter/jpush_flutter.dart'; import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:power_logger/power_logger.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:aku_community/constants/api.dart'; import 'package:aku_community/constants/api.dart';
@ -52,7 +53,11 @@ class UserProvider extends ChangeNotifier {
Future updateProfile() async { Future updateProfile() async {
_userInfoModel = await SignFunc.getUserInfo(); _userInfoModel = await SignFunc.getUserInfo();
if (_userInfoModel != null && !kIsWeb && !Platform.isMacOS) { if (_userInfoModel != null && !kIsWeb && !Platform.isMacOS) {
await JPush().setAlias(_userInfoModel?.id.toString() ?? ''); try {
await JPush().setAlias(_userInfoModel!.id.toString());
} catch (e) {
LoggerData.addData(e);
}
} }
notifyListeners(); notifyListeners();
} }

@ -46,8 +46,7 @@ class _HomeNotificationState extends State<HomeNotification> {
.toList(), .toList(),
repeatForever: true, repeatForever: true,
), ),
), ).expand(),
Spacer(),
MaterialButton( MaterialButton(
shape: StadiumBorder(), shape: StadiumBorder(),
padding: EdgeInsets.symmetric(horizontal: 12.w), padding: EdgeInsets.symmetric(horizontal: 12.w),

@ -81,7 +81,6 @@ class _GoodsOrderDetailPageState extends State<GoodsOrderDetailPage> {
), ),
bottomNavi: BottomButton( bottomNavi: BottomButton(
onPressed: () async { onPressed: () async {
final cancel = BotToast.showLoading(); final cancel = BotToast.showLoading();
BaseModel baseModel = await NetUtil().post( BaseModel baseModel = await NetUtil().post(
API.market.appointment, API.market.appointment,

@ -13,7 +13,7 @@ class HouseFunc {
} }
/// ///
static Future get passedHouses async{ static Future<List<PassedHouseListModel>> get passedHouses async{
BaseModel model = await NetUtil().get(API.user.passedHouseList); BaseModel model = await NetUtil().get(API.user.passedHouseList);
if (!model.status!) return []; if (!model.status!) return [];
return (model.data as List).map((e) => PassedHouseListModel.fromJson(e)).toList(); return (model.data as List).map((e) => PassedHouseListModel.fromJson(e)).toList();

@ -1061,6 +1061,13 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
tobias:
dependency: "direct main"
description:
name: tobias
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:

@ -37,6 +37,9 @@ dependencies:
#用户存储路径 #用户存储路径
path_provider: ^2.0.1 path_provider: ^2.0.1
#支付宝支付功能
tobias: ^2.1.0
#微信支付
fluwx: ^3.4.2 fluwx: ^3.4.2
get: ^4.1.4 get: ^4.1.4
velocity_x: ^3.0.0 velocity_x: ^3.0.0

@ -41,3 +41,9 @@ void gen() async {
arguments: ['build'], arguments: ['build'],
); );
} }
@Task('build runner clean')
void genClean() async {
await Pub.runAsync('build_runner',
arguments: ['build', '--delete-conflicting-outputs']);
}

Loading…
Cancel
Save