热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOS内购服务端票据验证及漏单引发的思考.

因业务需要实现了APP内购处理,但在过程中出现了部分不可控的因素,导致部分用户反映有充值不成并漏单的情况。仔细考虑了几个付费安全上的问题,凡是涉及到付费的问题都很敏感,任何一方出现损失都是不能接受的,

因业务需要实现了APP内购处理,但在过程中出现了部分不可控的因素,导致部分用户反映有充值不成并漏单的情况。

仔细考虑了几个付费安全上的问题,凡是涉及到付费的问题都很敏感,任何一方出现损失都是不能接受的,所以在这里整理一些支付安全的要点分享一下。

支付方式

IAP是指In-App Purchase, 是一种付费方式,而并不是苹果专有的付费方式,在其它平台上也会有不同的实现,这里针对Apple IAP。

说到IAP安全问题,在苹果的IAP流程中有一个比较明显的逻辑漏洞,这个逻辑漏洞是建立在我们处理不当的情况下发生的,会导致己方提供的服务和用户之间出现问题。先看看IAP支付时序图:

支付流程

1.客户端向Appstore请求购买产品(假设产品信息已经取得),Appstore验证产品成功后,从用户的Apple账户余额中扣费。

2.Appstore向客户端返回一段receipt-data,里面记录了本次交易的证书和签名信息。

3.客户端向我们可以信任的服务器提供receipt-data

4.服务器对receipt-data进行一次base64编码

5.把编码后的receipt-data发往itunes.appstore进行验证

6.itunes.appstore返回验证结果给服务器

7.服务器对商品购买状态以及商品类型,向客户端发放相应的道具与推送数据更新通知

这七个步骤实际上是一个很安全的流程了。那问题出在哪里呢?我们谈谈两种苹果IAP的验证模型。

验证方式

1.IAP built-in Model,本地验证

有些APP甚至是网游,都直接跳过了3~7步骤,在第2步拿到receipt-data之后,直接由客户端向itunes.appstore发送验证请求,并且拿到结果,根据结果修改数据。

我们在设计APP的时候都遵循一个真理,“凡是在客户端的数据都是不安全的”,深以为然。如果没有独立服务器辅助验证,这样也就避免不了数据被修改的事实了,是的,你会少赚钱。

不过如果APP也不通过独立服务器验证,而是在客户端验证之后再告知服务器状态让其发放游戏道具,那就太可怕了点。这是IAP built-in Model

那是不是就完全不能让这个过程变得安全了呢?也不是,但这个安全保障只是让修改变得困难而已。苹果官方提供了 Validating Receipts Locally 在客户端对receipt-data进行安全验证,主要是对证书以及签名的合法性验证。如果不想自己写代码验证,也可以借助第三方机构提供的receipt-data验证API,比较著名的有  urbanairship和  beeblex 。

但如果能伪造一个完全合法的receipt-data,是不是一样可以达到欺骗目的。是的,为了绕过Validating Locally,于是黑客开始用自己伪造的receipt-data进行移花接木,所以出现了可以伪造”合法订单”的 in-appstore 。因此这种本地加强验证的方法也不能完全避免IAP攻击。

2.IAP Server Model,服务器验证

而如果我们把验证逻辑移到服务器上,这个过程就变得容易多了。因为不再需要担心receipt-data被伪造的问题。不过就算把步骤4~7在服务器上做了,同样也会产生一些幼稚的逻辑漏洞:

 对验证receipt-data的reponse content不进行验证和记录,只根据Product直接发放商品。这样只要客户端不断提交receipt-data,按照正常逻辑你就需要不断验证并且重复发放商品。较为安全的做法是:

在每一次收到receipt-data之后,都把提交的用户账号以及receipt-data中的单号建立映射并记录下来,在每次验证receipt-data时,先判断其是否已经存在。

只要做了这样的验证,整个支付流程都变得明朗起来。

确保receipt-data的成功提交与异常处理

建立在IAP Server Model的基础上,并且我们知道手机网络是不稳定的,在付款成功后不能确保把receipt-data一定提交到服务器。如果出现了这样的情况,那就意味着用户被appstore扣费了,却没收到服务器发放的道具。(这样就引发了漏单)

解决这个问题的方法是在客户端提交receipt-data给我们的服务器,让我们的服务器向苹果服务器发送验证请求,验证这个receipt-data账单的有效性. 在没有收到回复之前,客户端必须要把receipt-data保存好,并且定期或在合理的UI界面触发向服务端发起请求,直至收到服务端的回复后删除客户端的receipt账单记录。

如果是客户端没成功提交receipt-data,那怎么办?就是用户被扣费了,也收到appstore的消费收据了,却依然没收到道具,于是投诉到客服处。

这种情况在以往的经验中也会出现,常见的用户和运营商发生的纠纷。客服向用户索要账号和appstore的收据单号,通过查询itunes-connect看是否确有这笔订单。

如果订单存在,则要联系研发方去查询服务器,看订单号与用户名是否对应,并且是否已经被使用了,做这一点检查的目的是 为了防止恶意用户利用已经使用过了的订单号进行欺骗(已验证的账单是可以再次请求验证的,曾经为了测试,将账单手动发给服务器处理并成功),谎称自己没收到商品。

当然了,如果查不到这个订单号,就意味着这个订单确实还没使用过,手动给用户补发商品即可。

