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 苹果内购流程

    本文参考: iOS开发之内购完全笔记 iOS开发内购全套图文教程 iOS应用程序内购/内付费(一) 代码...

  • iOS内购流程文档-Lion

    iOS内购流程: iOS内购 什么时候用到呢? 虚拟产品就需要用到iOS内购;购买的商品,是在本app中...

  • iOS-内购

    前言:关于iOS内购,参考两篇博文 iOS-iOS内购流程(手把手图文教程)iOS内购你看我就够了(埋坑篇) 我自...

  • iOS内购一条龙------项目代码 (4)

    步骤一 iOS内购一条龙------账户信息填写(1)步骤二 iOS内购一条龙------配置内购产品ID (2)...

  • iOS内购一条龙------内购测试账号 (3)

    步骤一 iOS内购一条龙------账户信息填写(1)步骤二 iOS内购一条龙------配置内购产品ID (2)...

  • iOS 内购 IAP

    1. iOS内购IAP(一) —— 基础配置篇(一)2. iOS内购IAP(二) —— 工程实践(一)3. iOS...

  • 应用内购(In-App Purchase)常见问题解答

    应用内购(In-App Purchase)常见问题解答iOS的应用内购买 iAP 坑 iOS内购你看我就够了(一)...

  • iOS内购从放弃到上架

    iOS内购方面的坑

  • ios内购IAP相关内容

    ios内购IAP相关内容 iOS IAP应用内购详细步骤和问题总结指南 - 简书https://www.jians...

  • 2019-05-20

    iOS内购编程指南 - 简书 iOS内购 服务端票据验证及漏单引发的思考. - WidgetBox - 博客园 一...

网友评论

    本文标题:iOS内购

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