iOS内购

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

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

  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 )
        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内购)