有朋友问怎么通过itunes-connect查看具体订单,itunes-connect中无法直接看到订单信息,可以用以下方法来查询

1.可以通过账单向苹果发送账单验证,有效可以手动补发

2.用自己的服务器的记录账单列表对比 

3.利用第三方的TalkingData等交易函数,会自动记录账单数据

建议

为保证审核的通过,需要在客户端或server进行双重验证,即,先以线上交易验证地址进行验证,如果苹果正式验证服务器的返回验证码code为21007,则再一次连接沙盒测试服务器进行验证即可。

在应用提审时,苹果IAP提审验证时是在沙盒环境的进行的,即:苹果在审核App时,只会在sandbox环境购买,其产生的购买凭证,也只能连接苹果的测试验证服务器,如果没有做双验证,需要特别注意此问题,否则会被拒。

其他

在sandbox中验证receipt:https://sandbox.itunes.apple.com/verifyReceipt

在生产环境中验证receipt:https://buy.itunes.apple.com/verifyReceipt

那么如何自动的识别收据是否是sandbox receipt呢?
识别沙盒环境下收据的方法有两种:

  1. 根据收据字段 envirOnment= sandbox。
  2. 根据收据验证接口返回的状态码。
    如果status=21007,则表示当前的收据为沙盒环境下收据, 进行验证。

苹果反馈的状态码

  • 21000 App Store无法读取你提供的JSON数据
  • 21002 收据数据不符合格式
  • 21003 收据无法被验证
  • 21004 你提供的共享密钥和账户的共享密钥不一致
  • 21005 收据服务器当前不可用
  • 21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
  • 21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证
  • 21008 收据信息是产品环境中使用,但却被发送到测试环境中验证

 

By Hgq


推荐阅读
  • 阿里云ecs怎么配置php环境,阿里云ecs配置选择 ... [详细]
  • 丽江客栈选择问题
    本文介绍了一道经典的算法题,题目涉及在丽江河边的n家特色客栈中选择住宿方案。两位游客希望住在色调相同的两家客栈,并在晚上选择一家最低消费不超过p元的咖啡店小聚。我们将详细探讨如何计算满足条件的住宿方案总数。 ... [详细]
  • 本文详细介绍如何使用CSS自定义HTML5视频播放器的样式,涵盖常见属性及跨浏览器兼容性问题。发布时间:2020-09-14 14:46:29;来源:亿速云;阅读量:58;作者:小新。 ... [详细]
  • 本文介绍了如何使用JavaScript的Fetch API与Express服务器进行交互,涵盖了GET、POST、PUT和DELETE请求的实现,并展示了如何处理JSON响应。 ... [详细]
  • 本文总结了优化代码可读性的核心原则与技巧,通过合理的变量命名、函数和对象的结构化组织,以及遵循一致性等方法,帮助开发者编写更易读、维护性更高的代码。 ... [详细]
  • 云函数与数据库API实现增删查改的对比
    本文将深入探讨使用云函数和数据库API实现数据操作(增删查改)的不同方法,通过详细的代码示例帮助读者更好地理解和掌握这些技术。文章不仅提供代码实现,还解释了每种方法的特点和适用场景。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • yikesnews第11期:微软Office两个0day和一个提权0day
    点击阅读原文可点击链接根据法国大选被黑客干扰,发送了带漏洞的文档Trumps_Attack_on_Syria_English.docx而此漏洞与ESET&FireEy ... [详细]
  • 百度安全应急响应中心(BSRC)与补天漏洞响应平台共同举办2021年暑期挑战赛,提供丰厚奖励、联名证书及更多惊喜。活动时间从7月12日至7月31日。 ... [详细]
  • 本文详细介绍了如何解决 Microsoft SQL Server 中用户 'sa' 登录失败的问题。错误代码为 18470,提示该帐户已被禁用。我们将通过 Windows 身份验证方式登录,并启用 'sa' 帐户以恢复其访问权限。 ... [详细]
  • WinSCP: 跨Windows与Linux系统的高效文件传输解决方案
    本文详细介绍了一款名为WinSCP的开源图形化SFTP客户端,该工具支持SSH协议,适用于Windows操作系统,能够实现与Linux系统之间的文件传输。对于从事嵌入式开发的技术人员来说,掌握WinSCP的使用方法将极大提高工作效率。 ... [详细]
  • 本文详细探讨了HTML表单中GET和POST请求的区别,包括它们的工作原理、数据传输方式、安全性及适用场景。同时,通过实例展示了如何在Servlet中处理这两种请求。 ... [详细]
  • 配置多VLAN环境下的透明SQUID代理
    本文介绍如何在包含多个VLAN的网络环境中配置SQUID作为透明网关。网络拓扑包括Cisco 3750交换机、PANABIT防火墙和SQUID服务器,所有设备均部署在ESXi虚拟化平台上。 ... [详细]
  • 本文详细介绍了在 Windows 7 系统中配置 Nginx 1.10.3 和 PHP 7.1.1 NTS 的步骤,包括修改 PHP 配置文件、处理依赖项以及创建批处理脚本启动和停止服务。重点解释了如何解决常见的运行时错误。 ... [详细]
  • 本文介绍 Java 中如何使用 Year 类的 atMonth 方法将年份和月份组合成 YearMonth 对象,并提供代码示例。 ... [详细]
author-avatar
男孩形式恋人
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有