苹果内购(IAP)掉单处理防hook以及一些坑1.结束交易finishTransaction[SKPayme

a.支付失败。比如手动取消支付、卡里没钱了等。即SKPaymentTransactionStateFailed状态下。

b.支付成功。票据上传给服务器去做校验后,校验返回结果失败。

c.支付成功。票据上传给服务器去做校验后,校验成功。

但是,一般情况下,请求苹果的票据校验接口,都是由App服务端完成的。加密的原始票据,上传给服务器后,服务器再去请求对应的苹果票据校验接口,拿到解密的票据数据。之后,再解析票据合法性,合法后才告知前端并下发道具。这个校验合法性的逻辑,只有前端通过延迟轮询,才能够获得结果。

理想情况下,我们需要在确保商品已经成功发放到用户手中再调用finishTransaction。但因为服务端的校验结果,前端不能马上知道,有些时候因为网络问题,甚至会校验失败。所以我们可以在请求服务器并且回调结果后,就finishTransaction。这样不至于导致充值队列卡住,但却很容易导致掉单。有利有弊。

在发起充值之前,我们会创建SKMutablePayment对象,并添加到支付队列中。

swift复制代码SKMutablePayment*payment=[[SKMutablePaymentalloc]init];payment.applicationUsername=orderId;//透传参数payment.productIdentifier=_productId;payment.quantity=count;[[SKPaymentQueuedefaultQueue]addPayment:payment];其中,有个applicationUsername参数,是一个透传参数。在你添加支付到支付完成获得SKPaymentTransaction后,这个参数都会存在于transaction.payment.applicationUsername中。在开发的实际应用中,我们往往需要将我们自己服务器的订单号、或者用户ID跟苹果的订单关联。我们可以通过缓存读写的形式,但也可以通过applicationUsername这个透传字段来传递参数。比如我们把orderID(订单号)写入透传字段中。我们在创建订单发起支付,到完成支付后,我们都能关联到这个订单。

这个透传字段,看似是非常方便地解决了我们的关联问题。但是,实践中我们却发现,applicationName这个参数在支付完成的回调的时候有可能为nil。以下场景是已经发现的情况:

所以我们可以采用“透传字段+双重keychain”的多重策略。如下所示:

a.尝试从transaction.payment.applicationUsername中读取orderId,如果uid为orderId,则继续下一步;

c.再次尝试从keyChain中恢复orderId,而这个keyChain的值是创建订单时缓存的。

d.在每次启动App和每次发起充值之前,都检查交易队列里是否有没有finished的交易(非订阅的)。如果有则处理这笔交易,重新上传票据给服务器校验。

比如一个商品按钮,被飞速连续点击多次。这时也会调起多次IAP购买。如果不涉及到APP自身的订单的逻辑,充值然后拿到票据校验,苹果一整套逻辑下来是没什么问题的。但是,基本每个APP都会让IAP订单跟自身服务器的订单系统做关联。

如果本地只缓存一个订单号,然后在校验订单请求的时候作为请求参数,在当前情况下,就会导致订单号与实际的receipt_data关联错误的情况;

如果本地通过队列缓存订单,或许能避免上面的情况,但队列的计算也会考验开发者的计算能力,队列内订单判断失误也会导致掉单;

如果通过透传参数applicationUsername传递订单号或者其他信息,又会遇到applicationUsername为空的情况。

当然,办法总是有的,我这里暂时没想出一个完美的处理连续购买商品且能不掉单的方案。相对地,本人更提倡的是,避免“连续购买多个商品”的情况,不让用户触发这种情况。

方法一:一次支付完成之前,只允许一笔订单在支付队列中操作。订单支付完成后,才能发起新的支付。

最简单的方法,就是将按钮enable。但前提是UIKit控件直接触发支付。如果是SDK,或者unity、cocos游戏则不行。

swift复制代码-(IBAction)clickBtn:(UIbutton*)sender{sender.enabled=NO;[[PayKitshareKit]startPay:^(BOOLresult){sender.enabled=YES;}];}也可以采用属性标记,BOOL值。

swift复制代码if(isOrdering){NSLog(@"订单正在支付中...");return;}isOrdering=YES;[[PayKitshareKit]startPay:^(BOOLresult){if(支付完成){isOrdering=NO}}];方法二:用户一点击按钮后就展示蒙版。防止用户再次点击按钮。订单支付完成后,再关闭蒙版。

方法三:设置在1s内,只能调起一笔支付(需搭配方法二使用)

swift复制代码[selfperformSelector:@selector(payPlatformWithModel:)withObject:payModelafterDelay:1.0];-(void)payPlatformWithModel:(id)payModel{[[MaskViewshareView]showView];[[PayKitshareKit]startPay:^(BOOLresult){if(支付完成){[[MaskViewshareView]hideView];}}];}个人建议:防止支付多次触发,建议所有方法都用上。多多益善。

如果开发者并没有采用“屏蔽多次触发支付”的方法,而是支持多笔订单连续调起,通过支付队列去正确匹配订单号与苹果票据的形式(这的确是技术上的正统方法),你就很可能踩到苹果爸爸给你埋的另一个坑。线上环境下可能触发,多笔订单合并付款的情况。比如你点击了6元商品和30元商品购买,苹果会让你输入密码付款36元。付款成功后,苹果只会回调你一个transaction,然后receipt_data解析后in_app内会有两笔支付数据。但对于服务器而言,6元和30元是两笔订单,因为是分别创建的订单。那我到底用那个订单号去匹配票据呢?或许能匹配上其中一个订单,但却很难匹配上两个订单(苹果将app服务器的两笔订单当成1比订单处理了),那势必会导致其中一个订单掉单。你或许可以通过下次启动[SKPaymentQueuedefaultQueue]时去重新校验订单进行补单,或者直接等用户联系客服后进行服务器手动补单。

这个问题没有一个很好的解决办法。所以个人建议还是采用“屏蔽多次触发支付”的方法。

苹果的接口,在线上环境下,即使网络不错的情况,也会出现回调很慢、甚至请求失败的情况。在以下几个情况下,我们会涉及到跟苹果请求:

场景一:通过SKProductsRequest获取商品的时候,请求失败。

建议不通过SKProductsRequest去获取SKPayment对象,而是手动创建,绕过这一步。

swift复制代码SKMutablePayment*payment=[[SKMutablePaymentalloc]init];payment.applicationUsername=orderId;//透传参数payment.productIdentifier=_productId;//商品ID直接传字符串payment.quantity=count;[[SKPaymentQueuedefaultQueue]addPayment:payment];场景二:支付队列addPayment后,并没有调起充值而直接回调"充值失败";或者在输入密码后由于网络问题回调“充值失败”(实际并没有扣款)。

因为这个时候,这笔订单实际并没有发生任何扣款,所以不用继续这笔订单,可以直接finishTransaction。

场景三:请求苹果接口校验票据失败。

因为票据校验逻辑,是由服务端异步完成的。由上所说,充值成功后最好的finishTransaction的时机,应该是在票据校验成功并且道具(权益)已经下发了,再finish。但有些时候为了避免等待,我们也会在请求服务端去校验,服务端返回receipt_data上传成功时,就会finishTransaction。但后者的情况下,如果在服务器都请求苹果校验接口失败,而客户端已经finishTransaction了,就会导致掉单。这种情况下,服务端应该给这笔订单加上“已付款,未到账”的标识,前端也可以上报一个自定义的日志告诉服务器“这笔订单异常”。在客户端因为提前finishTransaction导致已经无法再次发起校验时,等用户找上客服后,服务端需要根据订单的这个状态进行手动补单。

当我们调用[[SKPaymentQueuedefaultQueue]addTransactionObserver:self]开启支付队列时,支付队列会自动检查是否有没有finish的transaction,并回调给我们。那在哪儿开启这个队列监听合适呢?

swift复制代码[[SKPaymentQueuedefaultQueue]addTransactionObserver:**self**];注意这里是调用addTransactionObserver而不是restoreCompletedTransactions。因为这时候支付队列还没有初始化,直接调用restoreCompletedTransactions是没效果的。

如果有个未结束的交易,会回调这笔交易最新的状态。如果是Pruchasing状态,则输入密码,成功后继续走校验逻辑;如果是Pruchased状态,则上传票据给服务器校验。注意:上面提到的applicationUserName这个透传参数有可能在这种有未结束的交易的情况下为空值,所以注意订单数据要匹配。

swift复制代码[[SKPaymentQueuedefaultQueue]restoreCompletedTransactions];描述同上。

以上的办法,都只是尽量减少掉单的发生,并不能完全解决掉单问题。每个app的逻辑不同,坑也各不相同。掉单之后如何补单?补给那个账号?补给哪个订单?很多问题都需要结合具体问题具体分析。

THE END
1.苹果试玩赚钱软件任务多单价高的平台排行榜苹果手机试玩赚钱是目前非常火的一种手机赚钱方法,但是众多试玩赚钱app参差不齐,这里就是把那些任务多、单价高的平台整理出来,总结一个苹果试玩赚钱软件任务多单价高的平台排行榜供大家参考。https://www.yixiangzhuan.com/special/36.html
2.最新ios应用双开软件有哪些苹果双开软件免费下载合集iOS应用双开软件有哪些-苹果双开软件免费下载合集随着智能手机的普及,人们对手机功能的需求也越来越高。在日常生活中,我们经常需要使用多个社交账号、游戏账号等,但是iOS系统并没有原生支持双开功能,这就导致了很多用户的困扰。为了解决这个问题,市面上出现了很多iOS应用双开软件,它们可以帮助用户在一部手机上同时登录多个http://leondns.com/m/article/20250203/2901045.shtml
3.苹果手机游戏盒子app推荐苹果游戏盒子手机版下载io九游苹果版 等级: 大小:79.1M更新时间:2024-09-19 AppStore 下载 简要: 九游app苹果版是专门为使用ios系统的玩家们提供的一款游戏助手,提供了部落冲突、海岛奇兵、云上城之歌等多款手游的游戏圈子,这样玩家们不仅可以与其他网友们一起讨论玩法,交流心得,还能与游戏商那边的开发者进行反馈,从而更好的得到你想要的游https://www.ddooo.com/zt/wfsyziff.htm
4.iOSrunloop处理卡顿iosrunloop的使用嘲保持程序持续运行。程序一启动就会开一个主线程,主线程一开起来就会跑一个主线程对应的RunLoop,RunLoop保证主线程不会被销毁,也就保证了程序的持续运行。 处理App中的各种事件(比如:触摸事件,定时器事件,Selector事件等) 。 节省CPU资源,提高程序性能。程序运行起来时,当什么操作都没有做的时候,RunLoop就告诉CPU,https://blog.51cto.com/u_16099341/9345191
5.大小单双app下载软件大全下载苹果版大小单双app下载软件大全{9123}好彩支持:64/128bit系统类型:IOS/安卓通用版/winall。{9123}第一步:访问好彩《大小单双app下载软件大全》官网首先,打开您的浏览器,输入《大小单双app下载软件大全》的官方网址 。您可以通过搜索引擎搜索或直接输入网址来访问。{hchttp://www.sintoro.cn/
6.苹果ai写作神器免费app一、苹果ai写作神器免费app 在数字时代,人工智能技术已经无处不在,包括在写作方面。苹果公司最近推出了一款名为“苹果AI写作神器”的免费APP,让写作变得更加容易和高效。 这款APP的主要功能是利用人工智能技术,为用户提供高质量的写作建议和指导。用户只需要输入他们要写的文章或段落,苹果AI写作神器就会分析文本,并提供https://tool.a5.cn/article/show/80588.html
7.苹果AppStore财年和账单那些趣事腾讯云开发者社区根据上文 2.3 最后一点提到:苹果财务日历只有364天,而正常年有365和366日,所以,苹果每5年必须在12月的账单月增加一周。 2017年周期增加了一周: AppStore-Financial-06.png 所以,计算一下 2017 +5 年 = 2022 年,但 2022 年财年如上文提到,22Q1并没有增加多一周,估计2023年增加? https://cloud.tencent.com/developer/article/2003041
8.同一款App的会员,为什么苹果和安卓用户价格不一样?全文共7600字,10张图表,分为6个部分:1、价格歧视;2、“苹果税”;3、两个阵营;4、安卓抽成更高?;5、孰是孰非?;6、终局? 1、价格歧视 首先,军师要说一个可能绝大多数普通消费者都不知道的事实:苹果和安卓用户的爱奇艺会员价格是不同的(如下图),苹果用户的会员价格平均要高20%以上,以连续包年价格为例https://36kr.com/p/669086077009664
9.苹果给推特开后门!AppStore唯一的单字母应用“X”来了据悉,由于未遵循苹果的「铁令」,这「破例」之举让“X”成为目前苹果 App Store 内唯一的单字母应用。 更名受阻,遭到苹果「拦路」 半个月前,马斯克给推特换了个耳目一新的新标志 ——“X”,只为将其重塑为一个集音频、视频、信息、支付和银行服务于一体的「万能应用程序」。 https://blog.csdn.net/csdnsevenn/article/details/132064765
10.你不知道AppStore原来还有这些小窍门(全文)苹果iPhone6S最近苹果的App Store出现搜索故障,据了解在故障期间,有超过65%的应用程序失去10%以上的下载,大约有15%的应用程序失去50%的下载。而这次事件来看造成如此大的下载损失,从另外一方面来看也证明App Store在我们日常生活中有多么的重要。那么当App Store遇到问题例如下载慢、切换地等,该如何解决呢?今天就带大家学习App https://4g.zol.com.cn/582/5827822_all.html
11.登顶苹果社交榜第一的App,没想到是个元宇宙版的QQ秀?于是就好奇之下,去 App Store 上搜索了一下,这款叫做啫喱的社交软件。没想到这款App 已经登顶社交软件第一名了。。。 要知道 App Store 的社交软件榜单里,可是有微信和 QQ 这两个 “ 巨无霸 ” 存在,能够登顶社交排行榜第一的 App 那可没一个是省油的灯。 https://m.thepaper.cn/newsDetail_forward_16670087
12.欧易app苹果下载欧易app苹果最新版下载v6.103.0交易平台欧易app苹果版是一款非常权威的数字货币交易软件,该软件拥有各种虚拟数字货币产品,里面包括大量的虚拟币,你可以在上面进行各种比特币、虚拟币、数字币的购买和交易,从比特币、币币到其他数字币,你可以在这里找到各种不同类型和潜力的币种。欧易app涵盖的门类和玩法丰富多样,利用全新一代区块链技术,可以保证你的虚拟资产https://www.jb51.net/blockchain/867987.html
13.苹果应用商城“藏”成人App正常下载后竟能玩“变身”近日,有市民反映在苹果应用商城内,有外表看似正常的工具软件,下载后却变为成人色情App。新黄河记者发现,为使用户正常下载,在软件网址介绍中,特意注明“当在ios商店中下载时,由于应用规则原因,点击链接后的图标可能不一样,此属于正常现象,请放心安装。”而在下载后,该软件则直接变身为成人色情App。随后记者在苹果应用http://news.hnr.cn/shxw/article/1/1570571382058061826
14.年货节网店市场营销方案(通用12篇)全场灯光熄灭,表演者每人手上托一支小红烛走入会场,现场营造出一种温暖沁心的氛围,同时将观众的注意力吸引到整台晚会上来。 2.主持人上场(暂定2女1男):时间:1分半 开场白: 女1:伴随着这首“祈祷”的优美旋律,我们走进了~年的春天; 男:当我们满怀喜悦的告别~,我们收获最多的是“成长”,懂得最多的是“成https://www.unjs.com/fanwenku/417527.html
15.安卓秒变ios的app有哪些安卓秒变ios的app推荐安卓秒变ios的app有哪些?这些软件能够让安卓手机用户描边苹果系统,有了这些,用户能够在手机上下载各种苹果软件,使用苹果主题,各种图片还能变成和苹果一样的像素模式,喜欢苹果手机却没办法拥有苹果手机的用户一定要下载这类软件,轻轻松松使用苹果的各种功能,体验苹果手机系统,给大家一个全新的手机体验,需要的用户快来这里http://www.downcc.com/k/azmbiosdapp
16.苹果手机试玩赚钱App(任务多排名第一的iOS赚钱平台)在当前数字化时代,手机不仅仅是我们日常沟通的工具,更是我们赚取额外收入的平台。特别是苹果手机用户,他们可以借助各种iOS赚钱App,轻松实现边玩手机边赚钱的目标。下面,我们将为您介绍几款任务多、排名靠前的iOS赚钱平台,让您在享受科技带来的便利的同时,也能获得一定的经济回报。 https://maimai.cn/article/detail?fid=1853537753&efid=jaxALbw2A1ZMkjIyt1kd8g