iOS内购

作者: 正在输出昵称 | 来源:发表于2020-10-14 15:39 被阅读0次

    内购其实真的不难,🤨不信你往下看

    首先我们来总体看下内购的流程

    1. 资料填写 (协议,税务,银行业务,联系信息)
    2. App Store 配置(内购账号及产品ID) 及Xcode配置
      3.项目主要代码及二次验证

    完成以上几个步骤内购你就了解的差不多了。

    一. 资料填写

    你需要准备的资料

    1.联系地址(英文)
    2.银行账户(公司名称,账号,账户持有人姓名,账户类型(公司/个人),CNAPS)
    3.一个没有与 App ID 有关联的邮箱(差不多就是添加测试账号的时候去注册App ID)

    按照步骤填写就行。《不懂点这里》

    二. 添加沙盒测试账户及内购产品ID。

    截屏2020-10-14 下午2.21.42.png

    现在添加内购产品。创建的产品会保存在苹果的服务器上面。请求购买的时候会需要带上这个产品ID。

    App Store Connect ->我的App ->App 内购项目 -> 管理
    1.这里根据你们app自己的产品选择合适的项目。

    截屏2020-10-14 下午2.35.28.png
    2.接下来进行产品ID的设置。
    截屏2020-10-14 下午2.45.25.png
    截屏2020-10-14 下午2.48.05.png

    到这里内购信息,沙盒测试账号及产品ID就填写完成了。
    Xcode项目设置,添加 In-App Purchase。

    三。项目主要代码

    项目主要用到StoreKit 框架。继承协议 SKProductsRequestDelegate ,SKPaymentTransactionObserver实现代理方法。
    1.根据产品ID去苹果服务器请求产品。
            let requset = SKProductsRequest.init(productIdentifiers: NSSet(object: productId) as! Set<String> )
            requset.delegate = self
            requset.start()
    
    // 请求到产品会调用这个代理方法
        // MARK : ==== SKProductsRequest Delegate ====
        func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
            if response.products.isEmpty {
                delegate?.failurePurchaseWithError("无法获取产品信息")
                return
            }
            myProducts = response.products
            delegate?.receiveProduct(myProducts[0])
        }
    
    2.根据请求到的产品进行支付请求。
            if SKPaymentQueue.canMakePayments() {
                let payment = SKPayment(product: skProduct)
                SKPaymentQueue.default().add(self)
                SKPaymentQueue.default().add(payment)
            }else {
                print("用户禁止应用内购买")
            }
    
    3.之后会走支付回调方法
        // MARK : ==== SKPaymentTransactionObserver Delegate ====
        func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
            print(transactions.count)
            for transaction in transactions {
                 switch transaction.transactionState {
                case .purchasing: // 商品添加进列表
                    print("商品:被添加进购买列表")
                case .purchased:// 交易成功
                    completeTransaction(transaction)
                    finishedTransaction()
                case .failed:// 交易失败
                    failedTransaction(transaction)
                case .restored: // 已购买过该商品
                    restorePurchase()
                case .deferred: // 交易延迟
                    break
                @unknown default: break
                }
            }
        }
    // 当你的订单完成或者失败。需要手动完成该订单。不然会一直在苹果的支付队列里面。
        func finishedTransaction() {
            SKPaymentQueue.default().finishTransaction(self.currentTransaction)
            print("该订单已结束")
        }
    

    没事可以多看看《文档》

    四。为了确保支付成功。苹果提供了二次验证。

    我这里就在本地通过AppStore进行验证,(验证的这个过程都是通过服务器去验证,然后再给我们返回支付结果)

    沙盒:"https://sandbox.itunes.apple.com/verifyReceipt"
    正式 :"https://buy.itunes.apple.com/verifyReceipt"

        func verfyIAPurchase() {
            print("购买成功---验证")
            // MARK : 从沙盒中获取交易凭据
            let receiptUrl = Bundle.main.appStoreReceiptURL
            let receiptData = NSData(contentsOf: receiptUrl!)
            let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
            
            // MARK :  拼接请求数据
            let bodyStr = "{\"receipt-data\" : \"\(String(describing: receiptString!))\"}"
            let bodyData = bodyStr.data(using: .utf8)!
            let session : URLSession = URLSession.shared
            let url = URL(string: ViewController.url_verify_test)
            let request : NSMutableURLRequest = NSMutableURLRequest(url: url!)
            request.httpMethod = "POST"
            request.httpBody = bodyData
            
            let dataTask : URLSessionDataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
                do {
                    let dict  = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : Any]
                    let receiptDic = dict["receipt"] as! [String:Any]
                    let inApp = receiptDic["in_app"] as! [[String:Any]]
                    let transaction_id = inApp.last!["transaction_id"] as! String
                    let transaction_id2 = IAPManager.shared.currentTransaction.transactionIdentifier!
                    print(transaction_id,transaction_id2)
                    // MARK : 验证
                    if transaction_id == transaction_id2 {
                        print("验证成功")
                    }else {
                        print("验证失败")
                    }
                } catch {}
            }
            dataTask.resume()
        }
    
    

    ps: 我们在测试过程中,返回的in_app里面有时候会有多个数据,之前提到的,没有结束的支付队列都会在这个数组里面,所以当支付失败/完成的时候需要客户端手动去完成这个transaction。

    如果没有请求到订单信息可以用下面的这种方法去重新请求

       // MARK :  刷新凭证
       func refreshReceipt() {
           let request = SKReceiptRefreshRequest()
           request.delegate = self
           request.start()
       }
    
    给大家看下效果图😂
    50.png

    识别沙盒环境下收据的方法有2种:
    1.根据返回的字段 environment = sandbox
    2.根据返回的状态码,如果你请求正式环境返回的状态码是21007则表示为沙盒环境

    到这里,内购(非订阅)的东西差不多就这么多。其实真的不难。非订阅没有做过,不过应该也差不太多。

    最后附上demo

    相关文章

      网友评论

        本文标题:iOS内购

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