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<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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355