活动地址:CSDN21天学习挑战赛
安装flutter插件
fluwx: ^3.8.5 #微信
注册微信接口
_initfluwx() async {
print('789879797987979');
//7ca7229f15fb67f76aa529b98234139f
await fluwx
.registerWxApi(
appId: "自己的id",
doOnAndroid: true,
doOnIOS: true,
universalLink: '',
)
.then((value) {
print(value);
print('-----------------------');
});
}
调用方法
static Future<bool> payWechat(price) async {
if(price == null )return false;
bool isInstalled = await fluwx.isWeChatInstalled;
if (!isInstalled) {
ToastUtils.showToast("请先安装微信");
return false;
}
// commonViewModel.sealPrice
Map<String, dynamic> map = {'amount':price};
Map data;
{
//此处可以进行后端接口请求
if (data != null && data.data['code'] == 0) {
data = data.data['data'];
var result = await fluwx.payWithWeChat(
appId: data['appId'].toString(),
partnerId: '自己的id',
prepayId: data['prepayId'].toString(),
packageValue: data['package'].toString(),
nonceStr: data['nonceStr'].toString(),
timeStamp: int.parse(data['timeStamp']),
sign: data['paySign'].toString(),
);
return result;
}
Future.delayed(Duration.zero,(){
});
print('-------------------------------------------------------------------$data');
return false;
// 应用程序后台地址
}
监听微信支付事件
payListen = fluwx.weChatResponseEventHandler.listen((event) {
//监听调起
if (event.errCode == 0) {//event.isSuccessful
print("监听支付调起成功");
saveSeal();
} else {
ToastUtils.showToast(event.errStr ?? "微信支付失败");
return ;//写或不写都行
}
});
事件结束时关闭微信消息订阅
StreamSubscription _wxPay;
void wxSubscriptionClose() => _wxPay?.cancel();
_wxPay?.cancel();
// 支付回调
_wxPay = fluwx.weChatResponseEventHandler.listen((event) {
_wxPay?.cancel();
if (event is fluwx.WeChatPaymentResponse) {
if (event.isSuccessful) {
return onSuccess?.call();
} else {
return onError?.call(event.errCode == -1 ? '系统错误,请联系管理员' : '您取消了支付');
}
}
});
出现两次回调,是由于没有注销监听产生的
代码示例
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:fluwx/fluwx.dart' as fluwx;
class WechatPayment {
StreamSubscription _wxPay;
/// 关闭微信消息订阅
void wxSubscriptionClose() => _wxPay?.cancel();
/// 调起微信支付面板
/// 这里的WxPayModel是业务层的数据,即后台返回的有关微信支付订单的信息
void wxPay(WxPayModel wxPayModel, {VoidCallback onWxPaying, VoidCallback onSuccess, Function(String data) onError}) async {
// 跳转微信支付前,告诉页面进入微信支付,页面层可以做一些关闭加载框等的操作
onWxPaying?.call();
// 一些异常情况的处理
if (!await fluwx.isWeChatInstalled) return onError?.call('请安装微信完成支付或使用苹果手机支付');
if (wxPayModel.appId != Config.WX_APP_ID) return onError?.call('AppID不一致,请联系管理员');
// 此方法笔者没有做单例,因此支付前尝试注销监听,避免重复回调
_wxPay?.cancel();
// 支付回调
_wxPay = fluwx.weChatResponseEventHandler.listen((event) {
_wxPay?.cancel();
if (event is fluwx.WeChatPaymentResponse) {
if (event.isSuccessful) {
return onSuccess?.call();
} else {
return onError?.call(event.errCode == -1 ? '系统错误,请联系管理员' : '您取消了支付');
}
}
});
// 发起支付
fluwx.payWithWeChat(
appId: wxPayModel.appId,
partnerId: wxPayModel.partnerId,
prepayId: wxPayModel.prepayId,
packageValue: wxPayModel.packageValue,
nonceStr: wxPayModel.nonceStr,
timeStamp: wxPayModel.timeStamp,
sign: wxPayModel.sign,
signType: wxPayModel.signType,
extData: wxPayModel.extData,
);
}
}
WechatPayment paymentUtils = new WechatPayment();
paymentUtils.wxPay(
state.model.wxPayModel,
onError: (String err) {
if (!mounted) return;
// 微信支付错误,设置支付状态为false,弹框即可
_isPaying = false;
SchedulerBinding.instance.addPostFrameCallback((_) {
CommonUtils.showToast(err, backgroundColor: Theme.of(context).errorColor);
});
},
onSuccess:(){
_isPaying = true;
},
onWxPaying: () {
// 启动微信支付,设置支付状态为true,关闭加载框
_isPaying = true;
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.pop(context);
});
},
);
但是需要注意,微信的回调是异步的,并且有很多种情况是接收不到回调的,以下是确定收不到会调的情况。
现在主流的做法是再支付页面监听app的生命周期,即由后台切回前台的时候,检测下状态,若还在支付中,直接进入查询结果页面,由后台去检验订单,拿到结果显示即可。(后台主动查询理论上还是存在微信服务端延时的问题,因此后台进行查询的时候,建议采取轮询机制,若是没有支付成功的话,延时5秒后再确认下更保险)
class _XXXPageState extends State<XXXPage> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this); //添加观察者
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this); //销毁观察者
super.dispose();
}
/// 应用状态监听
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
{
if (Platform.isAndroid && _isPaying) {
_isPaying = false;
// 监听到时安卓设备并且支付还在进行中,程序员要根据业务做一下处理
break;
}
default:
break;
}
super.didChangeAppLifecycleState(state);
}
}