// #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 插件市场