抛砖引玉,原文:http://jingwei6.me/2015/06/17/iap.html
自从用iMac以来,再也没有在电脑上玩儿过游戏,即使是最喜欢的飞行模拟类的游戏。周末在App Store上看到一款排名靠前的直升飞机模拟游戏--Helicopter Sim - Hellfire Squadron,尽管mac上的游戏不能期望太高,不过聊胜于无,于是下载下来玩儿了一下,配合我那已经封尘多年的游戏手柄,几局下来,已能熟练控制,pitch/yaw/roll,加上攻击时的摇滚音乐,也让我乐在其中。不过很快缺省的关卡都被我玩完了,要玩儿更多的关卡只能应用内付费购买了。
这自然激起了我对应用内付费(IAP)的兴趣。关于IAP的知识,在苹果的开发者网站都能找到。 IAP部署图如下所示:
苹果通过提供StoreKit框架来帮助客户端实现IAP,StoreKit和App Store之间的通讯,主要提供两个功能:
- StoreKit从App Store取回可以提供的内购项目
- StoreKit向App Store提出付费请求,并把付费完成的消息通知客户端
至于客户端和“Your Server”的通讯,其实跟IAP框架没什么关系,开发者根据自己的情况,决定用户付费成功后,是从服务器下载数据,还是直接暴露新的功能给用户。Helicopter Sim这款游戏,内购的关卡并不需要从服务器下载。
那么我们就有机会在一次失败的购买过程中,在Store Kit把购买失败的消息通知给客户端之前,把购买失败的消息篡改成购买成功的消息。
Store Kit中购买的状态有以下5种,
enum {
SKPaymentTransactionStatePurchasing,
SKPaymentTransactionStatePurchased,
SKPaymentTransactionStateFailed,
SKPaymentTransactionStateRestored,
SKPaymentTransactionStateDeferred,
};
typedef NSInteger SKPaymentTransactionState;
它们都封装在SKPaymentTransaction中,通过SKPaymentTransactionObserver的回调函数
(void)paymentQueue:(SKPaymentQueue )queue updatedTransactions:(NSArray )transactions
告诉给客户端。
那么我们就可以在上述回调函数中加入如下逻辑:
if (SKPaymentTransaction.transactionState == SKPaymentTransactionStateFailed)
{
SKPaymentTransaction.transactionState = SKPaymentTransactionStatePurchased
}
具体的实现方法,发挥一下想象,可以用补丁在代码中加入上述逻辑,也可以用调试器动态的修改内存或者寄存器。 上述逻辑准备好以后,点击内购项目进行购买,在弹出对话框要求输入App Store的密码的时候,点击取消,这时上面的逻辑就会起作用。 当这一切结束的时候,你就会发现,你点击的关卡已经出现在你的游戏中:)