首页使用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支付,苹果支付,内购