iOS 内付费(in-app purchase)--非消耗品的购买与恢复

2023-11-30 16:58

本文主要是介绍iOS 内付费(in-app purchase)--非消耗品的购买与恢复,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这里写图片描述


iOS内付费的功能对于一个app来说是非常重要的,如果在这一环节出了一些致命的问题,那就很可能会影响app的推广和公司的利益了。

我在很早之前写过一篇关于iOS内付费的文章(文章地址),在那篇博客中讲述了如何在苹果后台生成iOS内付费商品,以及在我们的app工程中如何去添加相应的内付费代码。但是,在后来的日子里面我发现网友在关于内购功能上遇到的问题比我想象的还要多,其中很大一部分都是一些很简单的问题,比如说签名使用的不正确,内购商品ID不正确,bundleID没有和签名一致,苹果账号没有补充完整银行税务信息等导致的,只要简单的修改一下就能解决以上问题。

另外,很多app项目创建的内购商品都是以“消耗品“ ,这种类型的商品为主,不过有的网友也遇到了其他的问题,他在app中创建了几个非消耗品的内购商品,然后提交苹果审核的时候,却被苹果打回了,原因是苹果要求开发者对这种非消耗品的商品增加一个“恢复“的按钮。

Apple 打回的原文如下:

Business - 3.1.1We found that your app offers In-App Purchase(s) that can be restored but does not include a "Restore Purchases" feature to allow users to restore the previously purchased In-App Purchase(s), as specified in the "Restoring Purchase Products" section of the In-App Purchase Programming Guide"Users restore transactions to maintain access to content they've already purchased. For example, when they upgrade to a new phone, they don't lose all of the items they purchased on the old phone. Include some mechanism in your app to let the user restore their purchases, such as a Restore Purchases button."To restore previously purchased In-App Purchase products, it would be appropriate to provide a "Restore" button and initiate the restore process when the "Restore" button is tapped by the user.Before You Submit

今天,我在这篇文章中就来针对上述的苹果打回的问题做出解决方案。


“非消耗品的购买和恢复” 该如何操作

创建非消耗品(non-consumable)

在 iTunesconnect 后台中创建一个非消耗品,根据内购商品所需要的内容编辑完整。创建的选项如下图所示:

这里写图片描述

内购流程梳理

非消耗品第一次购买的逻辑和消耗品是一样,我们先来理一遍内购的流程,首先在代码中我们一定要在内购初始化的地方加上这句代码:

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

不然购买成功和失败的任何回调你都收不到。在初始化之后,要去苹果服务器那获取我们所要提供给用户的详细商品信息,代码逻辑如下:

- (void) requestProductData{if(!self.mRequestProductDataObjects || self.mRequestProductDataObjects.count == 0){return;}if ([SKPaymentQueue canMakePayments]){NSArray *product = nil;product = [NSArray arrayWithArray:_mRequestProductDataObjects];NSSet *nsset = [NSSet setWithArray:product];SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];request.delegate = self;[request start];}...
}

在保证商品id正确的情况下,我们的程序会把获取到的商品信息回调到此函数中:

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response NS_AVAILABLE_IOS(3_0);

解析商品信息的逻辑,我这边就不细说了,要看详细的代码,就去我这篇文章中 iOS应用程序内购/内付费看吧!

在获取到商品信息之后,我们就可以开始进行购买了,购买的逻辑函数如下:

- (void) purchase:(NSString*) productId
{if(productId.length == 0 || !productId){return;}SKProduct * _payProduct  =nil;if ([SKPaymentQueue canMakePayments]){for (SKProduct * payment in self.purchasableObjects) {if ([productId isEqualToString:payment.productIdentifier] ){_payProduct = payment;break;}}}if(!_payProduct){return;}SKMutablePayment * payment = [SKMutablePayment paymentWithProduct:_payProduct];[[SKPaymentQueue defaultQueue] addPayment:payment];
}

上述函数的内部逻辑走完以后,就会回调此方法了:

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{for (SKPaymentTransaction *transaction in transactions){switch (transaction.transactionState){case SKPaymentTransactionStatePurchased:[self completeTransaction:transaction];NSLog(@"支付成功");break;case SKPaymentTransactionStateFailed:[self failedTransaction:transaction];NSLog(@"支付失败");break;case SKPaymentTransactionStateRestored:[self restoreTransaction:transaction];NSLog(@"交易恢复处理");default:break;}}
}

在这个回调函数的内部逻辑里面,分别有对购买成功,购买失败,恢复交易的处理。好了,经过一遍简单的梳理以后,想必你已经在心中有了一个大概,接下来就是我们的重头戏了。

恢复按钮怎么添加?

正常情况下,非消耗品的内购商品在购买成功后,应该把 “购买” 字样变成 “恢复” 字样,当用户完成一次购买以后,就可以永久使用啦!那在什么时机去修改这个按钮呢。

当非消耗品完成一次购买以后,再次去点击购买的话,系统会提示你已经购买了此项目,如图:

这里写图片描述

为了确保我们的app在每次运行起来后,内购商品列表能正确显示,哪些非消耗商品是已经购买过的,我们得在内购功能初始化的地方(就是添加监听函数下面)调用该函数,来获取哪些商品是已经买过的:

[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];

该函数调用后会恢复之前的交易,程序会直接进入到函数updatedTransactions的回调:

 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{case SKPaymentTransactionStateRestored:.....}

然后再走到此回调函数:

- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue

