中秋节快到了,那帮做游戏的又想让大家氪金,太坏了!

举报
HelloWorld杰少 发表于 2022/08/24 09:57:40 2022/08/24
【摘要】 前言Hello, 小伙伴们,中秋节快到了,在这里提前祝大家中秋节快乐啦!说起这种带有传统特色的节日,游戏公司一定会推出带有相关节日元素的氪金道具,来让玩家消费,譬如万圣节南瓜,中秋节月饼,春节年兽等等,那我今天就来给大家说说在 iOS 系统中氪金到底是怎么一回事呢! In-App_Purchase 介绍iOS 的应用内购买(In-App_Purchase)功能简称: IAP,一直是付费 A...

前言

Hello, 小伙伴们,中秋节快到了,在这里提前祝大家中秋节快乐啦!

说起这种带有传统特色的节日,游戏公司一定会推出带有相关节日元素的氪金道具,来让玩家消费,譬如万圣节南瓜,中秋节月饼,春节年兽等等,那我今天就来给大家说说在 iOS 系统中氪金到底是怎么一回事呢!

In-App_Purchase 介绍

iOS 的应用内购买(In-App_Purchase)功能简称: IAP,一直是付费 APP 的重要组成模块,尤其是对游戏类的应用,因为苹果规定虚拟类货币必须得使用 IAP 支付,否则该应用就不能通过苹果的审核,所以 IAP 一直是众多游戏开发者需要集成的功能;回顾这几年的开发趋势 Objective-C 已经慢慢的失去了热度,iOS 开发者们逐渐的拥抱了 Swift,同样也包括我自己,于是趁这个机会,干脆去实现一个基于 Swift 语言的开源 IAP Framework 吧!

效果

演示氪金成功:

image

演示氪金失败:

image

开源地址

项目名称 PurchaseX

需求分析

在 iOS 应用内集成过 IAP 的同学肯定知道 IAP 具体的工作流程,不知道的也不要紧,这就为大家简单的介绍一下,请看思维导图:

image

通过上面的思维导图,需求应该很清晰了,整体概括为以下几点需求:

  1. 根据商品 ID 去请求商品信息,并将 AppStore 返回的商品信息回调给客户端去显示;
  2. 发起支付,如果支付失败,则发送回调信息给客户端,并提示支付失败;如果支付成功,则进入下一步验证票据;
  3. 提供本地验证票据,验证成功则发送回调信息给客户端,提示购买成功,反之则提示购买失败;
  4. 提供远程验证票据,验证成功则发送回调信息给客户端,提示购买成功,反之则提示购买失败;

明确需求以后,就可以着手开发了,因为这是个开源项目,而且代码量有点多,所以我在这里就不一一解释了,下面把主要的几个功能说明以下,大家感兴趣的话,可以去阅读源码。

监听 App Store 消息

首先,第一步要做的事情就是注册监听,这个监听机制会让我们的应用能够接收交易成功,失败还有恢复购买的消息;

我用 Self 来作为一个 Observer, 并把它加入到 StoreKit payments queue 中:

SKPaymentQueue.default().add(self)

获取商品信息

实例化对象:

var purchaseXManager = PurchaseXManager()

请求商品信息,该接口会先在本地去读取商品ID配置文件,并用数组的形式保存,然后向 AppStore 请求商品信息。回调将会以闭包的形式通知客户端, 参数记录了当前请求商品的状态,可以用 if 或者 switch 的方式来罗列这些状态。

purchaseXManager.requestProductsFromAppstore { notification in
            if notification == .requestProductsStarted {
            	print("Request Products Started")
            } else if notification == .requestProductsSuccess {
                print("Request Products Success")
            } else if notification == .requestProductsFailure {
                print("Request Products Failed")
            } else if notification == .requestProductsDidFinish {
                print("Request Products Finished")
            } else if notification == .requestProductsNoProduct {
                print("No Products")
            } else if notification == .requestProductsInvalidProducts {
                print("Invalid Products")
            }
        }

最终,当收到的状态为 requestProductsSuccess 时,表明商品信息请求成功,最终的商品会被保存在 purchaseXManager 的属性 products 中,定义如下:

