【原创 附源码】Flutter集成Apple支付详细流程(附源码)

最近有时间,特意整理了一下之前使用过的Flutter平台的海外支付,附源码及demo可供参考

这篇文章只记录Apple支付的详细流程,其他相关Flutter文章链接如下:

【原创 附源码】Flutter集成谷歌支付详细流程(附源码)

【原创 附源码】Flutter安卓及iOS海外登录--Google登录最详细流程

【原创 附源码】Flutter安卓及iOS海外登录--Tiktok登录最详细流程

【原创 附源码】Flutter安卓及iOS海外登录--Facebook登录最详细流程

【原创 附源码】Flutter安卓及iOS海外登录--Apple登录最详细流程

让我们开始吧

一 Apple开发者平台添加内购商品

首先使用苹果开发者账户登录苹果开发者平台

Sign In - Apple

点击【App】 

 

添加新的苹果内购商品

 

添加的时候页面的指引很清晰,就不赘述了,苹果添加内购商品比较简单,加完就可以了。

然后去创建沙盒账户用来做苹果支付测试,回到首页,点击【用户和访问】

点击沙盒,然后添加一个苹果测试账户,这个账户可以是个假的邮箱,不需要是正式的Apple id,比如你可以设置为88888@qq.com类似之类的账户

 

添加完点击创建即可

二 flutter 代码集成

使用到的第三方插件:

in_app_purchase: ^3.1.5

插件官网地址:in_app_purchase | Flutter package

将插件添加至yaml文件,然后执行flutter pub get

执行完了记得去IOS和安卓端分别执行pod install 和 gradle sync同步一下第三方插件

然后在项目中新建dart文件,命名为:BuyEngine.dart

然后将以下代码放入:

