首页使用uniapp提供的iap.js文件
// 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;
uni.showToast({
title:channel,
icon:'none'
})
resolve(channel);
}, (err) => {
reject(err);
})
})
}
getProduct(productIds) {
return new Promise((resolve, reject) => {
this._channel.requestProduct(productIds || this._productIds, (res) => {
resolve(res);
}, (err) => {
reject(err);
})
});
}
// 注意这里是新加的,必须要有,不然支付不起
requestOrder(productIds) {
if (this._productIds.length == 0) this._productIds = productIds;
return new Promise((resolve, reject) => {
this._channel.requestOrder(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
}页面上的调用
import {
Iap,
IapTransactionState
} from "./iap.js"
export default {
data() {
return {
constants: {},
selected: 0, // 选择的套餐
productList: [], // 套餐列表
token: '',
userInfo: {}, // 用户信息
loading: false,
paytype: 1, // 支付方式
meal_id: 1, // 套餐ID与苹果那边添加的规则要对应上
osType: '', // 判断客户端类型ios android
disabled: true,
productId: '', // 选择的产品id
productIds: [] // 内购产品productid列表
}
},
onLoad() {
this.userInfo = uni.getStorageSync('userInfo');
this.getUser();
this.getMeal(); // 套餐列表
},
onShow() {
if (this.osType == 'ios') {
if (this._iap.ready) {
this.restore();
}
}
},
methods: {
// 获取登录用户信息
getUser() {
uni.$u.http.post('/user/index', {})
.then(({
data
}) => {
this.userInfo = data
uni.setStorageSync('userInfo', this.userInfo)
});
},
// 获取套餐列表
getMeal() {
uni.$u.http.post('/msg/meal', {})
.then(({
data
}) => {
this.meal_id = data[0].id; // 默认第一个选中
this.productList = data;
var productIds = [];
data.forEach(item => {
productIds.push('p'+item.id);
})
this.productIds = productIds;
this.disabled = false;
uni.getSystemInfo({
success: (e) => {
if (e.platform == 'ios') {
// 创建示例
this._iap = new Iap({
products: [] // 苹果开发者中心创建
})
this.init();
}
}})
})
},
submit() {
if (this.loading) return;
var that = this;
var params = {}
params.meal_id = this.meal_id;
if (this.osType == 'ios') {
params.paytype = 3;
} else {
params.paytype = this.paytype;
}
this.loading = true;
// 后端生成订单
uni.$u.http.post('/msg/order', params)
.then(({data}) => {
if (this.osType == 'ios') {
this.payment(data.orderId)
} else {
// 其他支付
}
this.loading = false;
})
.catch(err => {
this.loading = false;
})
},
selectItem(index) {
this.selected = index
this.meal_id = this.productList[index].id;
},
selectPay(index) {
this.payList[0].checked = false;
this.payList[1].checked = false;
this.payList[index].checked = true;
this.paytype = this.payList[index].value;
},
async init() {
uni.showLoading({
title: '检测支付环境...'
});
try {
// 初始化,获取iap支付通道
await this._iap.init();
this.requestOrder(); // 这步必须
// 从苹果服务器获取产品列表
// this.productList = await this._iap.getProduct(this.productIds);
// this.selected = 0;
// this.productId = this.productList[0].productid;
// 填充产品列表,启用界面
this.disabled = false;
} catch (e) {
uni.showModal({
title: "提示",
content: e.errMsg ? e.errMsg : (e.message ? e.message : '请求失败'),
showCancel: false
});
} finally {
uni.hideLoading();
}
if (this._iap.ready) {
this.restore();
}
},
// 必须请求
requestOrder() {
this._iap.requestOrder(this.productIds, (orderList) => { //必须调用此方法才能进行 iap 支付
uni.hideLoading();
}, (e) => {
uni.hideLoading();
uni.showToast({
title:'初始化订单失败',
icon:'none'
})
});
},
async restore() {
// 检查上次用户已支付且未关闭的订单,可能出现原因:首次绑卡,网络中断等异常
// 在此处检查用户是否登陆
uni.showLoading({
title: '正在检测已支付且未关闭的订单...'
});
try {
// 从苹果服务器检查未关闭的订单,可选根据 username 过滤,和调用支付时透传的值一致
const transactions = await this._iap.restoreCompletedTransactions({
username: this.userInfo.username
});
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(orderId) {
// if (this.loading == true) {
// return;
// }
// this.loading = true;
uni.showLoading({
title: '支付处理中...'
});
try {
// 请求苹果支付
const transaction = await this._iap.requestPayment({
productid: 'prod'+this.meal_id, // 与苹果添加的id对应
// manualFinishTransaction: true,
username: this.userInfo.username+'-'+orderId //根据业务需求透传参数,关联用户和订单关系
});
// 在此处请求开发者服务器,在服务器端请求苹果服务器验证票据
await this.validatePaymentResult({
orderId: orderId,
receipt: {
username: this.userInfo.username,
transactionReceipt: transaction.transactionReceipt, // 不可作为订单唯一标识
transactionIdentifier: transaction.transactionIdentifier
}
});
// 验证成功后关闭订单
await this._iap.finishTransaction(transaction);
this.loading = false;
uni.hideLoading();
// 支付成功
} catch (e) {
this.loading = false;
uni.hideLoading();
uni.showModal({
content: e.message ? e.message : '支付失败',
showCancel: false
});
} finally {
this.loading = false;
uni.hideLoading();
}
},
// 能过后台验证支付
validatePaymentResult(data) {
return new Promise((resolve, reject) => {
if (data) {
uni.$u.http.post('/msg/checkorder', data)
.then(({data}) => {
uni.showToast({
title:'支付成功',
icon:'none'
})
resolve(data)
})
.catch(err => {
reject(err)
})
} else {
resolve()
}
});
}
},
};uniapp,苹果,ios内购,ios支付,苹果支付,内购