根据uniapp官方demo并加以改正 ApplePay.js :
/*
需求:两个或多个页面会使用到充值逻辑。
思考:根据uniapp官方案例,一个页面需要写的代码太多,不适合多页面这么玩,冗余代码会很多,还不易维护;
所以基于demo,再次封装,此次封装不是最好,只是刚好适合当前需求,后续可能还会迭代,可以根据自己需求修改。
由于需求暂定,所以直接将 api请求 直接引入到当前页面使用。
*/
import api from '@/common/api/api.js'
import app from '@/utils/app.js'
const IapTransactionState = {
purchasing: "0", // 应用程序商店正在处理的交易.
purchased: "1", // 成功处理的交易.
failed: "2", // 一个失败的交易.
restored: "3", // 恢复用户以前购买的内容的事务.
deferred: "4" // 处于队列中的事务,但其最终状态为等待外部操作
};
class Iap {
_channel = null; // 支付渠道
_channelError = null; // 获取支付渠道失败的对象
_productIds = []; // Apple 官网后台 配置的内部购买项目列表
_ready = false; // 是否还有未处理的交易
constructor({
products
}) {
this._productIds = products;
}
/*
初始化、获取支付渠道
*/
init() {
return new Promise((resolve, reject) => {
this.getChannels((channel) => {
this._ready = true;
resolve(channel);
}, (err) => {
reject(err);
})
})
}
/**
* @description 向苹果服务器获取产品列表
* @param productIds 产品列表
*/
getProduct(productIds) {
return new Promise((resolve, reject) => {
this._channel.requestProduct(productIds || this._productIds, (res) => {
resolve(res);
}, (err) => {
reject(err);
})
});
}
/**
* @description 发起支付请求
* @param orderInfo 订单信息
*/
requestPayment(orderInfo) {
return new Promise((resolve, reject) => {
uni.requestPayment({
provider: 'appleiap',
orderInfo: orderInfo,
success: (res) => {
resolve(res);
},
fail: (err) => {
uni.hideLoading();
reject(err);
}
});
});
}
/**
* @description 获取苹果服务器已支付且未关闭的交易列表
* @param username 用户姓名
*/
restoreCompletedTransactions(username) {
return new Promise((resolve, reject) => {
this._channel.restoreCompletedTransactions({
manualFinishTransaction: true,
username,
}, (res) => {
resolve(res);
}, (err) => {
reject(err);
})
});
}
/**
* @description 关闭订单
* @param transaction 订单对象
*/
finishTransaction(transaction) {
return new Promise((resolve, reject) => {
this._channel.finishTransaction(transaction, (res) => {
resolve(res);
}, (err) => {
uni.hideLoading();
reject(err);
});
});
}
/**
* @description 获取支付渠道
* @param success 成功获取回调
* @param fail 失败获取回调
*/
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;
}
}
/* 实现支付 自定义逻辑 */
class realize {
productItem = null; // 当前选择充值项id
loading = false; // 是否允许提交充值
//应用内购项目
productList = ['leanmaster.app.rmb6', 'leanmaster.app.rmb18', 'leanmaster.app.rmb68',
'leanmaster.app.rmb128',
'leanmaster.app.rmb298', 'leanmaster.app.rmb698'
];
// 调用官方案例
_iap = new Iap({
products: this.productList,
});
async init() {
try {
// 初始化,获取iap支付通道
await this._iap.init();
// 从苹果服务器获取产品列表
this.productList = await this._iap.getProduct();
// 将列表按照从小到大的顺序排好
this.productList.sort((a, b) => {
return a.price - b.price
})
// 默认选择第一个产品
this.productItem = this.productList[0];
} catch (e) {
uni.showModal({
title: "init",
content: e.message,
showCancel: false
});
} finally {
uni.hideLoading();
}
if (this._iap._ready) {
this.restore();
}
}
async payment() {
if (this.loading == true) {
return;
}
this.loading = true;
uni.showLoading({
title: '支付处理中...'
});
// 请求苹果支付
let transaction;
try {
// 从开发者服务器创建订单
const orderId = await api.payApple({
productId: this.productItem.productid,
price: this.productItem.price
});
transaction = await this._iap.requestPayment({
productid: this.productItem.productid,
manualFinishTransaction: true,
username: app.username, //根据业务需求透传参数,关联用户和订单关系
});
// 在此处请求开发者服务器,在服务器端请求苹果服务器验证票据
let verifyRes = await api.payAppleVerify(transaction);
// 验证成功后关闭订单
await this._iap.finishTransaction(transaction);
if (verifyRes) {
app.toast('支付成功')
} else {
app.toast('支付失败')
}
// 支付成功
} catch (e) {
this._iap.finishTransaction(transaction);
if (e.errCode == 2) {
app.toast('取消支付')
return false;
}
app.toast('支付失败')
} finally {
this.loading = false;
uni.hideLoading();
}
}
}
export {
realize
}
- 调用页面 index.vue :
import { realize } from "@/utils/ApplePay.js"
this._iap = new realize()
this._iap.init();
- 如有报错,仔细看看是否改动了代码,产生的bug。