美文网首页
记录一下IAP内购的流程

记录一下IAP内购的流程

作者: 栋柠柒 | 来源:发表于2018-08-12 17:28 被阅读63次

    前段时间做了点内购的东西,记录一下内购流程,对于丢单的处理留到下一篇再记录,本次先不考虑丢单的情况。开发者中心设置税务财务就不记了,直接上代码逻辑。
    先来看下内购的流程图:


    image

    在此我默认内购的商品已经在开发者中心配置好,服务端也已经同步。
    大概流程就是:
    1.选择某个商品,客户端向服务端发起请求生成一个订单号,存到本地。
    2.客户端向苹果发起支付请求,苹果处理支付请求,将成功或者失败返回给客户端。
    3.如果苹果返回给客户端支付成功的话,会同时返回一个支付凭证,客户端需要把这个支付凭证和第一步生成的订单号回传给服务端,由服务端向APPLE验证支付的合法性,完成订单状态的最终修改。

    首先要导入用于内购的框架:

    import StoreKit
    

    配置获取支付凭证的地址,分为正式环境和沙盒环境:

    //沙盒测试环境验证
    let SANDBOX = "https://sandbox.itunes.apple.com/verifyReceipt"
    //正式环境验证
    let AppStore = "https://buy.itunes.apple.com/verifyReceipt"
    

    首先要声明一个SKProductsRequestDelegate和一个SKPaymentTransactionObserver,前者是获取商品详情的代理,后者是支付状态观察者的回调。
    声明两个全局变量:

    /**
         当前购买任务
         */
        private var currentTransaction:SKPaymentTransaction?
        /**
         商品对象
         */
        private var myProduct:SKProduct?
    

    判断是否支持支付:

    override init() {
            super.init()
            if SKPaymentQueue.canMakePayments(){
                SKPaymentQueue.default().add(self)//添加观察者
            }else{
                debugPrint("用户禁止应用内购买,操作失败!")
            }
        }
    

    根据商品id请求商品详情,这个id是在开发者后台配置好的.

    //MARK:- ==== 请求商品
        func requestProductWithId(productId:String)->Bool {
            if productId.count > 0{
                debugPrint("商品id:\(productId)")
                let productRequest = SKProductsRequest.init(productIdentifiers: [productId])//向苹果发送请求,请求所有可买的商品
                productRequest.delegate = self
                productRequest.start()
                return true
            }else{
                return false
            }
        }
    
    //MARK:-发起购买商品
        func purchaseProduct(skProduct:SKProduct)->Bool{
            if SKPaymentQueue.canMakePayments(){
                debugPrint("发起购买")
                let payment = SKPayment.init(product: skProduct)// 1.创建票据
    
                SKPaymentQueue.default().add(payment)// 2.将票据加入到交易队列
                return true
            }else{
                debugPrint("用户禁止应用内购买,操作失败!")
                return false
            }
        }
    

    实现支付状态回调的代理方法

    //MARK: - == SKPaymentTransactionObserver Delegate ==
        func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
            for transaction in transactions {
                debugPrint("identifer:\(String(describing: transaction.transactionIdentifier))")
                switch transaction.transactionState{
                case .purchasing://商品添加进列表
                    debugPrint("商品  \(transaction.payment.productIdentifier)  被添加进购买列表")
                    break
                case .purchased://交易成功
                    debugPrint("购买成功")
                    self.completeTransaction(transaction: transaction)
                    break
                case .failed://交易失败
                    debugPrint("交易失败")
                    self.failedTransaction(transaction: transaction)
                    
                    break
                case .restored://已购买过该商品
                    debugPrint("已购买过该商品")
                    queue.finishTransaction(transaction)
                    break
                case .deferred://交易延迟
                    debugPrint("交易延迟")
                    break
                }
            }
        }
    

    获取支付凭证

     //MARK: - ================ Private Methods =================
        func completeTransaction(transaction:SKPaymentTransaction){
            // 验证凭据,获取到苹果返回的交易凭据
            // appStoreReceiptURL iOS7.0增加的,购买交易完成后,会将凭据存放在该地址
            let recioptUrl = Bundle.main.appStoreReceiptURL
            do{
                let receiptData = try Data.init(contentsOf: recioptUrl!, options: Data.ReadingOptions.alwaysMapped)
            }catch{
                debugPrint("requestDidFinish出错!")
            }
            self.currentTransaction = transaction
        }
        func failedTransaction(transaction:SKPaymentTransaction){
            if (transaction.error != nil) {
               
            }
            SKPaymentQueue.default().finishTransaction(transaction)
            self.currentTransaction = transaction
        }
        deinit {
            SKPaymentQueue.default().remove(self)
        }
    
    //MARK:-结束当前交易
        func finishTransaction(){
            SKPaymentQueue.default().finishTransaction(self.currentTransaction!)
        }
    

    相关文章

      网友评论

          本文标题:记录一下IAP内购的流程

          本文链接:https://www.haomeiwen.com/subject/edyayftx.html