技术

BillingMeld:为什么购买应该由服务器验证而不是应用程序

BillingMeld成为关于购买和订阅的核心信息源。它通过App Store和Google Play验证交易状态的变化,连接的服务仅依赖已验证的BillingMeld状态。

在移动应用中的购买对用户来说通常看起来非常简单。他点击按钮,确认付款,获得功能或订阅的访问权限——并等待一切自动正常工作。

对开发者而言,按钮背后其实启动了一个更为复杂的流程。需要确认购买本身,考虑续订、订阅到期、退货、操作记录、更换设备以及苹果和谷歌商店之间的差异。

当服务器开始将客户端应用视为真相源时,主要问题就出现了。

如果应用声明:“购买已完成”,服务器会开启访问权限,并继续依据已获得的状态作出判断。但购买的生命周期远未结束。

订阅可以续费,自动续订可能被关闭,支付可能被退回,操作也可能被商店撤销。

因此,BillingMeld确认购买的责任不在应用,而由服务器承担。

客户端报告,但不决定

在BillingMeld架构中,移动应用不是购买信息的主要来源。

客户端可以传递完成操作的数据,但这只是验证的依据。最终决策由BillingMeld的后端部分做出,它通过苹果或谷歌的基础设施验证信息。

这是一项根本性的区别。

手机上的应用可能会基于旧状态工作,未能及时获取下一次的变更,或者传递已经不符合当前购买状态的数据。

此外,客户端不应有自行决定用户是否拥有付费权限的权力。

BillingMeld会验证,例如:

  • 购买是否真实存在;

  • 是否对应正确的应用和产品;

  • 已付费期限是否在有效期内;

  • 是否进行了续订;

  • 是否关闭自动续订;

  • 是否进行了退货;

  • 操作是否被撤销;

  • 已付费期限是否已到期。

因此,客户端的消息已不再是购买的证明,而是检查其实际状态的依据。

统一的真相源头

连接的服务无需同时实现苹果和谷歌完整的集成。

它们只需调用BillingMeld,即可获得经过标准化的购买状态。

比如:访问权限是否开启、已付费期限是否已结束、续订是否确认、自动续订是否关闭或购买是否已被撤销。

这明显划分了责任界限。

苹果和谷歌提供的是商店操作的状态信息。BillingMeld验证这些数据,将其归一化为统一模型,并保存最新状态。而最终权限的决策则基于BillingMeld的状态。

对产品的服务器来说,这意味着用一个统一的契约替换多重独立接口。

无需在每个服务中单独实现App Store和Google Play的规则,也不用试图将不同的格式、事件和状态统一到一道逻辑中。

为何不能完全信任客户端

客户端应用运行在用户设备上。

它可以被关闭、重启、从备份恢复、稍后更新或在不同设备上运行。它可能会暂时使用旧状态,或者甚至未能接收到之后发生的事件。

即使没有用户干预,客户端也不是最终的订阅状态的可靠来源。

举例而言,用户订阅后获得访问权限,之后可能因退货或商店撤销操作而状态发生变化。

如果服务器只知道最初客户端传递的状态,则仍会认为购买有效。

在另一种场景中,用户可能关闭自动续订,但已付费的周期仍应持续到结束日期。

如果系统只依据简单的“有订阅/无订阅”状态,会容易提前关闭访问权限或在权益结束后还继续允许使用。

BillingMeld的核心逻辑是:客户端不确认自己的权限,而是提供事件,服务器判定实际的购买状态。

购买不是单一事件

在支付架构中的主要错误之一是将购买视为单一事件。

实际上,购买拥有自己的生命周期:

首先有操作出现,然后由商店确认。订阅开始付费期,之后可能会续订。

用户可以关闭自动续订,但仍能在已付费的时间内使用订阅。

下一次续订可能未成功,退货也可能发生,操作也可能被撤销。

因此,只知道“这笔购买曾经存在”是不够的,必须知道它现在的状态。

退货不会被忽略

尤其在退货和操作撤销方面,服务器架构的必要性更明显。

最初的购买也许是有效的,用户确实支付并获得权限,但此后状态发生变化。

如果BillingMeld收到状态变化的信息,会更新自己的购买状态,同时根据需要再次验证商店的数据。

这样,连接的服务就能以新的状态进行操作。

应用程序不再永远依赖几周、几个月前自己报告的购买成功事实,每次状态变化都能得到实时反映。

如果商店不再认可相应的权限,BillingMeld会反映这一点。

取消订阅和权限终止并非相同

这里有一个重要区别。

如果用户关闭自动续订,通常并不意味着访问权限要立即关闭。

