uniapp 苹果支付内购示例代码

// #ifdef APP
			async init() {
				uni.showLoading({
				  title: '检测支付环境...'
				});
					
				try {
					// 初始化,获取iap支付通道
					await this._iap.init();
					// 从苹果服务器获取产品列表
					this.productList = await this._iap.getProduct();
					this.productList[0].checked = true;
					this.productId = this.productList[0].productid;
					console.log('this.productId',this.productId);
					console.log('this.productList',this.productList);
				} catch (e) {
					uni.showModal({
						title: "init",
						content: e.message,
						showCancel: false
					});
				} finally {
					uni.hideLoading();
				}
					
				if (this._iap.ready) {
					this.restore();
				}
			},
			async restore() {
				// 检查上次用户已支付且未关闭的订单,可能出现原因:首次绑卡,网络中断等异常
				// 在此处检查用户是否登陆
					
				uni.showLoading({
					title: '正在检测已支付且未关闭的订单...'
				});
					
				try {
					// 从苹果服务器检查未关闭的订单,可选根据 username 过滤,和调用支付时透传的值一致
					const transactions = await this._iap.restoreCompletedTransactions({
						username: this.userInfo.user_name
					});
					
					if (!transactions.length) {
						return;
					}
					
					  // 开发者业务逻辑,从服务器获取当前用户未完成的订单列表,和本地的比较
					  // 此处省略
					
				  switch (transaction.transactionState) {
						case IapTransactionState.purchased:
							// 用户已付款,在此处请求开发者服务器,在服务器端请求苹果服务器验证票据
							//let result = await this.validatePaymentResult();
			
							// 验证通过,交易结束,关闭订单
							// if (result) {
							//   await this._iap.finishTransaction(transaction);
							// }
							break;
						case IapTransactionState.failed:
							// 关闭未支付的订单
							await this._iap.finishTransaction(transaction);
							break;
						default:
							break;
				  }
				} catch (e) {
					  uni.showModal({
						content: e.message,
						showCancel: false
					  });
				} finally {
					uni.hideLoading();
				}
			},
			async payment() {
				if (this.loading == true) {
				  return;
				}
				this.loading = true;
					
				uni.showLoading({
				  title: '支付处理中...'
				});
					
				try {
					// 请求苹果支付
					const transaction = await this._iap.requestPayment({
						productid: this.productId,
						manualFinishTransaction: true,
						username: this.userInfo.user_name
					});
					console.log(transaction,'transaction');
					const res = await this.$service.getApplePaySign({
						receipt: transaction.transactionReceipt,
						id: this.detail.data[this.activeId].id,
						time: this.active
					})
					console.log(res,'借口返回');
					uni.showToast({
						icon:'none',
						title: res.msg
					})
					//支付成功
				} catch (e) {
					console.log(e,'e');
					uni.showModal({
						content: e.message,
						showCancel: false
					});
					
				} finally {
					this.loading = false;
					uni.hideLoading();
				}
			},

使用前先创建并引入以下文件:

// uni iap

const ProviderType = {
  IAP: 'iap'
}

const IapTransactionState = {
  purchasing: "0", // A transaction that is being processed by the App Store.
  purchased: "1", // A successfully processed transaction.
  failed: "2", // A failed transaction.
  restored: "3", // A transaction that restores content previously purchased by the user.
  deferred: "4" // A transaction that is in the queue, but its final status is pending external action such as Ask to Buy.
};

class Iap {

  _channel = null;
  _channelError = null;
  _productIds = [];

  _ready = false;

  constructor({
    products
  }) {
    this._productIds = products;
  }

  init() {
    return new Promise((resolve, reject) => {
      this.getChannels((channel) => {
        this._ready = true;
        resolve(channel);
      }, (err) => {
        reject(err);
      })
    })
  }

  getProduct(productIds) {
    return new Promise((resolve, reject) => {
      this._channel.requestProduct(productIds || this._productIds, (res) => {
        resolve(res);
      }, (err) => {
        reject(err);
      })
    });
  }

  requestPayment(orderInfo) {
    return new Promise((resolve, reject) => {
      uni.requestPayment({
        provider: 'appleiap',
        orderInfo: orderInfo,
        success: (res) => {
          resolve(res);
        },
        fail: (err) => {
          reject(err);
        }
      });
    });
  }

  restoreCompletedTransactions(username) {
    return new Promise((resolve, reject) => {
      this._channel.restoreCompletedTransactions({
        manualFinishTransaction: true,
        username
      }, (res) => {
        resolve(res);
      }, (err) => {
        reject(err);
      })
    });
  }