// MARK: Public Property
    /// Array of products retrieved from AppleStore
    @Published public var products: [SKProduct]?

购买

用户发起支付时,调用此接口,并传参要购买的商品ID;回调将会以闭包的形式通知客户端, 参数记录了当前购买的状态,可以用 if 或者 switch 的方式来罗列这些状态。

purchaseXManager.purchase(product: purchaseXManager.product(from: product.productID)!) { notification in
            if notification == .purchaseSuccess{
                print("Purchase Success")
            } else if notification == .purchaseCancelled {
                print("Purchase Cancelled")
            } else if notification == .purchaseFailure {
                print("Purchase Failed")
            } else if notification == .purchaseAbort {
                print("Purchase Abort")
            } else if notification == .purchasePending {
                print("Purchase Pending")
            }
        }

在收到回调参数是 purchaseSuccess 时,表示购买成功,接下来可以继续进行票据验证的工作;如果收到其他状态,则需要提示客户端当前购买遇到了麻烦。

恢复购买

当你的应用程序商城里有非消耗品的时候,就需要加上一个恢复购买的功能;如果用户换了手机或者卸载又安装了你的 App, 那就需要在应用内恢复这些商品的购买状态;restorePurchase 这个接口能够帮您实现需求;回调将会以闭包的形式通知你,当回调参数是 purchaseRestoreSuccess 则表示恢复购买完成,否则就需要重新再试。

purchaseXManager.restorePurchase { notification in
            switch notification{
            case .purchaseRestoreSuccess:
                print("Restore Success")
            case .purchaseRestoreFailure:
                print("Restore Failed")
            default:
                break
            }
        }

验证票据

一旦你完成了购买,你就需要去验证票据,来保证此次购买的流程是正常的,Apple 提供验证票据的方式有俩种,一种是在设备上验证,也就是我们所说的本地验证;还有一种就是将票据用 Http 传递给 AppStore 去进行验证,俩种方式在此都有方法支持。

本地验证

回调将会以闭包的形式通知你,如果验证成功,回调的参数中会包含具体的票据信息,来供开发者做进一步的逻辑处理,譬如 subscriptions 类型的商品。

/// validate locally
                purchaseXManager.validateReceiptLocally { validateResult in
                    switch validateResult {
                    case .success(let receipt):
                        print("receipt:\(receipt)")
                    case .error(let error):
                        print("Validate Failed:\(error)")
                    }
                }

远程验证

回调将会以闭包的形式通知你,如果验证成功,回调的参数中会包含具体的票据信息,来供开发者做进一步的逻辑处理,譬如 subscriptions 类型的商品。

/// validate remotelly
purchaseXManager.validateReceiptRemotely(shareSecret: "put your share secret key", isSandBox: true) { validateResult in
                    switch validateResult {
                    case .success(let receipt):
                        print("receipt:\(receipt)")
                    case .error(let error):
                        print("Validate Failed:\(error)")
                    }
                }

扩展接口

除了以上的这些接口,PurchaseX 还提供了一些扩展方法,让开发者可以更方便的集成内购功能,来认识一下吧!

商品是否已经初始化

if purchaseXManager.hasProducts {
	....
}

根据商品 ID 返回该商品对象

public func product(from productId: String) -> SKProduct?

刷新票据

public func refreshReceipt(completion: @escaping(_ notification: PurchaseXNotification?) -> Void)

根据传参商品 ID,获取该商品是否已经购买过

public func isPurchased(productId: String) -> Bool

最后

iOS 内购是每个苹果开发者都避不开的功能,里面的坑也是跳出一个又跳进另一个,希望我这个开源项目能帮助你避开这些坑。
此次分享的仅仅是 1.0 版本,所以代码有些地方写的不是很健壮,在日后我会继续维护这个项目;另外,关于 iOS15 新的 StoreKit2 也会尽快肝出来分享给大家;最后,如果你觉得此文对你有一丁点帮助,请记得一键三连啊!

请给我的开源项目:PurchaseX 点个 🌟 吧!

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。