Managing consumable products from your service
If your title uses a consumable-based ecosystem, it is a best practice to develop a back-end service to validate and manage the consumable transactions within your title. This allows secured communication and management of the consumable products between your trusted service and the Xbox Store Service APIs directly. Relying on the client to manage these transactions poses a risk as an attack vector to cheat your ecosystem. For example, the user could manipulate the traffic or drop packets on the client to cause issues with your consume calls. In prior cases this has caused theft or manipulation of consumable products not directly managed and controlled from a game service.
This article will outline how to build a robust and secure service to manage your consumable ecosystem. Additionally, this article outlines how to detect and manage user refunds of consumable products to prevent consumable fraud and theft.
To manage consumable products and handle refunds you will be calling the following Microsoft Store APIs from your service. See the documentation pages for specifics on calling and parsing the results.
Microsoft Store API | Function |
---|---|
collections.mp.microsoft.com/v8.0/collections/consume | Consume or fulfill a consumable product the user owns. |
purchase.mp.microsoft.com/v8.0/b2b/orders/query | Purchase Orders - Reports consumable purchases made by the user over the last 90 days. |
purchase.mp.microsoft.com/v8.0/b2b/clawback/sastoken | Provides an SAS token used to query the Clawback event service message queue for refund events related to your products. |
Utilizing the Microsoft.StoreServices .NET library and sample
To help demonstrate the principles and flows outlined in this article review the Microsoft.StoreServices Sample which provides the following:
Use of the Microsoft.StoreServices library to manage authentication and make the calls to the Microsoft Store Services.
Example logic for managing consumable products, tracking pending consume requests, reconciling refunded purchases, renew expired User Store Ids, and more.
A configuration guide that includes the steps in this article on how to configure and setup your Microsoft Entra ID for this authentication method.
Managing Consumables
Recommended outline of a consumable management service
A robust consumable management system will consist of the following functionality:
- Receive requests from the client to use or purchase in-game items with consumable currency
- Authenticate with the Microsoft Store Service APIs
- Validate the user's balance of a product in the Microsoft Store
- Validate if the user has sufficient consumable currency for the transaction (server managed or store managed)
- Consume or fulfill a portion of the user's balance
- Track and retry consume requests if needed to validate fulfillment
- Complete the client's transaction request
- Report back to the game client the results or items gained from the transaction
- Reconcile refunded consumable transactions
Managing the user balance on your service vs. the Microsoft Store
Store-managed consumable products can be fully managed on your game service by consuming any non-zero balance from the Microsoft Store. Alternatively, the user's consumable balance can be managed on the Microsoft Store by only consuming the qty needed at the time the user purchases something within your in-game economy. Developer-managed consumable products however, must be managed by your game service. See Choosing the Right Product Type for more info on developer-managed vs Microsoft store-managed consumables.
The recommended and most commonly used method is to track and manage the user's available balance within the game's service. This entails querying the Microsoft Store to see if the user has any non-zero balance of a game's consumable products, then consuming those quantities down to zero and adding the equivalent in-game currency to the user's balance that is tracked on the game service. This allows partners to know the user's current balance and manage it without further calls to the Microsoft Store APIs once fulfilled. In cross-platform scenarios this also is the best method so that consumables purchased on multiple store fronts can be combined together and used across the different platforms if allowed. Another benefit is that if the user has issues or needs to contact your Customer Service, your services can add quantity directly to the user's balance on your server as needed rather than having to manage or grant codes to products in the Microsoft Store. With this method the Store Managed consumable products are generally configured to grant a quantity of 1 per user purchase. That quantity is then translated to how many in-game currency units that product relates to. Example: When the user purchases a '500 coin' consumable product, the user's quantity of that product in the Microsoft Store API will increase by 1. When consumed from the service, the quantity will go down to 0 and the user's account balance on your service would be credited with 500 in-game coins.
Store Managed consumables can also be configured to grant any specified value to the user's quantity on purchase. For example, you could set the '500 coin' option mentioned above to increase the user's quantity in the Microsoft Store APIs by 500 on each purchase. This way, the store is managing the user's balance as they buy more consumable currency and your service would deduct quantity from their balance when the user purchases an in-game item from your consumable ecosystem.
Using TrackingIds as a redundant system for consume validation
When fulfilling or consuming a product from your service you include a TrackingId in the consume request. This TrackingId can be used as a redundant fall back to verify that a transaction request successfully completed and was honored on the Microsoft Store Services. For example, if your service sends a consume request, but does not get a response there is no way of knowing if the user's balance was changed from the request or not. In this scenario your service would not know if it should grant the user the consumable items or not. You can re-issue the request against the same user account with the same TrackingId, quantity to be removed, and productId to have the Microsoft Store Service respond on the result of that consume transaction. A recommended example flow of fulfilling a consumable from your service is provided below. This flow utilizes the TrackingId and keeps a list of pending consume transactions to be able to verify the result of a request if needed.
Product 1 (500 in-game coins) is a consumable configured to grant a quantity of 1 with each purchase that will then be translated to 500 coins within our service.
- The user purchases Product 1 and now has a quantity of 1 for the product when calling the query service
- The game's service query's the user's consumable balance within the Microsoft Store query API and sees the user's balance is '1'
- Game service generates a TrackingID, creates a consume request to consume 1 product quantity, and adds the request information to a pending transaction list.
- Game Service sends the request to the Microsoft Store consume API
- Something happens and the Game Service never gets a response from the consume API. This could be network packet loss, service outage, power loss, etc.
At this point, the game service has no idea if the quantity was actually consumed or not on Microsoft's side. If they query the inventory again, the quantity could still say 1, but that doesn't mean the transaction didn't go through. The consume may have succeeded resulting in quantity of 0, but the user may have purchased the consumable again during the outage raising their quantity back to 1. To verify if the transaction did go through, we will need to use the pending transaction list we added the request to above.
- Game service determines when it should retry the consume request
- Game service re-creates the consume request using the same user, ProductId, TrackingId, and quantity
- Game service sends the request to the Microsoft Store consume API
- Game service receives a response that the consume was successful and the new user's balance is '0'
- Game service adds 500 coins to the user's currency balance tracked on the server
- Game service removes the consume request from the pending transaction list as the item has now been consumed, verified, and user granted the correct in-game currency on the service
Behavior of the Microsoft Store Consume API when verifying previous transaction requests
If the consume API has not seen the incoming request before (TrackingID, User, Quantity, and ProductID) it will treat this as a new incoming request and complete it appropriately based on the user's current consumable balance in the system.
If the consume API sees that this is a retry of a previously consumed transaction (Same TrackingId, User, Quantity, and ProductId) it will not consume the item a 2nd time from the user's balance. But the service will respond back in the format that indicates the requested consume was completed and the user's current remaining balance. Therefore it is always safe to retry or replay the consume requests to validate they went through if a response was not received. You must however ensure that the User, TrackingId, Quantity, and Product are the exact same to the previous call. If using X-Token authentication to the consume API, you can update and get a new X-Token as long as the new X-Token is for the same Xbox user as the previous request. This may be needed as X-Token are only valid for 4 hours before having to obtain a new one.
Mitigating consumable return and refund fraud with the Clawback event service
To help prevent abuse and fraudulent returns / refunds of consumable products it is also recommended that your service integrate with the Clawback event service. This will allow your service to receive events when a consumable product purchased by a user has been returned or refunded and your service should remove the added value of the consumable from your service side.
In order to take action on Clawback events, you need to make sure that you use the "includeOrderIds": TRUE option in your consume request to collections.mp.microsoft.com/v8.0/collections/consume. Your consumable management service then needs to keep a record of the transaction including the user's information in your system, OrderID, LineItemOrderId, ProductID, and any other other useful information. The OrderID and LineItemOrderID pair of a clawback event can then be used to search your completed transactions for matches.
For more information see Managing refunds and chargebacks from your service
See also
Managing refunds and chargebacks from your service