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

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

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

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

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

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

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

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

让我们开始吧

一 google平台配置

首先进入谷歌开发者平台(记得科学上网)

https://developers.google.com/?hl=zh-cn

进入开发者平台之后,点击google play,创建我们的APP

点击登录管理中心

创建完我们的APP之后,就可以开始配置支付的功能。需要注意的是,在进行谷歌支付测试的时候,需要先提交一个封闭测试版本及以上等级(例如公开版本)的包,然后才可以去创建应用内支付的商品,等这个包提交审核通过之后才可以开始进行谷歌支付的测试。

点击创建轨道

点击创建新的发布版本

签名选择Google管理签名,然后上传aab格式的release版本的包,aab版本的包在这里生成
点开Build,选择Generate Signed Bundle/APK

 然后选择app bundle

然后一路next,最后选择release版本,然后finish

然后在输出控制台的build选项卡,即可找到刚刚打出来的aab包

然后上传就可以了。

上传完成之后,此时就可以配置应用内商品了,点击这里进行添加配置:

添加完成后记得激活,不然即使审核通过之后测试的时候也获取不到该商品

点击这里激活商品

这个时候商品的配置就完成了。

接下来添加测试账户,进入封闭测试页面,切换到【测试用户选项卡】,然后创建测试群组,在群组里添加测试人员账户即可

当你的APP审核通过之后,这个页面下方的测试人员参与方式便会生效,如下所示:

就可以将这些链接发给测试人员,让他们去安装进行测试购买。

最后修改一下测试政策状态

选中测试群组,然后将政策状态改为LICENSED

OK,配置完成

二 flutter 代码集成

使用到的第三方插件:

in_app_purchase: ^3.1.5

插件官网地址:https://pub.dev/packages/in_app_purchase

将插件添加至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就是你在google开发者中心配置的应用内购买商品的product ID

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

支付完成后可以看到可以正常获取到交易的ID和交易的验证收据,为了避免被第三方恶意刷购买接口来进行非法购买,建议将该收据上传后端服务器进行验证,验证通过之后再去更新用户的购买信息

Ok ,集成完毕,功德+1
源码地址: GitHub - TheRuningAnt/FGTALogin: 使用Flutter 去集成海外平台第三方登录,包含Google、Tiktok、Facebook、Apple登录 
(注:直接调用该demo的谷歌支付无法支付成功,因为该demo使用的安卓包名是测试包名,并未正式上线,但是功能是经过使用真实上线的包名支付验证过的,如上截图所示。如需使用该demo进行谷歌支付测试,可将安卓包名替换为你自己的审核通过的包名然后进行测试)

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

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

相关文章

【大数据Hive】hive 表设计常用优化策略

目录 一、前言 二、hive 普通表查询原理 2.1 操作演示说明 2.1.1 创建一张表&#xff0c;并加载数据 2.1.2 统计3月24号的登录人数 2.1.3 查询原理过程总结 2.2 普通表结构带来的问题 三、hive分区表设计 3.1 区表结构 - 分区设计思想 3.2 操作演示 3.2.1 创建分区表…

解决MAC连上wifi或热点却不能上网问题

解决MAC连上wifi或热点却不能上网问题 #新换的mac昨天还能连上wifi&#xff0c;今天就不好使了。 找到连接的wifi点击详细信息&#xff0c;选择TCP/IP 中的配置IPV4 选择关闭

独孤思维:绝版书副业又优化了

做副业&#xff0c;不光要低头干活&#xff0c;还要抬头看路。 我做绝版书那会&#xff0c;实操的心得和经验会分享给学员。 学员实操久了&#xff0c;就会在自己实操的过程中&#xff0c;总结自己的经验。 有些经验&#xff0c;比独孤的还好。 比如上周&#xff0c;群里有…

Python Matplotlib 的学习笔记

Python Matplotlib 的学习笔记 0. Python Matplotlib 简介1. 为什么要用 Matplotlib&#xff1f;2. Matplotlib 基础类详解2-1. Line&#xff08;线&#xff09;2-2. Marker&#xff08;标记&#xff09;2-3. Text&#xff08;文本&#xff09;2-4. Legend&#xff08;图例&…

Vue3-01

