iOS内购集成

栏目: IOS · 发布时间: 5年前

内容简介:In-App Purchase:应用内购买服务,简称IAP。是苹果为App内的虚拟商品和服务的交易定制的系统。所谓应用内购买,是指在操作虚拟商品交易的时候,不允许使用类似微信/支付宝/Apple Pay第三方支付手段,如果通过另类方式避开的话,会被下架。请参考前一篇文章 《

In-App Purchase:应用内购买服务,简称IAP。是苹果为App内的虚拟商品和服务的交易定制的系统。

所谓应用内购买,是指在操作虚拟商品交易的时候,不允许使用类似微信/支付宝/Apple Pay第三方支付手段,如果通过另类方式避开的话,会被下架。

配置内购信息

请参考前一篇文章 《 iOS打包上架最新(含内购)2019年

创建商品类型

消耗型:使用一次并耗尽,可以重复购买。类似于宝箱,武器皮肤

非消耗型:只需购买一次,不会过期。类似于地图,电子书

自动续期订阅:购买一次后服务或内容会自动续订,直到用户决定取消。类似于Apple music

非续期订阅:购买一次后,不会自动续订,并且可以再次购买,等同于购买一段时间的服务可以叠加。类似于会员,一定数量钻石

StoreKit

通过StoreKit框架使应用程序连接到App Store,以提示并安全地处理付款。

iOS内购集成

先遵循SKProductsRequestDelegate,SKPaymentTransactionObserver协议。

//添加支付监听
SKPaymentQueue.default().add(self) 
//移除监听
SKPaymentQueue.default().remove(self)复制代码

点击购买

//是否允许付款(通过权限限制购买的人群)
if SKPaymentQueue.canMakePayments() {
    pid:这里指的是选择套餐对应的id,从苹果后台的套餐配置生成,App服务端获取
	let set = NSSet(array: [pid])
	//检索本地化商品信息
	let request = SKProductsRequest(productIdentifiers: set as! Set<String>)  
	request.delegate = self
	request.start()
}else {
    print("禁止购买")
}复制代码

恢复购买,这里的作用是持久化我们的订单信息,下次重新监听支付队列的时候会重新调用

恢复之前的购买
SKPaymentQueue.default().restoreCompletedTransactions()//非续订订阅型和消耗型无法恢复

购买历史记录的事务,添加回队列出错回调
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
	print("错误恢复: \(error)")
}

恢复购买,成功添加队列回调
func paymentQueueRestoreCompletedTransactionsFinished(_ queue:SKPaymentQueue){
    
}复制代码

产品要求代理<SKProductsRequestDelegate>

收到产品信息的响应
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
}

请求失败
func request(_ request: SKRequest, didFailWithError error: Error) {
}

请求完成
func requestDidFinish(_ request: SKRequest) {
}复制代码

付款交易观察代理<SKPaymentTransactionObserver>

监听交易状态
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for tran in transactions {
            switch tran.transactionState {
            case .purchased:
                //交易完成,调起验证购买
                //1.从沙盒获取持久化订单信息
                //2.将收据上传到App服务器,成功后结束交易
                //3.删除保存的订单信息
            case .purchasing:
            	//交易中
            case .restored:
                //已经购买过
            case .failed:
                //交易失败
                break
            default:
                break
      }
   }
}

交易结束
private func payFinish(transaction:SKPaymentTransaction) {
}复制代码

代码