  finishTransaction(transaction) {
    return new Promise((resolve, reject) => {
      this._channel.finishTransaction(transaction, (res) => {
        resolve(res);
      }, (err) => {
        reject(err);
      });
    });
  }

  getChannels(success, fail) {
    if (this._channel !== null) {
      success(this._channel)
      return
    }

    if (this._channelError !== null) {
      fail(this._channelError)
      return
    }

    uni.getProvider({
      service: 'payment',
      success: (res) => {
        this._channel = res.providers.find((channel) => {
          return (channel.id === 'appleiap')
        })

        if (this._channel) {
          success(this._channel)
        } else {
          this._channelError = {
            errMsg: 'paymentContext:fail iap service not found'
          }
          fail(this._channelError)
        }
      }
    });
  }

  get channel() {
    return this._channel;
  }
}

export {
  Iap,
  IapTransactionState
}

效果图:

 需要注意的是,这里是沙盒环境,只能使用虚拟账号进行支付:

可以在下面这个页面进行添加账号:

Apple 内购申请流程: 苹果支付内购申请-CSDN博客

参考:uniapp开发对接IOS应用内支付

其他解决方案:

uni-pay:uni-pay - DCloud 插件市场

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云部署宝塔,设置了安全组还是打不开。

1.在安全组是开放正确的端口好。8888要开,但是不只是开放8888,举个例子,https://47.99.53.222:17677/49706cf7这个,要开放17677这个端口号。 2.安全组要挂载到实例上,从三个点的进入点击管理实例,加到对应的…

独立站推广新策略:从精准定位到网红合作,开启品牌“长红”之路

随着互联网技术的飞速发展和消费者购物习惯的不断变化,独立站作为一种新型的电商模式,正逐渐成为品牌商家们拓展市场、提升品牌影响力的重要途径。然而,如何在竞争激烈的市场中脱颖而出,实现从短期流量吸引向长期品牌建设的转变&a…

为响应国家号召,搜维尔科技开启虚拟仿真实验室设备升级改造服务

近日,国务院发布了关于《推动大规模设备更新和消费品以旧换新行动方案》,该通知的发布表现出国家对于科技创新事业的高度重视。各行各业都在积极响应国家号召,加快数字化转型和设备升级与更新步伐。搜维尔科技为响应国家号召,将开…

如何使用CHAT-AI?

伴随着CHAT-GPT的出现,人们都喜欢上了CHAT-AI。嗯?你还不会用?! 教程来喽! 首先点这里的 … 点击扩展 接着选择“管理扩展” 点击之后搜索“wetab” 最后你需要注册一个号,然后就可以使用CHAT-AI啦&#x…

28位驻华大使、公使参访苏州金龙 点赞刚刚全球发布的新V系大巴

3月26日下午,由外交部组织的“驻华使节团参访江苏”活动走进苏州金龙。来自28个国家和国际组织的驻华大使、公使参观了苏州金龙展厅,并试乘体验了苏州金龙全新V系大巴。外交部中国政府欧洲事务特别代表吴红波,外交部礼宾司、翻译司、非洲司、…

产品力升级:揭秘产品力课程,打造竞争力强劲的爆款产品

在当今激烈的市场竞争中,产品力是企业成功的关键之一。那么,什么是产品力?什么是产品力课程?产品力课程如何帮助企业打造竞争力强劲的爆款产品?本文将为您一一解答。 什么是产品力? 产品力指的是一个产品在市场竞争中所具备的能力和优势。…

浏览器导出excel

做java web项目时&#xff0c;经常遇到需要在页面上点击导出按钮&#xff0c;然后直浏览器接下载下来一个excel文档。 比如一个List<Person>的集合&#xff0c;需要将每个Person当做一行&#xff0c;输出到excel中去。其中Person实体类如下&#xff1a; import lombok.…

PTA-练习9

目录 实验10-4 递归实现顺序输出整数 实验10-10 十进制转换二进制 实验10-6 递归求简单交错幂级数的部分和 实验11-1-2 输出月份英文名 实验11-1-6 指定位置输出字符串 实验11-1-8 查找子串 递归的基本思路&#xff1a; 推出递归的条件或者进入递归的条件每层递归需要执行…

手把手教你绘画原型图:Axure的安装使用

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN签约讲师&#xff0c;CSDN博客专家&#xff0c;华为云云享专家&#xff0c;阿里云专家博主 &#x1f4cc; 擅长领域&#xff1a;全栈工程师&#xff0c;大模型&#xff0c;爬虫、ACM算法 &#x1f492; 公众号&#xff…

