import {
Iap,
IapTransactionState,
} from "@/utils/iap.js"
export default {
data() {
return {
// 获取苹果真实的产品列表
iapProductList: [],
loading: false,
disabled: true,
personId: uni.getStorageSync("personId"),
quantity: 1,
}
},
methods: {
// 初始化支付环境
initPayEnv(products) {
this._iap = new Iap({
products
})
this.init();
},
async init() {
uni.showLoading({
title: '正在检测支付环境...'
});
try {
await this._iap.init();
this.iapProductList = await this._iap.getProduct();
this.disabled = false;
} catch (e) {
uni.showToast({
icon: 'none',
title: '支付环境检测失败',
duration: 2000
});
} finally {
uni.hideLoading();
}
if (this._iap.ready) {
this.restore();
}
},
async restore() {
this.loading = true;
this.disabled = true
// 检查上次用户已支付且未关闭的订单,可能出现原因:首次绑卡,网络中断等异常
// 提示是正在检测支付环境,实际是正在检测未关闭的订单
uni.showLoading({
title: '正在检测支付环境...'
});
try {
// 从苹果服务器检查未关闭的订单,可选根据 username 过滤,和调用支付时透传的值一致
const transactions = await this._iap.restoreCompletedTransactions({
username: ''
});
console.log(transactions)
if (!transactions.length) {
return;
}
for (var i = 0; i < transactions.length; i++) {
let transaction = transactions[i]
switch (transaction.transactionState) {
case IapTransactionState.purchased:
// 用户已付款,在此处请求开发者服务器,在服务器端请求苹果服务器验证票据
const username = transaction.payment.username || uni.getStorageSync(
'IAP_ORDER_USERNAME');
console.log('username', username)
if (!username) {
return await this._iap.finishTransaction(transaction);
}
this.validatePaymentResult(username, transaction);
break;
case IapTransactionState.failed:
// 关闭未支付的订单
await this._iap.finishTransaction(transaction);
break;
// case IapTransactionState.restored:
// // 关闭未支付的订单
// this.validatePaymentResult(username, transaction);
// break;
default:
break;
}
}
} catch (e) {
uni.showToast({
icon: 'none',
title: e.message,
duration: 2000
});
} finally {
this.loading = false
this.disabled = false
uni.hideLoading();
}
},
async onPayment() {
if (this.loading === true) {
return;
}
this.loading = true;
this.disabled = true
try {
// 从开发者服务器创建订单
const orderInfo = await this.$u.post('/api/finance/CreateIAPOrder', {
"PersonId": this.personId,
"CoinCount": this.currProductInfo.Price,
"ProductId": this.currProductId
})
console.log(orderInfo)
if (orderInfo && orderInfo.Status) {
// 本地缓存username
uni.setStorageSync('IAP_ORDER_USERNAME', orderInfo.UserName);
} else {
uni.showToast({
icon: 'none',
title: '订单创建失败,请联系管理员',
duration: 3000
});
uni.hideLoading()
return
}
// 请求苹果支付
const transaction = await this._iap.requestPayment({
productid: this.currProductId,
username: orderInfo.UserName,
quantity: this.quantity,
manualFinishTransaction: true,
});
console.log('transaction', transaction)
if (transaction.transactionState === IapTransactionState.purchased) {
// 在此处请求开发者服务器,在服务器端请求苹果服务器验证票据
const res = await this.validatePaymentResult(transaction.payment.username, transaction)
if (res.ReturnCode === 1001) {
// 支付成功,重新获取用户余额
uni.showToast({
icon: 'success',
title: '支付成功',
duration: 2000
});
// 触发统一的支付成功函数,由各个业务页面自行处理成功逻辑
this.paySuccess()
} else {
uni.showToast({
icon: 'none',
title: res.MessageChinese,
duration: 3000
});
}
uni.hideLoading()
this.onPaySuccessReset()
}
} catch (e) {
console.log(e)
uni.setStorageSync('IAP_ORDER_USERNAME', '');
if (e.errCode === 2 && e.code === 2) {
uni.showToast({
icon: 'none',
title: '支付已取消',
duration: 2000
});
} else {
uni.showToast({
icon: 'none',
title: e.message,
duration: 2000
});
}
uni.hideLoading()
this.onPaySuccessReset()
} finally {
// this.onPaySuccessReset()
}
},
// 向本地服务器验证支付结果
async validatePaymentResult(userName, transaction) {
const serverRes = await this.$u.post('/api/finance/IAPOrderVerify', {
"UserName": userName,
"TransactionReceipt": transaction.transactionReceipt,
})
console.log(serverRes)
if (serverRes.ReturnCode === 1001) {
uni.setStorageSync('IAP_ORDER_USERNAME', '');
// 验证成功后关闭订单
await this._iap.finishTransaction(transaction);
}
return serverRes
}
}
}
- 发布:2024-04-17 11:53
- 更新:2024-11-05 16:58
- 阅读:436
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: windows10 v2009
HBuilderX类型: 正式
HBuilderX版本号: 3.99
手机系统: iOS
手机系统版本号: iOS 15
手机厂商: 苹果
手机机型: iPhone6s Plus
页面类型: vue
vue版本: vue2
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
ios测试环境:沙盒环境
场景一:在每次支付前不调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买苹果系统会提示“你目前已订阅此项目”
场景二:在每次支付前调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买会直接进入支付成功回调,无提示。
场景三:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在未调用restoreCompletedTransactions api后购买该订阅产品,会先执行支付成功回调,再弹出系统支付弹窗。
场景四:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在调用restoreCompletedTransactions api后购买该订阅产品,会直接进入支付成功回调,支付弹窗未弹出。同时,检查设置->App Store->沙盒账户->产品订阅状态还是未订阅状态
ios测试环境:沙盒环境
场景一:在每次支付前不调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买苹果系统会提示“你目前已订阅此项目”
场景二:在每次支付前调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买会直接进入支付成功回调,无提示。
场景三:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在未调用restoreCompletedTransactions api后购买该订阅产品,会先执行支付成功回调,再弹出系统支付弹窗。
场景四:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在调用restoreCompletedTransactions api后购买该订阅产品,会直接进入支付成功回调,支付弹窗未弹出。同时,检查设置->App Store->沙盒账户->产品订阅状态还是未订阅状态
预期结果:
产品在未订阅状态下,可以订阅成功。产品在已订阅状态下,有系统提示用户。
产品在未订阅状态下,可以订阅成功。产品在已订阅状态下,有系统提示用户。
实际结果:
无法形成订阅产品支付闭环
无法形成订阅产品支付闭环
bug描述:
ios测试环境:沙盒环境
场景一:在每次支付前不调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买苹果系统会提示“你目前已订阅此项目”
场景二:在每次支付前调用restoreCompletedTransactions api的情况下,订阅产品在订阅状态下,再次购买会直接进入支付成功回调。
场景三:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在未调用restoreCompletedTransactions api后购买该订阅产品,会先执行支付成功回调,再弹出系统支付弹窗。
场景四:在产品订阅情况下,进入设置->App Store->沙盒账户->取消产品订阅,再进入app,在调用restoreCompletedTransactions api后购买该订阅产品,会直接进入支付成功回调,支付弹窗未弹出。同时,检查设置->App Store->沙盒账户->产品订阅状态还是未订阅状态
7 个回复
vonfly (作者) - 中端开发工程师
顶下
vonfly (作者) - 中端开发工程师
有官方同学解答下吗?
1***@qq.com
+1 我也遇到了
y***@163.com
顶,好多问题啊
pengcheng933
建议用原生插件来解决这个问题
y***@163.com
不会原生的
2024-07-24 14:09
pengcheng933
回复 y***@163.com: 我写了个,https://ext.dcloud.net.cn/plugin?id=17130
2024-07-24 17:24
y***@163.com
生产环境也这样,会返回初次的订单记录,而不是拉起支付弹窗,官方能不能看看问题啊,服了
y***@163.com
根据DCloud_iOS_WZT大佬的指导已经解决了问题,我没有使用官方的iap.js,所以在调用iapChannel.finishTransaction(Transaction, <Function> success, <Function> fail)原生函数的时候我没有传递success、fail这两个回调函数导致关闭交易失败了。
2024-09-03 16:46
PenGuin1
回复 y***@163.com: 我使用官方的iap.js,但是也碰到了同样的问题
2024-11-05 16:58
PenGuin1
有没官方的人出来解释下哇
y***@163.com
解决了,刚开始是因为没有关闭交易,后面沙盒环境这样是因为有延迟问题,取消订阅后需要等待20分钟后再次发起支付就可以拉起弹窗了
2024-11-05 17:00
PenGuin1
回复 y***@163.com: 每次支付前都会restore,然后关闭订单吗
2024-11-05 17:14
PenGuin1
回复 y***@163.com: restore后无法重新订阅(拉起订阅弹窗)
2024-11-05 17:16
vonfly (作者)
回复 PenGuin1: 你取消订阅之后过一段时间再试试呢
2024-11-11 09:48