App内购之 Ray Wenderlich 的 IAP 文章的学习笔记

App内购与RayWenderlich的IAP文章学习笔记
本文深入解析了App内购流程,包括配置、支付流程和编码实现细节,通过示例代码帮助开发者理解如何在iOS应用中实现内购功能。

App内购之 Ray Wenderlich 的 IAP 文章的学习笔记。

原创文章,转载请保留地址:http://blog.youkuaiyun.com/abware/article/details/12165933


前面几步的流程请看原文,很详细,有中文版。这里主要是讲解一下代码,这块代码对新手来说有点难懂。 
一、配置。这块比较繁琐,填很多表,信用卡帐号等要填
1. AppID。应该是不能用*
2. ProductID
3. Test帐号
二、支付流程
1. 无独立服务器模式
2. 有独立服务器模式
三、编码
1. 初始化
     把IAPHelper.h与IAPHelper.m两个文件导入工程。
     创建自己的xxxxIAPHelper类,继承自IAPHelper。
     将xxxxIAPHelper写为单例,并在单例初始化时调用- ( id )initWithProductIdentifiers:(NSSet *)productIdentifiers函数,同时给定输入参数,该输入参数即ProductID列表。需要与itunes connect中设定的一致。另外初始化函数中还做了一件事:注册为支付事务的观察者。
     该单例的第一次初始化放在AppDelegate中,原因如后面所述。
2. 查询
     查询请求的入口函数被封装为- ( void )requestProductsWithCompletionHandler:( RequestProductsCompletionHandler )completionHandler,其中输入参数是一个Block,在请求结果的返回中,会调用到该Block,这个Block的内容则需要自己来写,用来对返回结果进行处理。另一个隐含的输入是成员变量 _productIdentifiers   ,该成员变量在初始化时被赋值。另外该函数还用到成员变量 _productsRequest ,该变量用来保存该查询请求的句柄。
     查询结果的返回需要要实现 SKProductsRequestDelegate 协议,该协议的两个函数分别用来处理请求成功和请求失败两种情况。这两个函数都会将成员变量 _productsRequest 设置为nil,同时打印一些日志信息,最后都会调用 RequestProductsCompletionHandler 这个Block,即发送请求时指定的Block。该Block的定义为 typedef void (^RequestProductsCompletionHandler)( BOOL success, NSArray * products);,可以看到有两个输入参数,请求成功时第一个参数赋为YES,第二个参数为 NSArray 是包含了所有产品列表,是从StoreKit框架标准返回参数 SKProductsResponse 中得到的response. products ;请求失败时第一个参数赋为NO;第二个参数为nil。
     注:Block如果不太理解,可以暂把它理解为一个回调,或者函数指针。实际上Block是一个函数对象,有其自身的作用域。
3. 支付购买
     发送支付请求的入口函数被封装为- ( void )buyProduct:( SKProduct *)product,其中需要增加一点的是[ SKPaymentQueue canMakePayments ]判断。该函数内会把输入参数封装为 SKPayment ,然后加入到 SKPaymentQueue 队列中。实际这里有一个类似事务的概念在里面,一次支付行为的payment加到队列后,会自动持久化保存,防止app中断执行后,支付事务丢失。当然这些事情都由 StoreKit 框架来完成,开发者知道就行,不用另外编码。支付过程中可能app会中断,开发者可以在AppDelegate的didFinishLaunchingWithOptions函数中把IAP类初始化,由于初始化里会注册为事务的观察者[[ SKPaymentQueue defaultQueue ] addTransactionObserver : self ];因此可以在app重新打开后继续接收未完成的支付行为的返回消息。
     支付请求的返回要实现 SKPaymentTransactionOBserver 协议,该协议有一个必须实现的接口和四个可选的接口。
     IAPHelper中实现了必选接口- ( void )paymentQueue:( SKPaymentQueue *)queue updatedTransactions:( NSArray *)transactions。其功能是根据支付返回结果的状态transaction. transactionState 来进行分发处理流程,这里的transaction是输入参数中transactions容器中的一个遍历值。用switch case分发处理流程到另外三个可选的接口函数:
     - ( void )completeTransaction:( SKPaymentTransaction *)transaction
     - ( void )restoreTransaction:( SKPaymentTransaction *)transaction
     - ( void )failedTransaction:( SKPaymentTransaction *)transaction
     这三个函数中都进行了日志打印,最后都调用了[[ SKPaymentQueue defaultQueue ] finishTransaction : transaction]来关闭该支付事务。另外前两个函数的中在关闭事务之前都调用IAPHelper的一个封装函数- ( void )provideContentForProductIdentifier:( NSString *)productIdentifier。 该函数做的事情是:把已购项写到 NSUserDefaults 中,然后利用 NSNotificationCenter 把消息 IAPHelperProductPurchasedNotification 广播一下。支付成功或恢复成功后发通知,通过这个消息里的内容,外部类就可以获得相关支付的信息。因此开发者需要注册为该通知的观察者(注册操作需要自己编码完成,要记得在合适的时候删除注册),收到通知后响应。注册为该消息的观察者时要提供一个回调,这个回调函数需要开发者实现。- ( void )productPurchased:( NSNotification *)notification。其输入参数中保存了产品标识,可这样获得: NSString * productIdentifier = notification. object
