文章目录
微信支付
支付流程
- 1.先下单,获取商品订单号orderId
- 2.拿到orderId去请求微信支付参数
- appId
- 微信AppId
- partnerId
- 商户ID
- prepayId
- 预支付Id
- nonceStr
- 随机字符串
- timestamp
- 支付当前时间戳
- packageValue
- 签名包
- sign
- 签名
- signType
- 签名类型
- appId
- 3.App端吊起微信支付并监听支付结果并展示
- 4.拿到支付结果后跳转到订单详情或我的订单展示支付结果
支付配置
依赖配置
# 微信SDK Share:https://tanggongfanghos.com.cn/.well-known/apple-app-site-association
fluwx: ^3.6.1+4
源码
import 'package:fluwx/fluwx.dart' as fluwx;
/// 微信支付
static void wxPay() async{
bool installed = await fluwx.isWeChatInstalled;
if (!installed) {
// 未安装微信,请前去下载
String name = Platform.isIOS ? "AppStore":"应用商店";
Toast.show("您未安装微信,请前往$name下载~");
return;
}
try {
WeChatPayModel weChatPayParams =
WeChatPayModel(
Config.WX_APPID,
"partnerId",
"prepayId",
"nonceStr",
DateUtil.currentTimeMillis(),
"package",
"sign",
"signType",
);
if (weChatPayParams != null) {
fluwx.payWithWeChat(
appId: weChatPayParams.appId,
partnerId: weChatPayParams.partnerId,
prepayId: weChatPayParams.prepayId,
packageValue: weChatPayParams.package,
nonceStr: weChatPayParams.nonceStr,
timeStamp: weChatPayParams.timestamp,
sign: weChatPayParams.sign,
);
// 监听支付结果
fluwx.weChatResponseEventHandler
.listen((event) async {
print(event.errCode);
// 支付成功
if (event.errCode == 0) {
Toast.show('微信支付成功~');
} else {
Toast.show('微信支付失败~');
}
// 关闭弹窗
});
}
} catch (e) {
Toast.show("吊起微信失败~${e.toString()}");
}
}
支付宝支付
准备
- 1.申请支付宝企业账号
- 2.创建App应用并添加App能力,绑定App
- 3.设置接口加密方式(公钥/秘钥)
- 4.开始审核,审核成功即可(1天之内)
支付流程
- 1.先下单,传入商品id、规格、商品数量进行下单,拿到订单号orderId
- 2.拿到orderId去请求支付宝支付参数及签名
- app_id
- 支付宝AppId
- biz_content
- 商品信息
- 商品id
- 商品数量
- 交易订单号
- out_trade_no
- 商品信息
- charset
- utf-8
- method
- alipay.trade.app.pay
- timestamp
- 支付当前时间戳
- version
- 1.0
- sign_type
- 签名类型:RSA2
- app_id
- 3.App端吊起支付宝支付并监听支付结果并展示
- 4.拿到支付结果后跳转到订单详情或我的订单展示支付结果
支付配置
依赖配置
# AliPay支付宝支付插件 https://github.com/RxReader/alipay_kit
#alipay_kit: ^2.0.0
alipay_kit:
path: ./alipay_kit/
源码
import 'package:alipay_kit/alipay_kit.dart';
static StreamSubscription<AlipayResp>? _paySubs;
/// 支付宝支付
static void aliPay() async{
bool isAliPayInstalled = await Alipay.instance.isInstalled();
if (!isAliPayInstalled){
String name = Platform.isIOS ? "AppStore":"应用商店";
Toast.show("您未安装支付宝,请前往$name下载~");
return;
}
//支付宝支付调试
final Map<String, dynamic> bizContent = <String, dynamic>{
'timeout_express': '30m',
'product_code': 'QUICK_MSECURITY_PAY',
'total_amount': '0.01',
'subject': '1',
'body': '我是测试数据',
'out_trade_no': '123456789',
};
final Map<String, dynamic> orderInfo = <String, dynamic>{
'app_id': '2021003109659746',
'biz_content': json.encode(bizContent),
'charset': 'utf-8',
'method': 'alipay.trade.app.pay',
'timestamp': DateUtil.currentTimeStamp(),
'version': '1.0',
};
Log.d("AliPayInfo>>>>>${orderInfo.toString()}");
final String? charset = orderInfo['charset'] as String?;
final Encoding encoding = Encoding.getByName(charset) ?? utf8;
final Map<String, dynamic> clone = <String, dynamic>{
...orderInfo,
'sign_type': 'RSA2',
};
final String param = Utils.getParams(clone, encoding);
final String sign =
"ZoE2WQV6MXJUJrfdW7+sd2YQ6eeizsHr2i+qEGqseM7RvVpes/XglJ0vFhUlIXM0v8a6puM9uWYoQKLPJQ15182zezcmyMDFOPanofNZb4zIg7Axmv+KEyqqXwMM/ADajwzpHnoPy2cf+46ZBZZOMfvplA6dQ+CkdQz8oMveK7OQakshYu80oAkb9ICH8JTRCZmE3edYTxsUr5eD/T6SVnFBYKC4svXGmSctrkdPqQq9+Jrj+OPHjT8MAodUrBopMUXAPZYeu2ac4XyJI4PYvwdd3uic9YUfkkbZHh61rxT6xS+ygTJ7+N7tNeFtj+4x4rftynO9M08+tYcMdaqYEA==";
Alipay.instance.pay(
orderInfo:
'$param&sign=${Uri.encodeQueryComponent(sign, encoding: encoding)}');
_paySubs = Alipay.instance.payResp().listen((AlipayResp resp) {
final String content = 'pay: ${resp.resultStatus} - ${resp.result}';
if (resp.resultStatus == 9000){
Toast.show("支付宝支付成功~");
}else {
Toast.show("支付宝支付失败~");
}
Log.d('支付${content}');
});
}
苹果支付
支付流程
0.内购初始化
缺少产品ID列表,创建支付前先从苹果后台创建商品
- 1.先下单,拿到订单Id
- 2.IAP支付前通过订单Id获取支付参数
- 3.调用Api吊起苹果支付
- 4.拿到支付结果后通知服务端校验数据有效性(Noti)
- 'receipt-data': productItem.transactionReceipt
- 重试机制:5次,服务端还未收到则退出
- 结束该笔交易,否则无法生成新的交易
- 5.错误日志上报及漏单处理
配置内购环境
1.第一次注册需申请商户ID和证书
https://www.jianshu.com/p/39f5f87b0932
2.协议、税务和银行业务信息配置
按要求录入账户银行卡信息和相关用户信息
CNAPS代码获取:
https://e.czbank.com/CORPORBANK/QYUK
设置税务
https://www.jianshu.com/p/134b506a27e9
等待处理
审核完成
3.根据项目需求选择适合的内购类型
消耗型项目
只可使用一次的产品,使用之后即失效,必须再次购买。
示例:钓鱼 App 中的鱼食。非消耗型项目
只需购买一次,不会过期或随着使用而减少的产品。
示例:游戏 App 的赛道。自动续期订阅
允许用户在固定时间段内购买动态内容的产品。除非用户选择取消,否则此类订阅会自动续期。
示例:每月订阅提供流媒体服务的 App。非续期订阅
允许用户购买有时限性服务的产品。此 App 内购买项目的内容可以是静态的。此类订阅不会自动续期。
示例:为期一年的已归档文章目录订阅。
4.添加内购商品信息录入相应的产品内购信息
如:名称、ID、价格、商品审核截图
App 内购买项目的截屏,即所售项目的示意图。例如,如果 App 内购买项目是一本图书,您可以提交图书的截屏。您也可以提交购买页的截屏。该截屏仅用于 Apple 审核,不会在 App Store 中显示。
截屏要求如下:
iOS 至少需要 640 x 920 像素
App 审核图像上传后,可以替换,但无法移除。当您的 App 内购买项目处于审核中时,您无法更新截屏。
- 点按“存储”或“提交以供审核”。提交审核前需要上传购买界面截图,供苹果审核
注意:若出现无效的商品ID
则需要提交新的版本,最好选择手动发布,因为本次提交只是为了让创建的内购项目ID生效,项目中可以没有关于内购的逻辑代码
5.沙盒账号创建及使用注意事项
沙盒账号创建
https://appstoreconnect.apple.com/access/testers
注意📢
- 电子邮件不能是别人已经注册过AppleID的邮箱
- App Store 地区不要乱选。弹出的购买提示框会根据当前AppleID(沙盒账号)的地区显示语言。
沙箱账号怎么登录不成功
沙箱账号是不能直接在App Store进行登录的,只能在点击了购买商品之后,在弹出的登录框进行登录
验证是否已登录沙箱测试账号:
设置--iTunes Store与App Store,页面拉到最底部,会看到沙箱账户项会列出你已登录的沙箱测试账号!沙盒账号使用流程
必须真机测试!!!
- 1.在iPhone上安装测试包(必须是adhoc签名证书或者develop签名证书打的包,不能是从App Store上下载的)
- 2.退出iPhone的App Store账号(因为我们需要使用沙盒账号登录)。
操作方法一:打开App Store应用首页滑到最下方--选中AppleID--注销
操作方法二:设置--iTunes Store与App Store--选中AppleID--注销
6.Xcode Capabilities里面打开In-App Purchase功能
接入项目
依赖配置
# 支付代码测试
iap_pay:
git:
url: https://gitee.com/Steven_Hu/iap_pay.git
ref: master
伪代码展示
//TODO:IAP第一步 下单
await PairDao.enrollPay(stateId, couponId: 0, paymentChannel: 1);
//TODO:IAP第二步 获取支付参数
var r = await IapDao.getPayParams(orderId: orderId);
//TODO:IAP第三步 IAP支付
int pId = r.data['params']['apple_product_id'];
await InAppPurchase().requestPurchase(productId: '${pId}', orderId: orderId);
//TODO:IAP第四步: 发送给服务端验证数据有效性
IapPay.purchaseUpdated!.listen((PurchasedItem productItem) async {
this.saveReceipt(
transactionReceipt: productItem.transactionReceipt ?? "",
);
this.notiServer(
transactionReceipt: productItem.transactionReceipt ?? "",
complete: () {
this.count = 0;
this.time = 0;
this.removeReceipt();
finishTransition(productItem);
if (success != null) {
success(productItem);
this.end();
}
},
);
}
//TODO:IAP第五步:错误日志上报
IapDao.reportPayException(
orderId: '${this.orderId}',
errCode: purchaseError.code ?? "",
message: mesage,
status: purchaseError.responseCode ?? 0,
);
项目使用
/// 苹果内购
static void iapPay(BuildContext context) async {
// 查看是否能进行苹果内购
var result = await IapPay.instance.check;
print('CanInAppPurchase============: $result');
if (result == "true") {
await IapDao.instance.config(context);
try {
List<IAPItem> item = await IapPay.instance.getProducts(["10001"]);
Log.d("IAPItem>>>>>>>>>>>${item.first.toJson()}");
Future.delayed(Duration(seconds: 3)).then((_) async {
if (item.length > 0) {
IapDao.instance.iapPay(context: context);
}
});
} catch (e) {
Log.d("IAP-ERROR>>>>>>>>>>>${e.toString()}");
}
} else {
IapPay.showLoading("CanPay:${result}");
}
}
吊起支付效果图
彩蛋~
苹果内购Flutter 2.0空安全正在调试中,上线后会通知大家~请大家多多支持