已付费的当前周期仍然有效至结束日期。

在这种情况下,BillingMeld应保存自动续订关闭的标记,同时记录已付费周期的结束时间。

只有在周期结束后,未发生新的确认续订,权限才被视为已终止。如果仅用一个布尔值subscription = true,不足以描述完整状态。

订阅状态总是和时间、事件、生命周期相关联的。

续订也是独立验证的一环

订阅并非在首次付费后终结。

服务器必须判断是否真的发生续订,且是否经过商店确认了未来的付费周期。

BillingMeld会追踪这些变更,更新订阅状态。

若续订确认为有效,权限继续存在。

如未发生续费或商店不再确认下一个周期,系统不能仅依赖假设继续提供权限。

对用户来说,这符合预期:只要付费的订阅还在有效期内,权限就应持续。

对开发者而言,这意味着不用在每个应用内重复实现续订逻辑。

典型流程示意

用户在移动端应用中订阅。

客户端获悉购买信息,传递给BillingMeld,但这还不足以确认购买已完成。

BillingMeld通过对应的商店验证操作。

如果App Store或Google Play确认购买且符合产品规则,BillingMeld会记录有效权益。

连接的服务随后提供已付费的功能。

之后状态会基于验证结果自动更新,不依赖最初客户端的报告。

如果订阅续订,BillingMeld会更新已付费周期;

如果用户关闭自动续订,当前周期会一如既往地持续到结束;

如果发生退货或操作撤销,状态也会随之改变。

在这个流程中,应用程序没有独立存储所谓“真相”状态,而是以BillingMeld确认、存储的状态为依据。

设备切换时会发生什么

这种服务器模型当用户更换手机或重新安装应用时尤为有用。

权限不应仅因应用曾经成功交易而存在。

反之,重新安装应用也不应抹除已验证的权限。

如果购买状态存储在服务器端并与确认的商店操作相关联,新的设备可以从服务器获得最新状态。

这是为什么不应该完全在移动端存储权限逻辑的另一个原因。

对开发者的益处

对于发布多个移动应用或同时支持iOS和Android的团队,支付逻辑很快演变为一项基础设施任务。

需要考虑:

  • 苹果与谷歌格式差异;

  • 验证首次购买;

  • 续订过程;

  • 支付周期结束;

  • 自动续订关闭;

  • 退货;

  • 操作撤销;

  • 应用重装;

  • 设备切换;

  • 购买恢复;

  • 非用户参与的状态变化。

BillingMeld将这些逻辑抽象出来,作为单一的专用层。

各产品的服务器通过统一契约与之交互,不必自己实现每个商店的全部细节。

这样可以减少重复代码,更重要的是降低同一公司的不同应用对同一支付场景理解不一致的风险。

验证的焦点从“票据”转向“权限”

在这个架构中,我特别关注的一点,是从验证单个购买转向控制实际状态的转变。

支付的历史本身不能回答产品的核心问题:

用户现在是否有权限使用付费功能?

操作可能有成功的初始购买,但付费期已结束;

订阅可能关闭自动续订,但允许已付费的周期继续;

可以存在确认的续订;

退货可能已完成;

商店可能撤销操作;

因此,最重要的对象不再是“票据”或客户端的首个响应,而是以确认状态为依据计算出的当前用户权限状态。

这个状态正是BillingMeld传递给其他服务的内容。

BillingMeld:商店与产品之间的桥梁

最终出现了明确的架构边界:

一边是拥有自己格式、事件、规则和生命周期的App Store与Google Play;

另一边是应用程序和内部服务,它们更需要的是一个简单的答案——用户当前拥有哪些权限。

中间则是BillingMeld。

它接受商店数据,验证后转换为自有模型,并向基础架构提供标准化结果。

这样,产品团队无需深入了解每个支付平台的全部细节。

这对用户意味着什么

对于用户而言,理想的支付架构应尽可能无感知。

如果购买已确认,且付费周期在有效期内,权限应正常工作。

如果用户关闭了自动续订,已付费的时间不应提前消失;

如果续订成功,权限应持续;

如果商店确认退货或撤销,系统应正确反映权限变更;

在换机或重装应用时,用户无须每次都向所有环节证明购买的存在性。

最终,规则变得很简单:用户报告购买,商店是状态的外部源,BillingMeld验证并标准化状态,其余服务在此基础上决定权限。这也是为什么BillingMeld不仅仅是一个支付模块,而是苹果、谷歌商店与产品之间关于用户付费权益的可信服务器层。更多信息请访问:billingmeld.de