有没有接苹果内购(Apple In-App Purchase)的完美方案

购买的票据 是由苹果异步推送过来的
除非是 用户只能一笔 一笔购买,
完成一笔才能继续购买下一笔,
一个道具购买没完成 不能再次购买这个道具,但可以购买其他道具

你的设计思路不对啊;
如果你是用购买某一个具体的物品作为一个真实的苹果内购订单,那么肯定是不妥的。
应该是购买N个宝石,10N个宝石这样。然后 用宝石去兑换物品。

另外,即使是购买同一个物品,那也是有购买时间的,即使不管购买时间,如果是同一个产品,你就算订单号对错了,那么也无所谓啊。两个同样的苹果,哪个先吃,哪个后吃,总数不变啊

商品 基本是 10个宝石 50个宝石 100个宝石
先买 10个宝石 ,这个交易必须完成后 才能再次购买 10个宝石
如果 10个宝石 这个交易没完成,则不能再次购买 10个宝石 但可以买 50个宝石

为啥买了10个宝石后,如果失败就不能继续买呢?
如果纯讨论技术,暂时忽略体验问题。退一万步,你即使搞不清哪个订单是先买,哪个后买,也无所谓啊。前面10个宝石失败,后面10个宝石成功了。 就算你把后面十个宝石当成前面的,有啥关系呢。。。。

吐槽一下,creator3.x为什么写个按钮的点击事件都这么麻烦?

需要用这个 购买项ID 做 票据和订单号 匹配的 key

这个无所谓啊 都是冲100个宝石。 下一次启动,恢复上一个订单,也是100个宝石。加起来总数一致。
说明:苹果订单里面是有购买时间的,你完全可以根据这个来匹配

https://developer.apple.com/documentation/storekit/skmutablepayment/1506088-applicationusername

applicationUsername 可以关联用户订单,可是很容易丢失(能解决一小部分吧)

最好的的办法还是拉起支付之前存储订单号,意外中断app ,再次启动app根据回调交易结果匹配此次交易的订单号,把订单号和票据发送服务端验证

即使同一个内购项前一次校验失败,也没必要限制玩家不能继续购买。只要你还没有向苹果服务器confirm玩家的订单,那都可以把这个订单的receipt拿过来重新尝试校验。只要校验成功了给玩家发就是了,没必要阻止玩家购买同一个内购项。反正同一个内购项,先发哪个后发哪个订单没影响的。

明白楼主的意思,漏单的订单号和支付凭证要怎样对应起来做精准补单这样子吗?验证单据这个一般是服务器处理的。之前的处理方式是把漏掉的凭证再重新传给服务器… 楼主说的这个我也纠结过,插个眼等大腿

后端做这个不是ezez吗?

同一个商品ID如果未消耗(未验证)是没法再次购买的,所以可以在发起支付时,本地或者钥匙串保存 [商品ID] =订单号,如果购买成功异常退出的话,下次登录取到苹果的购买凭证,可能有多个凭证,楼主纠结的是客户端不知道这些凭证分别对应哪个订单号。那就都发给服务器去校验啊,凭证、订单号1、订单号2…,服务器拿凭证去苹果服务器校验,拿到其对应的商品ID,再看订单号1、订单号2哪个的商品ID一样,就购买哪个订单。一个商品ID不可能有多个待支付的订单号

基本上 目前的做法和你说的差不多,
同一个商品id 只能有一个没完成的交易,这样方便 票据和订单号 匹配
就是 找不到订单号的情况下 用商品ID 匹配订单号
本地存储 订单号和相关详情

再问大家一个问题

有没有这种情况 客户端收到一个票据,但这个票据里 商品是多个,相当于
用户购买多个商品,结果苹果给合到一个票据里发给客户端了,客户端在把这个票据提交给服务器去验证,
就是一个票据里有多个商品,有没有这种情况?

是这样的,但如果有多个订单号,一个票据,那么怎么匹配呢?
现在是用商品ID来匹配,这样就只能是一个商品 再没完成交易前 不能再次购买
以免 出现一个票据 上用商品id 匹配到多个订单号

服务器验证票据 只能知道票据真伪,如何得知 谁购买的呢?又怎么下发道具呢!

苹果订单里的购买时间 是支付成功的时间,与咱们的订单生成时间有一定的延迟

只能知道 苹果订单里的购买时间 》咱们的订单生成时间

建议更改下支付逻辑,在一次支付没有结果(成功或失败)之前让玩家处在等待状态,等有了结果才能发起第二次支付,这样省去很多麻烦。。。

多个商品是因为
1.商品里面可能有类似订阅的付费项,订阅没过期的话,商品收据会在里面
2.也有可能是相邻这几次支付时间间隔太短,苹果一起发给你了(没验证)
所以说,最好让一次购买一个,让玩家多等几秒整再购买第二次也没啥影响 :rofl:。。。