Vue.js &#xff08;通常简称为 Vue&#xff09;是一套用于构建用户界面的渐进式框架。与其他框架不同的是&#xff0c;Vue采用了自底向上增量开发的设计。Vue的核心库只关注视图层&#xff0c;并且非常容易与现有项目集成。Vue也完全支持通过插件的方式进行扩展。Vue的设计理念…

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第二天-arm ads下的start.S分析(物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1E4x2TX_9SYhxM9sWfnehMg?pwd1688 提取码&#xff1a;1688 ; ; NAME: 2440INIT.S ; DESC: C start up codes ; Configure memory, ISR ,stacks ; Initialize C-variables ; 完全注释 ; HISTORY: ; 2002.02.25:kwtark: ver 0.…

中国电子学会2023年12月份青少年软件编程Scratch图形化等级考试试卷一级真题(含答案)

2023-12 Scratch一级真题 分数&#xff1a;100 题数&#xff1a;37 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1.观察下列每个圆形中的四个数&#xff0c;找出规律&#xff0c;在括号里填上适当的数&#xff1f;&#xff08;C&#xff09;&#xf…

预处理详解(下)

1.#运算符 #运算符将宏的一个参数转换为字符串字面量。它仅允许出现在带参数的宏的替换列表中。 #运算符所执行的操作可以理解为”字符串化“。 例如&#xff1a; 我们将打印的字符串中的n改为参数n,这样在传参的时候就也会随着变化。假如我们不将其改为参数n的话会发生什么呢…

C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(3) 保存表格数据

对上两篇篇的工作C Qt框架开发| 基于Qt框架开发实时成绩显示排序系统&#xff08;1&#xff09;-CSDN博客和C Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统&#xff08;2&#xff09;折线图显示-CSDN博客继续优化&#xff0c;增加一个保存按钮&#xff0c;用于保存成绩数据…

论文阅读-面向机器学习的云工作负载预测模型的性能分析

论文名称&#xff1a;Performance Analysis of Machine Learning Centered Workload Prediction Models for Cloud 摘要 由于异构服务类型和动态工作负载的高变异性和维度&#xff0c;资源使用的精确估计是一个复杂而具有挑战性的问题。在过去几年中&#xff0c;资源使用和流…

给定n个结点的树,其中有k个结点是特殊结点(未知),定义好结点:该结点到k个特殊结点的距离之和最小。若随机k个结点为特殊结点,求好结点个数的期望值

题目 思路: 举例: 其中黑色结点为特殊结点,可以看出,每种情况都有一个结点的s值不等于k / 2,但是是好结点,所以最后答案加一。 #include <bits/stdc++.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second …

支持向量机SVM

支持向量机&#xff08;SVM&#xff0c;Support Vector Machines&#xff09;是一种广泛使用的监督学习方法&#xff0c;适用于分类、回归和其他任务。SVM的核心思想是找到一个最优的决策边界&#xff08;在二维空间中是一条线&#xff0c;在更高维度是一个超平面&#xff09;&…

【北邮鲁鹏老师计算机视觉课程笔记】10 Classification 分类

【北邮鲁鹏老师计算机视觉课程笔记】10 Classification 分类 1 图像识别的基本范式 检测问题&#xff1a;不仅要知道有没有&#xff0c;还要知道在哪里 分类是整图级标签&#xff0c;检测是区域级标签&#xff0c;分割是像素级标签 2 检测任务的应用 3 单实例识别与类别识别…

问题 J: 今年暑假不AC

题目描述 “今年暑假不AC&#xff1f;” “是的。” “那你干什么呢&#xff1f;” “看世界杯呀&#xff0c;笨蛋&#xff01;” “#$%^&*%...” 确实如此&#xff0c;世界杯来了&#xff0c;球迷的节日也来了&#xff0c;估计很多ACMer也会抛开电脑&#xff0c;奔向电视…

【5G NR】【一文读懂系列】移动通讯中使用的信道编解码技术-Turbo编码原理

目录 Turbo码&#xff1a;无线通信中的革命性技术 引言 一、Turbo码的基本原理 1.1 卷积码基础&#xff1a; 1.2 Turbo码的构造&#xff1a; 1.2.1 分量编码器 1.2.2 随机交织器 1.2.3 穿刺和复接单元 1.3 编码器结构的重要性和影响 1.4 迭代解码&#xff1a; 1.4.1 …

接口测试怎么进行,如何做好接口测试

一、什么是接口&#xff1f; 接口测试主要用于外部系统与系统之间以及内部各个子系统之间的交互点&#xff0c;定义特定的交互点&#xff0c;然后通过这些交互点来&#xff0c;通过一些特殊的规则也就是协议&#xff0c;来进行数据之间的交互。 二、 常用接口采用方式&#x…

AI少女/HS2甜心选择2 仿剑三剑灵人物卡全合集打包

AI少女/HS2甜心选择2 仿剑三剑灵人物卡全合集打包 内含&#xff1a;菩提禅音[剑网3]明教晓天喵姐[剑3]明教晓天喵姐无帽版[剑3]茱莉亚[剑灵] 下载地址&#xff1a; https://www.changyouzuhao.cn/12492.html

配置DNS正反向解析服务!!!!

一.准备工作 #关闭防火墙和selinux,或者允许服务通过 [rootnode ~]# nmcli c mod ens32 ipv4.method manual ipv4.address 192.168.32.133/24 ipv4.gateway 192.168.32.2 ipv4.dns 192.168.32.132 [rootnode ~]# nmcli c reload [rootnode ~]# nmcli c up ens32[rootnode ~]# …

高速网络之翼:探索UDP的力量与灵活性

引言 在计算机网络中&#xff0c;用户数据报协议&#xff08;UDP&#xff09;是一种简单的面向数据报的传输层协议。与传输控制协议&#xff08;TCP&#xff09;相比&#xff0c;UDP不提供可靠性保证&#xff0c;但它因其低延迟和低开销的特性而在特定应用中非常有用。UDP使得…

【Java万花筒】解析Java依赖注入:从Spring到CDI的全方位比较

探索Java依赖注入&#xff1a;框架、实践与比较 前言 在当今的软件开发中&#xff0c;依赖注入已经成为了一种不可或缺的设计模式。Java作为一种广泛应用的编程语言&#xff0c;在依赖注入领域也有着丰富的框架和实践。本文将探索Java中几种常用的依赖注入框架&#xff0c;包…