iOS内购也算是老生常谈的一个技术点了, 但是对于我这种刚刚接触的人来讲, 还是踩了不少的坑, 这几天刚搞完, 来简单的总结一下内购的流程.
暂且不说申请税务, 添加银行卡 这些步骤, 直接进入代码.
首先了解一下iOS IAP内购的总的流程, 如下图:
那么根据上图所述6点进行 代码阐述.
- 在
Appdelegate
中应用程序启动时 设置transectionObserver:
SKPaymentQueue.default().add(self)
- 根据后端返回的产品id 或者 产品id 的集合, 进行产品的查询.
@discardableResult
public func requestProductsInfo(productIds: [String]) -> SKProductsRequest {
let request = SKProductsRequest(productIdentifiers: Set(productIds))
request.delegate = self
request.start()
return request
}
- 在
SKProductsRequestDelegate
代理方法中 可以找到接收到苹果服务器返回的查询产品方法
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
let products = response.products
print("products : \(products)")
/// 拿到数据集合 进行UI界面的更新
#warning UpdateUI
}
4, 5 . 如果后端有订单系统的话, 那么当点击某一款产品时, 要向后端请求生成订单号. 没有订单系统, 不要订单号也是可以的. 然后根据product创建payment实例, 并将其放入paymentQueue中, 发起付款请求:
public func purchaseProduct(product: SKProduct, orderId: String?) {
let payment = SKMutablePayment(product: product)
//设置订单号
if let orderId = orderId {
payment.applicationUsername = orderId
}
SKPaymentQueue.default().add(payment)
}
- . 收到付款的回调, 回调中会将transection 带出来, 可以根据transection.transactionState 来判断交易的状态, 根据交易状态来进行不同的处理, 要记住, 处理结束之后 一定要调用结束交易的代码:
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
// print("有交易更新")
switch transaction.transactionState {
case .purchasing:
printLog("商品添加进列表")
case .purchased:
printLog("交易完成")
case .failed:
if let swiftError = transaction.error {
let error = swiftError as NSError
if error.code == SKError.Code.paymentCancelled.rawValue {
// printLog("交易取消")
} else {
// printLog("交易失败")
}
}
SKPaymentQueue.default().finishTransaction(transaction)
case .restored:
// printLog("已经购买过商品")
SKPaymentQueue.default().finishTransaction(transaction)
case .deferred:
break
@unknown default:
break
}
}
}
要注意:
- 发起productRequest之前要判断当前设备或者AppId是否支持IAP:
func canMakePurchases() -> Bool {
return SKPaymentQueue.canMakePayments()
}
-
如果当前产品为非消耗类型的, 那么只能购买一次, 再次购买的话就会出现以下图片:
如果你的产品中有非消耗类型的产品, 那么需要判断当前产品是否已经购买过, 如果购买过, 苹果要求要有一个恢复购买按钮, 用来恢复当前appid的权益, 否则会被guildline 3.1.1 拒绝掉. 可通过下面的步骤查询到当前已经购买过的产品:
1. 在进入商品列表或者购买页面的时候 向PaymentQueue中添加存储已经完成交易的操作: SKPaymentQueue.default().restoreCompletedTransactions()
2. 接下来会出发SKPaymentTransactionObserver中的完成交易的代理方法, 在代理方法中 可以将已经完成交易的产品 存储起来:
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
// 处理已经购买过的商品.
for transaction in queue.transactions {
let productId = transaction.payment.productIdentifier
printLog("已经购买过的产品id = \(productId)")
/// 可以将产品或者产品id放入集合中 存储起来.
}
}
如果产品类型属于非续期订阅, 那么以上方法是查不出来的. 因为非续期订阅 是可以无限次购买的产品, 产品有有效期, 买的越多, 有效期越长, 例如为期一年的已归档文章目录订阅.