import UIKit
import StoreKit
// MARK: - swift title: IAP应用内购买
// MARK: - 点击购买
class UserIAPBuy: NSObject,SKProductsRequestDelegate,SKPaymentTransactionObserver {​    
    func startBuyInnerProduct(_ type: String) -> () {​        
        SKPaymentQueue.default().add(self as SKPaymentTransactionObserver)​        ​        
        localRequest(type)​    
    }​    ​    
    func localRequest(_ type: String) -> () {​        ​        
        if SKPaymentQueue.canMakePayments() {​            
            let set = NSSet(array: [type])​            
            //检索本地化商品信息​            
            let request = SKProductsRequest(productIdentifiers: set as! Set<String>)​            
            request.delegate = self​            
            request.start()​        
        }else {​            
            print("禁止购买")​        
        }​        ​    
    }​    
}
// MARK: - 恢复购买
extension UserIAPBuy {​    
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {​        
        print("错误恢复 code: (error)")​    
    }​    ​    
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {​        
        //恢复购买获取成功回调​        
        var array = String​        
        print("received restored transactions: (queue.transactions.count)")​        
        for pay:SKPaymentTransaction in queue.transactions {​            
            let productID = pay.payment.productIdentifier​            
            array.append(productID)​            
            print("message: (array)")​        
        }​    
    }​    
    //恢复之前购买​    
    @objc func replyToBuy() {​        
        SKPaymentQueue.default().restoreCompletedTransactions()​    
    }
}
// MARK: - 代理:商品 SKProductsRequestDelegate
extension UserIAPBuy {​    
    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {​        
        // 收到App Store商品信息的响应​        
        let pro = response.products​        ​        
        if pro.count > 0 {​            
            var p: SKProduct?​            
            for pid in pro {​                
                print("描述信息:  (pid.description)")​                
                print("产品标题:  (pid.localizedTitle), 产品描述信息:  (pid.localizedDescription)")​                
                print("价格:  (pid.price)")​                
                p = pid​            
            }​            
            guard let pro = p else {​                
                return​            
            }​            
            SKPaymentQueue.default().add(SKPayment(product: pro))​            ​        
        }else {​            
            // 处理无法获得商品信息的操作​            
            print("无法取得商品信息")​        
        }​    
    }​    ​    
    func requestDidFinish(_ request: SKRequest) {​        
        // 处理请求完成​    
    }​    ​    
    func request(_ request: SKRequest, didFailWithError error: Error) {​        
        // 处理请求失败​    
    }
}
// MARK: - 代理:付款交易观察 SKPaymentTransactionObserver
extension UserIAPBuy {​    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {​        
        //监听交易状态​        
        for tran in transactions {​            
            switch tran.transactionState {​            
            case .purchased:​                
                //交易完成,调起验证购买​                
                //1.从沙盒获取持久化订单信息​                
                //2.将收据上传到App服务器,成功后结束交易​                
                //3.删除保存的订单信息​                
                paymentTransactionPurchased()​                
                SKPaymentQueue.default().finishTransaction(tran)​            
            case .purchasing:​                
                //交易中​                
                paymentTransactionPurchasing()​            
            case .restored:​                
                //已经购买过​                
                paymentTransactionRestored()​                
                SKPaymentQueue.default().finishTransaction(tran)​            
            case .failed:​               
                //交易失败​               
                paymentTransactionFailed(tran)​            
            default:​                
                break​            
            }​        
        }​    
    }​    ​    
    func paymentTransactionPurchased() {​        
        // 验证购买,避免越狱软件模拟苹果请求达到非法购买问题​        
        guard let receiptUrl = Bundle.main.appStoreReceiptURL,let receiptData = try? Data(contentsOf: receiptUrl) else {​                        
            // 从沙盒中获取交易凭证并且b拼接成请求提数据0​            
            return​        
        }​        
        let receiptStr = receiptData.base64EncodedString(options: Data.Base64EncodingOptions.endLineWithLineFeed)​        
        //处理订单信息​        
        print("订单信息: (receiptStr)")​        
        //删除保存的订单​    
    }​    ​    
    func paymentTransactionPurchasing() {​        
        print("交易中")​    
    }​    ​    
    func paymentTransactionRestored() {​        
        print("已经购买过")​    
    }​    ​    
    func paymentTransactionFailed(_ transaction: SKPaymentTransaction) {​        
        guard let err = transaction.error else {​            
            SKPaymentQueue.default().finishTransaction(transaction)​            
            return​        
        }​        
        if (err as NSError).code != SKError.paymentCancelled.rawValue {​            
            print("交易失败")​        
        }else{​            
            print("交易取消")​        
        }​    
    }  
}复制代码

沙箱测试

沙箱账号是测试用途的Apple ID,由于内购涉及实际金钱交易,在测试阶段我们可以通过注册苹果的沙箱账号来完成内购付款。

电子邮箱可以自定义。

iOS内购集成

应用IAP权限打开

iOS内购集成

最后

技术总结:

1.在App Store后台配置内购买项目,需要先完成协议,税务银行项目。这部分可参考上一篇

2.配置具备In-App Purchase功能的App ID,并开启IAP权限。

3.通过StoreKit框架,在对应的地方实现并调整你的内购代码。

需要注意的地方:

1.有关于服务端验证收据,服务端也是有沙盒和正式两个环境,具体实现也有很多成熟的开源框架可用,这里也需要把应用套餐的信息给服务端配置。

2.苹果自带的内购买体验确实不是很好,由于本身服务器在美区,连接会比较慢,添加沙盒App ID的时候,介意不要在App内绑定,可以选择从设置绑定账号测试。

3.应用套餐也是需要审核的,把改填的地方填写清楚,问题不大,另外应用内套餐审核是伴随主App一起审核的,如果主App没有过,那么原先套餐审核通过的状态就会改变,在下一次重新提交主App的时候需要重置套餐的状态,否则,无法查找对应套餐信息。

纯属个人分享,希望对iOS社区能有更多贡献。


以上所述就是小编给大家介绍的《iOS内购集成》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Linux内核设计的艺术

Linux内核设计的艺术

新设计团队 / 机械工业出版社华章公司 / 2011-6-20 / 79.00元

关于Linux内核的书已经不计其数,但这本书却是独树一帜的,它的内容代表着Linux内核研究成果的世界顶尖级水平,它在世界范围内首次提出并阐述了操作系统设计的核心指导思想——主奴机制,这是所有操作系统研究者的一笔宝贵财富。本书可能也代表着同类图书的顶尖水平,是一本真正能引导我们较为容易地、极为透彻地理解Linux内核的经典之作,也可能是当前唯一能从本质上指引我们去设计和开发拥有自主知识产权的操作系......一起来看看 《Linux内核设计的艺术》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码