4. 恢复已购买
     恢复购买的请求的入口函数被封装为- ( void )restoreCompletedTransactions。该函数只有一句[[ SKPaymentQueue defaultQueue ] restoreCompletedTransactions ]。即把恢复请求加入到支付队列中。
     恢复购买的请求的返回在上述 SKPaymentTransactionOBserver 协议中的一个可选接口中已经实现了。即把返回内容写到 NSUserDefaults ,同时发通知。
5. 总结
     开发者导入了IAPHelper之后,自己需要完成的编码工作主要有:
     a. 创建一个xxxxIAPHelper类。可参考原文示例中的相关类,很简单,就是一个单例。在AppDelegate中进行该单例的初始化。
     b. 在自己的类(不是xxxxIAPHelper类)中加入两个私有成员变量。可在.m文件中加。
          NSArray *_products;          NSNumberFormatter * _priceFormatter;
     其中_products是保存查询结果(产品列表)的,示例中是每次程序运行后会发查询请求,请求结果被保存在成员变量 _products 中,这是一个强指针 NSArray* (因为是强引用,所以该值不设置为nil时会一直保留上次查询结果),保存了该应用所提供的全部产品列表,其中的元素是 SKProduct  *,包含了产品的ProductID、本地化名称、价格等级等信息。
     _priceFormatter则是格式化显示数字,主要是为了本地化显示货币(产品的价格)。
     c. 写查询请求中的那个Block。主要在这里实现一些更新显示的逻辑,根据查询结果更新显示。用下面的方式查询。
     [[ xxxxIAPHelper sharedInstance ] requestProductsWithCompletionHandler :^( BOOL success, NSArray *products) {
         // 这里添加需要编码的Block内容,查询结果先保存到_products中,然后加自己的处理逻辑
         if (success) {            _products = products;            // 更新 产品列表并展示相关信息及购买按钮 / 已购状态         }     }];
     d. 写购买按钮的响应处理函数。购买时根据 _products 中的值来构造 SKProduct ,做为支付入口的输入参数。
     e. 注册为消息 IAPHelperProductPurchasedNotification 的观察者。[[ NSNotificationCenter defaultCenter ] addObserver : self selector : @selector (productPurchased:) name : IAPHelperProductPurchasedNotification object : nil ];
     在回调中处理购买完成后的程序逻辑。示例中用了一个Block来遍历产品列表,找出需要更新的项进行处理。(这是又一个Block的使用技巧,可以学习一下:相当于该Block是该容器的迭代器回调)
     在适当的时候记得移除注册。[[ NSNotificationCenter defaultCenter ] removeObserver : self ];
     f. 因为IAPHelper会将购买结果保存在 NSUserDefaults 中,键值即为ProductID,因此可以在需要的时候直接查询 NSUserDefaults
     g. 支付事务观察者一直未移除注册,如果需要移除注册可以这样:[[ SKPaymentQueue defaultQueue ] removeTransactionObserver : self ]。因为示例中在单例初始化时注册的,单例在程序启动后就一直存在,所以未移除注册。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值