官方文档在这里:苹果应用内支付
官方文档有一部分说的比较模糊不太详细,报错也是如此。因此这里说一下方便大家排雷避坑
-
申请流程
- 要有苹果开发者账号这个就不说了
- 要在appstoreconnect的应用的功能下面管理你的 App 内购项目,亲测添加后把信息填写完整并保存,只要状态为准备提交即可!
- 把你添加的商品的产品 ID记下来一会要用到(下文称pid)
- 你需要到苹果开发者中心证书管理生成一个iOS App Development类型的证书并生成p12文件和Profile页面生成mobileprovision文件,具体生成教程很多就不一一列举了。生成后打包个自定义基座就可以写代码了。
注意!上述过程一个都不能漏
-
代码编写流程
代码编写文档放在文章开头了,这里说一下调起顺序:- 使用uni.getProvider获取id为appleiap的channel,下文称该channel为支付通道。例:
async getIAPChannel() { return await new Promise((recv, recj) => { uni.getProvider({ service: 'payment', success: res => { const iapChannel = res.providers.find(channel => { return channel.id === 'appleiap'; }); if (iapChannel) recv(iapChannel); recj(new Error('当前环境不支持使用IAP支付!')); } }); }); }
- 使用通道的requestProduct方法获取pid对应的商品信息。例:
let orderDetail = await new Promise((recv, recj) => { channel.requestProduct([pid], recv, recj); });
注意!!!这一步不能省略,否则会无法调起支付!!!
- 使用uni.requestPayment调起支付。例:
let transaction = await new Promise((recv, recj) => { uni.requestPayment({ provider: 'appleiap', orderInfo: { productid: pid, username: 'ORDERID' + orderid, quantity: 1, manualFinishTransaction: true }, success: t => { recv(t); }, fail: e => { recj(new Error('支付调起失败:Errcode ' + e.errCode + ',' + e.errMsg)); } }); });
- 使用uni.getProvider获取id为appleiap的channel,下文称该channel为支付通道。例:
-
掉单处理
官方文档中说明部分与实际demo代码不一致。这里说一下流程:- 使用uni.getProvider获取id为appleiap的channel,下文称该channel为支付通道。例同代码编写流程
- 使用支付通道的restoreCompletedTransactions方法获取可能掉单的订单列表(支付时一定要设置manualFinishTransaction为true否则这里就找不到了)。例:
let customOrderList = await new Promise((recv, recj) => { channel.restoreCompletedTransactions({}, recv, e => { //第一个参数必传,否则会导致app闪退! recj(new Error('获取未完成订单列表失败:Errcode ' + e.errCode + ',' + e.errMsg)); }); });
- 处理掉单,掉单分几种情况,官方文档有介绍:
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. };
我只需要处理failed和purchased两种状态的交易即可,具体根据业务需求决定。例:
for (let i = 0; i < customOrderList.length; i++) { if (customOrderList[i].transactionState == 2) { //关闭失败订单 for (let b = 0; b < 5; b++) try { await new Promise((recv, recj) => { channel.finishTransaction(transaction, recv, recj); }); break; } catch (e) { console.log(e); } } else await this.verifyTransactionReceipt(customOrderList[i]); //上报已经成功但服务器没有处理的订单(把transactionReceipt属性值发给服务端就行了),接收到服务器成功响应后再关闭订单。 }
2 个评论
要回复文章请先登录或注册
亚瑟
zhaoyu2020