我们可以给上面函数中添加如下逻辑,用一个NSMutableArray来存储苹果回调过来给我们已经购买过的非消耗品的商品信息:

- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{purchasedItemIDs = [[NSMutableArray alloc] init];NSLog(@"received restored transactions: %i", queue.transactions.count);for (SKPaymentTransaction *transaction in queue.transactions){NSString *productID = transaction.payment.productIdentifier;[purchasedItemIDs addObject:productID];NSLog(@"%@",purchasedItemIDs);}
}

在这里我们已经获取到了所有已经购买过的非消耗品的 transactions,那最后一步就是回调app界面去修改按钮名称咯。那有些人会问,如果我换了设备怎么办,其实也很简单,iOS内购商品是跟着你的Apple ID走的,你换到新设备后登录你的Apple ID帐号,启动app就会走到restoreCompletedTransactions函数,苹果还是会给你推送过来你购买过的非消耗品信息,然后再去修改app按钮是显示 购买 还是 恢复 。

最后关于在app内购买非消耗品 ,道具应该怎么下发,我做一下自己的理解说明吧!非消耗品不管是第一次购买,还是恢复购买,苹果验证票据返回过来的信息都是一致的,如图所示:

这里写图片描述

所以,我们在第一次购买非消耗品的时候,待苹果服务器票据验证成功后,服务器要将玩家的账号信息(非Apple ID账号,再说你app也获取不到)和 该商品ID保存在数据库中;玩家若换设备或者卸载了app以后,再次想要获取该道具,我们就可以直接根据玩家的账号信息和商品ID去数据库中查找,若已经购买过了,就可以直接下发道具。

总结

关于iOS内购的功能其实代码就那么些,但是如果你真的要做到内购功能很健壮,例如购买东西时不丢单,游戏充值到账等,确实要花很多精力去研究,这不单单是客户端的任务,还包括服务器如何保存票据,丢单的时候如何去补单这些操作。好了,写了这么些,不早了也该歇歇了,若有什么问题的话,请加以下公众号联系我。


好了。祝大家生活愉快。多多收获友谊和爱情。如果想获取更多的讯息,请扫描下方二维码关注我的微信公众号:
这里写图片描述

这篇关于iOS 内付费(in-app purchase)--非消耗品的购买与恢复的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/437805

相关文章

使用Python实现网络设备配置备份与恢复

《使用Python实现网络设备配置备份与恢复》网络设备配置备份与恢复在网络安全管理中起着至关重要的作用,本文为大家介绍了如何通过Python实现网络设备配置备份与恢复,需要的可以参考下... 目录一、网络设备配置备份与恢复的概念与重要性二、网络设备配置备份与恢复的分类三、python网络设备配置备份与恢复实

MySQL使用binlog2sql工具实现在线恢复数据功能

《MySQL使用binlog2sql工具实现在线恢复数据功能》binlog2sql是大众点评开源的一款用于解析MySQLbinlog的工具,根据不同选项,可以得到原始SQL、回滚SQL等,下面我们就来... 目录背景目标步骤准备工作恢复数据结果验证结论背景生产数据库执行 SQL 脚本,一般会经过正规的审批

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

WiFi6时代来临! 华三H3C NX54路由器还值得购买吗?

《WiFi6时代来临!华三H3CNX54路由器还值得购买吗?》WiFi6时代已经来临,众多路由器厂商也纷纷推出了兼容WiFi6协议的路由器,今天我们将深入体验H3CNX54路由器,这款由知名企业... 随着科技的发展,WiFi6逐渐走进了我们的日常生活之中,相比WiFi5来说,WiFi6拥有更高的带宽、更高

通过ibd文件恢复MySql数据的操作方法

《通过ibd文件恢复MySql数据的操作方法》文章介绍通过.ibd文件恢复MySQL数据的过程,包括知道表结构和不知道表结构两种情况,对于知道表结构的情况,可以直接将.ibd文件复制到新的数据库目录并... 目录第一种情况:知道表结构第二种情况:不知道表结构总结今天干了一件大事,安装1Panel导致原来服务

MySQL InnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据

《MySQLInnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据》mysql的ibdata文件被误删、被恶意修改,没有从库和备份数据的情况下的数据恢复,不能保证数据库所有表数据... 参考:mysql Innodb表空间卸载、迁移、装载的使用方法注意!此方法只适用于innodb_fi

mysql通过frm和ibd文件恢复表_mysql5.7根据.frm和.ibd文件恢复表结构和数据

《mysql通过frm和ibd文件恢复表_mysql5.7根据.frm和.ibd文件恢复表结构和数据》文章主要介绍了如何从.frm和.ibd文件恢复MySQLInnoDB表结构和数据,需要的朋友可以参... 目录一、恢复表结构二、恢复表数据补充方法一、恢复表结构(从 .frm 文件)方法 1:使用 mysq

mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespace id不一致处理

《mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespaceid不一致处理》文章描述了公司服务器断电后数据库故障的过程,作者通过查看错误日志、重新初始化数据目录、恢复备... 周末突然接到一位一年多没联系的妹妹打来电话,“刘哥,快来救救我”,我脑海瞬间冒出妙瓦底,电信火苲马扁.

Git中恢复已删除分支的几种方法

《Git中恢复已删除分支的几种方法》:本文主要介绍在Git中恢复已删除分支的几种方法,包括查找提交记录、恢复分支、推送恢复的分支等步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录1. 恢复本地删除的分支场景方法2. 恢复远程删除的分支场景方法3. 恢复未推送的本地删除分支场景方法4. 恢复

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat