鬣狗消化
This article will help you get understanding of how purchasing works with Apple/Google’s In App Purchase SDKs/APIs.
本文将帮助您了解购买如何与Apple / Google的In App Purchase SDK / API一起使用。
There are plenty of articles about technical integration with In-App-Purchasing (Apple) / In-App-Billing (Google) APIs for mobile applications, but there is a lack of explanation for why these APIs are built the way they are which is super helpful to understand when you actually perform the integration. This article will hopefully help explain the logic behind In-App-Purchasing as it is designed by major platforms and will serve as a good introduction for somebody who is just starting on the monetization journey for their mobile apps.
关于用于移动应用程序的In-App-Purchasing(Apple) / In-App-Billing(Google) API进行技术集成的文章很多,但对于这些API为何以其原本的方式构建的原因,缺乏解释有助于您真正地进行集成。 本文有望帮助解释应用内购买背后的逻辑,因为它是由主要平台设计的,并且将为刚刚开始其移动应用获利之旅的人提供良好的介绍。
采购是一个概念 (Purchasing as a concept)
When it comes to “purchasing” something, it is a good idea to think about it through the following simple and generic user journeys:
当涉及到“购买”某物时,最好通过以下简单而通用的用户旅程来思考它:
- User can browse through offers for items they can buy (“list of offers”) 用户可以浏览要约中可以购买的物品(“要约列表”)
- User can purchase such offers (“purchase item”) 用户可以购买此类优惠(“购买商品”)
- User can receive the goods they just bought (“fulfill item”) 用户可以收到他们刚刚购买的商品(“完整商品”)
- User can refund their purchase (“refund”) 用户可以退款购买(“退款”)
In our physical world the concept of “purchasing” is easier to understand mostly because after the item is purchased and delivered (fulfilled) to us — we “own” it, meaning we actually possess it (like it sits in our house somewhere for example) and there is no further need to prove to somebody that we actually own it and we are free to use it however we want (subject to warranty, etc).
在我们的物理世界中,“购买”的概念更容易理解,主要是因为在购买并交付(交付)给我们之后,我们“拥有”了它,这意味着我们实际上拥有了它(例如,它位于我们家中的某个地方) ),则无需再向某人证明我们确实拥有它,并且我们可以随意使用它(但需保修)。
In the digital world (such as mobile applications or games) however, the fact of ownership has to be recorded somewhere and this record has to be used to check if the user in fact is “entitled” to use purchased items in such an application or a game.
但是,在数字世界(例如移动应用程序或游戏)中,所有权事实必须记录在某处,并且该记录必须用于检查用户实际上是否“有权”在此类应用程序中使用购买的物品或一个游戏。
Keeping such a record client-side is not safe — the client can lose it, it can get corrupted or even forged — so in most cases entitlements should be securely stored server-side and queried by clients and other services as needed.
在客户端保存这样的记录并不安全-客户端可能会丢失它,它可能会被破坏甚至伪造-因此在大多数情况下,应将权利安全地存储在服务器端,并由客户端和其他服务根据需要查询。
So the purchasing flow in mobile applications in most cases would mean:
因此,在大多数情况下,移动应用程序中的购买流程将意味着:
![Image for post](https://miro.medium.com/max/9999/1*NhK9kgHMhH4jy7beI0LgOA.png)
- User can browse through offers for items they can buy (“list of offers”) 用户可以浏览要约中可以购买的物品(“要约列表”)
- User can purchase such offers (“purchase an item (offer)”) 用户可以购买此类优惠(“购买商品(优惠)”)
- User can receive the goods they just bought (“fulfill item”) 用户可以收到他们刚刚购买的商品(“完整商品”)
- User can use the purchased item (“entitlement”) 用户可以使用购买的物品(“权利”)
- User can refund their purchase (“refund”) 用户可以退款购买(“退款”)
The above means that the digital world is a bit more “advanced” in that it has to keep a good track of our digital purchases via “Entitlements” and use those as flags to allow the use of otherwise “locked” content or functionality.
上面的内容意味着数字世界更加“先进”,因为它必须通过“ 权利”来跟踪我们的数字购买,并将其用作标记,以允许使用其他“锁定”的内容或功能。
Now Let’s zoom into this flow through the lens of Apple/Google’s in app purchasing APIs to understand them better.
现在,让我们通过Apple / Google应用内购买API的镜头来放大此流程,以更好地理解它们。
优惠(==“应用内商品”) (Offers (== “In-App-Products”))
Just like when we walk through a grocery store and see Items on the shelves with Prices / Discounts etc information attached to them (we call them “Offers”) we have the same concept in the digital world. The seller typically wants to have tight control over the Offers (what price is set for a given item, what discount applied under which conditions, limited time availability etc) hence both Apple and Google require any developer to register their Items for sale as well as key offer metadata (such as Price) on their server-side since in this case they are the “seller” that takes real money from real users.
就像当我们走进杂货店并在货架上看到标有价格/折扣等信息(我们称为“要约”)的商品一样,我们在数字世界中也有相同的概念。 卖方通常希望对要约进行严格控制(给定商品的价格,在什么条件下应用什么折扣,有限的时间可用性等),因此Apple和Google都要求任何开发者注册其要出售的商品以及服务器上的关键商品元数据(例如Price),因为在这种情况下,他们是从真实用户那里获得真实收益的“卖家”。
Here is how developer registers their “Offers” with both platforms:
这是开发人员在两个平台上注册其“要约”的方式:
Apple’s App Store:
苹果的App Store:
- go to “My Apps” and select specific application 转到“我的应用”,然后选择特定的应用
- then to “In App Products” > Manage 然后进入“应用内商品”>“管理”
![Image for post](https://miro.medium.com/max/9999/1*qnleRU15VVOIuxx3P-_irw.png)
Google Play:
Google Play:
https://play.google.com/apps/publish (Google Play Console)
- go to your specific application 转到您的特定应用程序
- then on the left side: “Store Presence” > “In App Products” 然后在左侧:“商店状态”>“应用内商品”
Surely ability to define the Offers (~“In-App-Products”) requires you to have proper developer agreement with the platforms, the actual application that was submitted to the relevant store (all these steps are outside of the scope of this article), but the main point here is that the “In-App-Products” conceptually are just the Offers for items that your user could eventually see and purchase inside of your application.
确定要约(〜“应用内商品”)的功能肯定需要您与平台达成适当的开发人员协议,以及提交给相关商店的实际应用程序(所有这些步骤均不在本文范围内) ,但是这里的要点是,“应用内商品”从概念上讲就是用户最终可以在应用程序内部看到并购买的商品的优惠。
So why not allow developers to have their offers hosted elsewhere? The reason for that is that when it comes to Purchasing the platform (Apple or Google) wants to make 100% guarantee that what the user sees as an Offer actually is what they are going to be charged for and what they will receive. So basically both Apple and Google want to “host” Offers information on their side for consistency and to avoid issues for users paying for something different than what was shown in the Offer (“In-App-Product”).
那么,为什么不让开发人员将其报价托管在其他地方呢? 这样做的原因是, 在购买平台时(Apple或Google)希望100%保证用户实际视为要约的是他们将要支付的费用以及将要收到的价格 。 因此,基本上,Apple和Google都希望在其方面“托管”要约信息以保持一致性,并避免用户为与要约中显示的内容(“应用内商品”)不同的价格支付费用。
Its worth to mention that In-App-Products also feature differentiation based on type of a thing users will be buying:
值得一提的是,应用内商品还具有根据用户要购买的商品类型进行区分的功能:
Apple’s Offer types:
苹果的优惠类型:
Subscriptions— time based offer for access to content (can be auto renewable)
订阅 -基于时间的内容访问报价(可以自动更新)
Consumables — offer for items that need to be consumed after purchasing
消耗品 -提供购买后需要消耗的物品
Non-consumables — offer for items that are unique and can be purchased only once
非消耗品 -提供独特且只能购买一次的物品
Google’s Offer types:
Google的优惠类型:
Managed Product (Consumables and Non-Consumables)— offers for all items that are not subscription basically, one-time purchases.
被管理产品(易损件和非易损件) -基本上不是一次性订购的所有项目的报价。
Subscriptions — same as with Apple — time based access to content
订阅 -与Apple一样-基于时间的内容访问
This is done mostly to accommodate the way purchasing and validation of purchase (checking Entitlement) works for these different in nature items: subscriptions assume recurring charges for example, while consumables represent “stackable” items that a user can have a number of.
这样做主要是为了适应自然中这些不同项目的购买和购买验证(检查权利)的方式:例如,订阅承担经常性费用,而消耗品表示用户可以拥有的“可堆叠”项目。
Once developer setup all of the In-App-Products — they are advised to pull the list of registered and available Offers in their apps to display them for the user:
开发人员设置完所有应用内商品后,建议他们在其应用中提取已注册和可用商品的列表,以向用户显示:
Google: https://developers.google.com/android-publisher/api-ref/rest/v3/inappproducts/list
Google: https : //developers.google.com/android-publisher/api-ref/rest/v3/inappproducts/list
苹果: https : //developer.apple.com/documentation/storekit/in-app_purchase/fetching_product_information_from_the_app_store
Apple here is a bit different in the approach to retrieve Offers as it requires In-App-Product’s ids to query for their availability. This means the developer has either to “hard code” those IAP IDs in their application bundle (if the offers are static) or to retrieve them from developer’s service, then use those IDs requesting Apple service to confirm they are valid for purchasing.
苹果在这里检索报价的方法有些不同,因为它需要应用内商品的ID来查询其可用性。 这意味着开发人员必须“硬编码”其应用程序捆绑包中的这些IAP ID(如果要约是静态的),或者从开发人员的服务中检索它们,然后使用那些请求Apple服务的ID来确认它们对于购买有效。
采购(==付款) (Purchasing (==Paying))
Purchasing is the most sensitive and crucial part of the overall flow. This is where the Platforms (Apple/Google) provide a lot of value to developers by abstracting the necessity to deal with region specific Payment instruments, fraud checks, local tax, audit etc. To ensure proper and secure purchasing process both Platforms have the integration guidance that drills down to the following:
采购是整个流程中最敏感,最关键的部分。 在这里,平台(Apple / Google) 通过抽象处理区域特定的付款工具,欺诈支票,地方税,审计等的必要性,为开发人员提供了很多价值 。 为了确保正确和安全的购买过程,两个平台都具有集成指南,该指南可深入到以下内容:
- the application has to ensure the Offer to be purchased is valid (as long as it is retrieved from Apple/Google’s platform as valid— it can be purchased) 应用程序必须确保要购买的要约有效(只要从Apple / Google平台检索到的要约有效,就可以购买)
the application needs to call native SDK specific method such as ~purchaseProduct(ProductID) (Apple uses a PaymentQueue for example) and then start “listening” for status changes of this particular purchase while user is going through the payments flow governed by the platform
应用程序需要调用本机SDK特定的方法,例如〜purchaseProduct (ProductID)(例如Apple使用PaymentQueue ),然后在用户通过平台控制的付款流程时,开始“监听”此特定购买的状态更改
- finally when status of a purchase (payment) changes — the application should react accordingly: in case of errors or issues — warn the user, in case of successful payment — inform the user of the further processing step, which is…the fulfillment. 最后,当购买(付款)状态发生变化时,应用程序应做出相应的React:在出现错误或问题的情况下-在成功付款的情况下警告用户-通知用户进一步的处理步骤,即……完成。
实现(==解锁) (Fulfillment (==Unlocking))
“Delivering the product” might sound a bit strange for a digital environment since we do not really have a delivery truck shipping product to our user. But the process of fulfillment here is both important and nuanced.
在数字环境中,“交付产品”听起来有些奇怪,因为我们实际上并没有向用户运送产品的送货卡车。 但是,实现的过程既重要又细微。
Successful purchase (payment) by this stage only means that the user did their part of the exchange — got their money committed to buy the Offer (In-App-Product), now it is up to the developer to ensure the transaction can be completed since at this point it is only the application client-side that is aware of the successful purchase step.
在此阶段成功购买(付款)仅意味着用户完成了交易的一部分-承诺将其钱用于购买要约(应用内商品),现在由开发商决定是否可以完成交易因为在这一点上,只有应用程序客户端才知道成功的购买步骤。
This is what needs to happen next:
接下来需要进行以下操作:
Developer needs to validate that the user (client) claim that they purchased something is legit. For that both platforms implemented client side and server side approaches to “validate the receipt” (Apple, Google). So just like in a real store where items get shipped to you afterwards the delivery person wants to double check your receipt.
开发人员需要验证用户(客户)声称他们购买的东西合法。 为此,这两个平台都实现了客户端和服务器端方法来“验证收据”( Apple , Google )。 因此,就像在真正的商店中,然后将物品运到您的仓库中一样,送货员想仔细检查您的收据。
- Once such validation is completed the developer is expected to “fulfill” the purchased item. Fulfillment in case of the digital world is writing a record to some database that says “this specific user has acquired this item and hence should have access to it”. Such record becomes user’s “entitlement” to use this item going forward. 一旦完成此类验证,开发人员就有望“完成”购买的物品。 在数字世界的情况下,实现情况是将记录写到某个数据库,上面写着“该特定用户已经获得了该项目,因此应该可以访问它”。 这样的记录成为用户使用此项目的“权利”。
- Finally both platforms require the application to confirm that the transaction (including fulfillment) was completed (with a success or failure). This is an important step that concludes each specific transaction preventing situations where a user got charged but never got their item fulfilled or got charged twice. 最后,两个平台都要求应用程序确认交易(包括履行)已完成(成功或失败)。 这是重要的步骤,它结束了每个特定的交易,避免了用户被收取费用却从未满足其商品两次或两次被收取费用的情况。
It is worth noting that what Apple and Google call a “transaction” is not just the fact of user completing the payment step. The transaction is the exchange of user’s money for entitlement to use the item (product). Hence it is important to call “transaction completed” API end point only AFTER you ensured user received the entitlement record. Since writing data is an asynchronous task — this is the stage where a lot of developers get into trouble by doing:
值得注意的是, Apple和Google所谓的“交易”不只是用户完成付款步骤的事实 。 交易是用户的金钱交换使用物品(产品)的权利 。 因此,只有在确保用户收到授权记录之后,才应调用“事务完成” API端点,这一点很重要。 由于写数据是异步任务,因此许多开发人员在这样做时会遇到麻烦:
concludeTransaction() { postEntitlement(); finishTransactionWithApple();};
Instead of:
代替:
concludeTransaction() { postEntitlement().then(success => finishTransactionWithApple())};
权益 (Entitlements)
So how does entitlement really work to control whether we have access to an item (or a thing) inside an app or a game?
那么,权利实际上如何控制我们是否可以访问应用程序或游戏中的项目(或事物)?
![Image for post](https://miro.medium.com/max/9999/1*ERPIGqfnMZPtwDrI4c81Uw.png)
Typically developers implement business logic in their apps and services to “consult” the entitlements service (~call GET /api/v1/entitlements) every time a game or application needs to make a decision that involves the use of locked content. Whether client application goes directly to such a service or indirectly via App Services backend is subject to design decisions of a particular application. But in all cases the above means that Entitlements service has to be highly reliable and available service (API) that clients and backend services can talk to optimized for dominant amount of “reads” (95%+) and some “writes” (< 5%).
通常,每次游戏或应用程序需要做出涉及使用锁定内容的决策时,开发人员都会在其应用程序和服务中实施业务逻辑,以“咨询”权利服务(〜称为GET / api / v1 / entitlements)。 客户端应用程序是直接转到此类服务还是通过App Services后端间接访问,取决于特定应用程序的设计决策。 但是在所有情况下,以上情况都意味着授权服务必须是高度可靠且可用的服务(API),客户端和后端服务可以与这些服务进行对话,以针对占主导地位的“读取”(95%+)和某些“写入”(<5 %)。
Important thing is that entitlements are not just about access control, they typically feature additional details around the context of the purchase made. Such information is vital when it comes to marketing, customer support, and financial audit as it describes the context of why the user has access to a certain digital item (which is also crucial for things like “refunds”).
重要的是, 权利不仅与访问控制有关 ,而且通常会围绕所购买的内容提供其他详细信息。 当涉及市场营销,客户支持和财务审计时,此类信息至关重要,因为它描述了用户访问特定数字商品的原因(这对于“退款”也很重要)。
You can think of entitlements as of purchase receipts that are attached to your user account and can be queried programmatically at any time. In fact, both Apple’s In-App-Purchasing and Google’s In-App-Billing solutions feature a “recover purchases” functionality for those developers that lack their own backend that tracks entitlements thus such purchase history end-points could be used to recover entitlements status for a given user.
您可以将权利视为附带在用户帐户中的购买收据,可以随时以编程方式对其进行查询 。 实际上, 苹果的应用内购买解决方案和谷歌的应用内结算解决方案都为那些缺少自己的后端来跟踪权利的开发人员提供了“恢复购买”功能,因此此类购买历史端点可用于恢复权利状态给定用户。
退款 (Refunds)
Finally if a user was not happy with their purchase and wants to get their refund the digital world starts to adapt the legal rules that exist to protect consumers. Unfortunately this is not yet well defined for In-App-Purchases where the refunds are subject to particular platform rules (Google).
最后,如果用户对他们的购买不满意并且想获得退款,那么数字世界将开始采用现有的法律规则来保护消费者。 遗憾的是,对于应用内购买(退款)受特定平台规则( Google )约束的定义尚不明确。
For general understanding the Refund is just a reverse of transaction that happened in the past. This underlines why it is super important to keep precise information about context of the purchased offer somewhere safe on the developer’s side.
对于一般理解,退款只是过去发生的交易的逆转。 这强调了为什么将有关购买报价的上下文的准确信息保持在开发者一方安全的位置非常重要。
总结一下 (Summing it all up)
So conceptually the Apple/Google’s In-App-Purchase APIs do the following:
因此,从概念上讲,Apple / Google的应用内购买API会执行以下操作:
- They host and allow configuration of Offers (In-App-Products) 他们托管并允许配置优惠(应用内商品)
- They take care of Payment acquisition for a specific Offer 他们负责特定报价的付款获取
- They require developer to perform Receipt Validation and Fulfillment of purchased Entitlement, followed by the conclusion of the Transaction 他们要求开发人员执行收据验证和购买的权利的履行,然后完成交易
- They allow developers to restore context of Purchases made in case something went wrong 它们允许开发人员恢复购买时的情况,以防出现问题
While mobile app developers are advised to invest time and effort creating robust and highly available Entitlement services that would keep user’s entitlements records in good standing— as in a way the entitlements are all what those users are getting in exchange for their real money and they expect it to be kept safe.
建议移动应用程序开发人员投入时间和精力来创建强大且高度可用的授权服务,以使用户的授权记录保持良好的信誉-从某种意义上说,授权就是这些用户获得的全部钱,以换取他们的真实金钱,并且他们期望为了安全起见。
Here is how the overall flow looks like:
总体流程如下所示:
![Image for post](https://miro.medium.com/max/9999/1*w_E66yD7vFGVhjXZEWvAfQ.png)
Thank you for reading!
感谢您的阅读!
翻译自: https://medium.com/swlh/digesting-in-app-purchasing-apis-faa6d73ce9d7
鬣狗消化