DC-3靶机

一.环境搭建 下载地址&#xff1a; http://www.five86.com/downloads/DC-3-2.zip 下载不下来的可以用迅雷输入上面的网址进行下载 虚拟机配置&#xff1a; 切换连接桥接模式为nat模式&#xff0c;启动靶机&#xff0c;出现如下报错&#xff0c;进入虚拟机配置 选中CD/DVD&…

通过Appium和Xcode Accessibility Inspector获取iOS应用元素定位的方法

在 iOS 移动应用程序上使用选择器查找元素定位是我们在移动端 UI 自动化测试的先决条件。 但是&#xff0c;由于应用程序内容在原生 iOS 应用程序中的呈现方式&#xff0c;我们可以用来定位应用程序元素的选择器与 Web 浏览器元素有很大不同。 在本文中&#xff0c;我们将了解 …

百元开放式耳机怎么选?五款入手不亏的上乘产品推荐

耳机已经成为了我们生活中不可或缺的一部分&#xff0c;无论是通勤路上的音乐陪伴&#xff0c;还是家中观影的沉浸体验&#xff0c;一款优质的耳机都能为我们带来极大的享受。而在众多耳机类型中&#xff0c;开放式耳机因其独特的声场表现和舒适的佩戴体验&#xff0c;受到了越…

弹性伸缩 AS

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

JavaScript进阶5之垃圾回收(计算机组成、解释与编译、JavaScript引擎、垃圾回收、内存管理)、运行机制(浏览器进程分类、浏览器事件循环)

垃圾回收&运行机制 垃圾回收计算机组成解释与编译JavaScript引擎V8引擎 垃圾回收引用计数法标记清除&#xff08;mark-sweep&#xff09;算法 内存管理新生代 运行机制浏览器进程分类&#xff1a;浏览器事件循环宏任务微任务整体流程浏览器事件循环案例一案例二 垃圾回收 …

成都克鲁斯机器人电路板故障维修攻略,快来了解一下!

一、克鲁斯机器人电路板维修步骤 断开电源&#xff1a;在进行电路维修前&#xff0c;务必断开机器人的电源&#xff0c;确保安全。 拆卸电路板&#xff1a;根据电路图或维修手册&#xff0c;小心拆卸故障电路板。注意记录拆卸过程中的细节&#xff0c;以便后续重新安装。 更换损…

Linux中APP读取按键的4种方法

查询方式 驱动程序中构造、注册一个file_operations结构体&#xff0c;里面有对应的open,read函数。 APP 调用 open 时&#xff0c;导致驱动中对应的 open 函数被调用&#xff0c;在里面配置 GPIO 为输入引脚。APP 调用 read 时&#xff0c;导致驱动中对应的 read 函数被调用&a…

一个金融长期主义案例:金融壹账通的财务减亏与生产力创新之路

产业变革正在进入新一轮竞速期&#xff0c;社会对新质生产力的需求越来越迫切。在此背景下&#xff0c;金融业也正在坚定重塑自我、向外赋能的决心。 在微观的企业角度上&#xff0c;改变也正悄然发生。3月18日&#xff0c;在美港股双重上市的金融壹账通公布2023年年度业绩报告…

正则表达式不会用?一篇教你快速搞懂 !

目录 前言一、基础字符二、一系列常用的字符&#xff1b;1、一些元字符&#xff08;Meta-characters&#xff09; 三、一些高级概念1、贪婪与懒惰匹配2、两个实例加深理解1.颜色值的匹配&#xff1a;RGBS值2.ipv4 地址匹配 四、正则表达式常用语法**1.Flags&#xff08;标志符或…

测试开发工程师(QA)职业到底需要干些什么?part5:性能测试工程师QA

工作职责 性能测试工程师&#xff08;Performance Testing Engineer&#xff09;是负责评估和优化软件、应用程序或系统在不同负载和压力条件下的性能的专业人员。他们的工作职责包括以下几个方面&#xff1a; 性能测试计划&#xff1a;性能测试工程师与开发团队、产品团队和系…

工作的第二天

昨天的进度 写今天思路如何做评论表的增删该查评论表的增加 选择用户和商品 弹出框出现了问题 检查代码 结构没有问题 定义变量也没有问题 控制太中也没有报错信息 问题解决了 出现的问题在哪里定义的变量都有问题应该现在 setup 上面 定义一个 变量 const ref ref(fals…