import 'dart:async';
import 'dart:io';import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';
import 'package:in_app_purchase_android/in_app_purchase_android.dart';class BuyEngin{StreamSubscription<List<PurchaseDetails>> _subscription;InAppPurchase _inAppPurchase;List<ProductDetails> _products; //内购的商品对象集合//初始化购买组件void initializeInAppPurchase() {// 初始化in_app_purchase插件_inAppPurchase = InAppPurchase.instance;//监听购买的事件final Stream<List<PurchaseDetails>> purchaseUpdated = _inAppPurchase.purchaseStream;_subscription = purchaseUpdated.listen((purchaseDetailsList) {_listenToPurchaseUpdated(purchaseDetailsList);}, onDone: () {_subscription.cancel();}, onError: (error) {error.printError();print("购买失败了");});}void resumePurchase(){_inAppPurchase.restorePurchases();}/// 加载全部的商品void buyProduct(String productId) async {print("请求商品id " + productId);List<String> _outProducts = [productId];final bool available = await _inAppPurchase.isAvailable();if (!available) {// ToastUtil.showToast("无法连接到商店");print("无法连接到商店");return;}//开始购买// ToastUtil.showToast("连接成功-开始查询全部商品");print("连接成功-开始查询全部商品");List<String> _kIds = _outProducts;final ProductDetailsResponse response = await _inAppPurchase.queryProductDetails(_kIds.toSet());print("商品获取结果  " + response.productDetails.toString());if (response.notFoundIDs.isNotEmpty) {// ToastUtil.showToast("无法找到指定的商品");print("无法找到指定的商品");// ToastUtil.showToast("无法找到指定的商品 数量 " + response.productDetails.length.toString());return;}// 处理查询到的商品列表List<ProductDetails> products = response.productDetails;print("products ==== " + products.length.toString());if (products.isNotEmpty) {//赋值内购商品集合_products = products;}print("全部商品加载完成了,可以启动购买了,总共商品数量为:${products.length}");//先恢复可重复购买// await _inAppPurchase. ();startPurchase(productId);}// 调用此函数以启动购买过程void startPurchase(String productId) async {print("购买的商品id为" + productId);if (_products != null && _products.isNotEmpty) {// ToastUtil.showToast("准备开始启动购买流程");try {ProductDetails productDetails = _getProduct(productId);print("一切正常,开始购买,信息如下:title: ${productDetails.title}  desc:${productDetails.description} ""price:${productDetails.price}  currencyCode:${productDetails.currencyCode}  currencySymbol:${productDetails.currencySymbol}");_inAppPurchase.buyConsumable(purchaseParam: PurchaseParam(productDetails: productDetails));} catch (e) {e.printError();print("购买失败了");}} else {print("当前没有商品无法调用购买逻辑");}}// 根据产品ID获取产品信息ProductDetails _getProduct(String productId) {return _products.firstWhere((product) => product.id == productId);}/// 内购的购买更新监听void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) async {for (PurchaseDetails purchase in purchaseDetailsList) {if (purchase.status == PurchaseStatus.pending) {// 等待支付完成_handlePending();} else if (purchase.status == PurchaseStatus.canceled) {// 取消支付_handleCancel(purchase);} else if (purchase.status == PurchaseStatus.error) {// 购买失败_handleError(purchase.error);} else if (purchase.status == PurchaseStatus.purchased || purchase.status == PurchaseStatus.restored) {// ToastUtil.showToast(DataConfig.getShowName("Pay_Success_Tip"));//完成购买, 到服务器验证if (Platform.isAndroid) {var googleDetail = purchase as GooglePlayPurchaseDetails;checkAndroidPayInfo(googleDetail);} else if (Platform.isIOS) {var appstoreDetail = purchase as AppStorePurchaseDetails;checkApplePayInfo(appstoreDetail);}}}}/// 购买失败void _handleError(IAPError iapError) {// ToastUtil.showToast("${DataConfig.getShowName("Purchase_Failed")}:${iapError?.code} message${iapError?.message}");}/// 等待支付void _handlePending() {print("等待支付");}/// 取消支付void _handleCancel(PurchaseDetails purchase) {_inAppPurchase.completePurchase(purchase);}/// Android支付成功的校验void checkAndroidPayInfo(GooglePlayPurchaseDetails googleDetail) async {_inAppPurchase.completePurchase(googleDetail);print("安卓支付交易ID为" + googleDetail.purchaseID);print("安卓支付验证收据为" + googleDetail.verificationData.serverVerificationData);}/// Apple支付成功的校验void  checkApplePayInfo(AppStorePurchaseDetails appstoreDetail) async {_inAppPurchase.completePurchase(appstoreDetail);print("Apple支付交易ID为" + appstoreDetail.purchaseID);print("Apple支付验证收据为" + appstoreDetail.verificationData.serverVerificationData);}@overridevoid onClose() {if (Platform.isIOS) {final InAppPurchaseStoreKitPlatformAddition iosPlatformAddition =_inAppPurchase.getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();iosPlatformAddition.setDelegate(null);}_subscription.cancel();}}

至此集成完毕,开始测试苹果支付

三 支付测试 

在调用苹果支付的地方提前初始化购买插件:

BuyEngin _buyEngin = BuyEngin();
_buyEngin.initializeInAppPurchase();

然后调用即可:

_buyEngin.buyProduct("应用内商品ID");

应用内商品ID就是你在APP Store Connect配置的应用内购买商品的product ID

如果一切正常,则会正常唤醒苹果支付(记得是在科学上网的环境下测试)

源码地址:GitHub - TheRuningAnt/FGTALogin: 使用Flutter 去集成海外平台第三方登录,包含Google、Tiktok、Facebook、Apple登录 

(注:直接调用该demo的苹果支付无法支付成功,因为该demo使用的bundle ID是测试ID,并未正式上线,但是功能是经过使用真实上线的bundle ID支付验证过的,如需使用该demo进行苹果支付测试,可将IOS工程下的bundlle ID替换为你自己的包名然后进行测试)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/469858.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端高频面试题--虚拟DOM篇】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;前端高频面试题 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac;前端高频面试题--虚拟DOM篇 虚拟DOM的理解虚拟DOM的解析过程为什么要用虚拟DOM虚拟DOM与真实DOM的…

Phobos捆绑某数控软件AdobeIPCBroker组件定向勒索

前言 Phobos勒索病毒最早于2019年被首次发现并开始流行起来&#xff0c;该勒索病毒的勒索提示信息特征与CrySiS(Dharma)勒索病毒非常相似&#xff0c;但是两款勒索病毒的代码特征却是完全不一样&#xff0c;近日笔者在逛某开源恶意软件沙箱的时候发现了一款Phobos勒索病毒捆绑…

FreeRTOS 调度算法简述

优先级抢占式调度 本章的示例程序已经演示了 FreeRTOS 在什么时候以及以什么方式选择一个什么 样的任务来执行。  每个任务都赋予了一个优先级。  每个任务都可以存在于一个或多个状态。  在任何时候都只有一个任务可以处于运行状态。  调度器总是在所有处于就…

计算机毕业设计分享-SSM实验室耗材管理系统 13205(赠送源码数据库)JAVA、PHP,node.js,C++、python,大屏数据可视化等

SSM实验室耗材管理系统 摘 要 本课题研究的实验室耗材管理系统&#xff0c;主要功能模块包括用户管理、耗材管理、入库记录、出库记录、报废登记、供应商管理、耗材类别、实验室管理等&#xff0c;采取面对对象的开发模式进行软件的开发和硬体的架设&#xff0c;能很好的满足实…

【STM32 CubeMX】学STM必会的数据结构——环形缓冲区

文章目录 前言一、环形缓冲区是什么二、实现环形缓冲区实现分析2.1 环形缓冲区初始化2.2 写buf2.3 读buf2.4 测试 三、代码总况总结 前言 在嵌入式系统开发中&#xff0c;经常需要处理数据的缓存和传输&#xff0c;而环形缓冲区是一种常见且有效的数据结构&#xff0c;特别适用…

Codeforces Round 925 (Div. 3)

A. Recovering a Small String&#xff08;枚举&#xff09; 思路 每次枚举每一位 #include <iostream> using namespace std;int main() {int t;cin >> t;for (int i 0; i < t; i) {int n;cin >> n;if(n < 28){cout<<"aa"<<…

Rust 数据结构与算法:3栈:用栈实现符号匹配

1、符号匹配 如: (5+6)(7+8)/(4+3)、{ { ( [ ] [ ])}}、(a+b)(c*d)func() 等各类语句的符号匹配。 这里我们关注的不是数字而是括号,因为括号更改了操作优先级,限定了语言的语义,这是非常重要的。如果括号不完整,那么整个表达式就是错的。 括号都必须以成对匹配的形式出…

「数据结构」MapSet

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;Java数据结构 &#x1f387;欢迎点赞收藏加关注哦&#xff01; Map&Set &#x1f349;概念&#x1f349;模型&#x1f349;Map&#x1f34c;TreeMap和HashMap的区别&#x1f34c;Map常用方…

LeetCode.107. 二叉树的层序遍历 II

题目 107. 二叉树的层序遍历 II 分析 这个题目考查的是二叉树的层序遍历&#xff0c;对于二叉树的层序遍历&#xff0c;我们需要借助 队列 这种数据结构。再来回归本题 &#xff0c;我们只需要将 二叉树的层序遍历的结果逆序&#xff0c;就可以得到这道题我们要求的答案了。…

引用的账户当前已锁定,且可能无法登录怎么办

WINDOWS提示引用账户已锁定怎么办&#xff08;补充&#xff09; 一般是多次输错密码的原因&#xff01;等待半个小时就能打开了&#xff01; 这跟手机锁屏被小朋友锁死原理类似&#xff0c;但是Windows不会给你显示具体时间&#xff0c;所以你登录BIOS改系统时间&#xff0c;欺…

102. 二叉树的层序遍历

给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例 2&#xff1a; 输入&…

模型 人货场

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。重在提升认知。连接消费者与商品的桥梁。 1 ”人货场“模型的应用 1.1 以抖音直播电商为背景的人货场应用-小杨哥的带货奇迹 小杨哥&#xff0c;一位知名的抖音主播&#xff0c;以其幽默风趣的直播风…