In-App Purchases
A guide on how to implement IAPs in your game
As we discussed in the What is Trail? and Setting Up Your Game articles: Trail has two components; the Trail Platform, represented by the The Game Manager and the Unity SDK.
This guide assumes that you are familiar with the Game Manager and will not discuss its different components. If you'd like to learn more about its different features we suggest you check out the Setting Up Your Game and The Game Manager articles first.
Creating a product
First, let's navigate to the Game Manager. Select your project (game) and then click on In-game purchases
:


In-game purchases screen.
It looks boring and empty, so let's change that by adding a new product. For the sake of this article, we'll use Gold Coins as an example. Gold Coins is a premium virtual currency the user needs to purchase first and then, using the Gold Coins, they can purchase various in-game cosmetics.
First, let's click on the Create product
button:


The add new product popup.
The pop-up above will appear. Let's start by adding the item's name (we recommend using a descriptive name so the player doesn't feel confused when seeing the popup on Trail).
Be descriptive
It is important to be accurate and descriptive when naming your product. The name you enter will be shown to the player when buying and will appear on the receipt they receive by email.
100 Gold Coins
is a good name because it tells the player what kind of item they are buying (Gold Coins) and how many of them (100). A poor name would be something likeCoins
where it doesn't tell the player which kind of coins or how many are they buying for the purchase price.
In our case, this will simply be "100 Gold Coins" as it will provide the player with 100 Gold Coins. Next, we add an image that represents the item -- again, it is a good idea to use the same image you're using in-game. In our case, we'll use an icon to represent gold coins. Finally, choose the price tier. As mentioned in π°οΈ PaymentsKit article, Trail uses price tiers for selecting prices. For our example, we'll just pick $3.99:


The "New Product" window after adding in the information.
Editing a product
You can edit a product after creating it by simply clicking on the created product's name. You can modify the icon and name. However, you can not modify the price tier. If you want to modify a price tier, you'll need to reach out to us on Discord
You'll notice a checkbox that says "Enable Upsell Window". We'll go through what it does in a separate article, so let's ignore it for the moment. Now click on the Add Product
button:


How it looks after we added a new product.
Once a product is created, it is marked as consumable and a unique product ID is generated for it, as seen in the above screenshot (last column). The product ID is very important as you'll be using it to reference your product in code.
Displaying a product in-game
Now that we've set up a product, the next step is to show the product to the user so they can buy it. This can be done in myriads of ways and depends highly on your game. We won't get into details of how you can design or show the information to the player. Instead, we'll look at how you can obtain the information from Trail so you can use it in your design. The main piece of information you'd need from Trail is the price; the name and description of the product are most likely part of your own data already. So let's request a product price:
// Remember to initialize the SDK first.
private void RequestProductPriceFromTrail()
{
// We tell Trail to send us the product ID
SDK.PaymentsKit.GetProductPrice("ff148434-9d1c-11eb-b2d9-c7e44343d0cd", PriceRequestCallback);
}
// Callback that fires when the request is done
private void PriceRequestCallback(Result result, Price price)
{
if(result.IsOK()) {
// We then pass the price and the information to the game so it displays it for the player
DisplayItem(itemName, itemDescription, price.ToString());
}
else {
Debug.Log("Something happened when requesting price: " + result);
}
}
What is price.ToString()
What
price.ToString()
does is combine the price and currency in one string. So in our example, it would say "3.99 Currency" where "Currency" in this case is replaced with your regional currency (USD, Euro, etc...).If you want to get the price amount and the currency separately, you can then use
price.Amount
for the amount itself andprice.CurrencyISO4217
for the currency itself.
Next, the player will probably want to buy the item so we need to request a payment.
Requesting a payment
Let's go back to Unity:
// Remember to initialize the SDK first.
// Calling the method below will show the payment dialog to the user.
Trail.PaymentsKit.RequestPayment(
"ff148434-9d1c-11eb-b2d9-c7e44343d0cd",
(Result result, string orderId, string entitlementId) =>
{
// First, check that there was not unexpected error.
if (result == Result.IsOK()) {
// The function below is just a placeholder.
// You will have to replace it with whatever method you use
// to send entitlements to your backend.
MyGameBackend.ConsumeEntitlement(orderID, entitlementID);
} else {
Debug.LogError("Something went wrong. ", result);
}
// The function below is just a placeholder.
// You will have to replace it with whatever method you use
// to send entitlements to your backend.
MyGameBackend.ConsumeEntitlements(entitlements);
}
);
Let's go over the code; first, we send a RequestPayment
using the payment ID
and wait for the request to finish. Once it is done, the callback RequestPaymentCallback
will run. We check if the result is good to go. If so, we report it to our back end to start the next step (note that you receive both the orderID
and entitlementID
in the callback. If not, we print the error out so we can debug it.
Consuming the entitlement
As discussed in the π°οΈ PaymentsKit article; a consumable product produces an entitlement (basically a receipt or a contract stating the player's ownership of the items bought) so you can consume it in your backend.
Consuming a product is done through an HTTP cURL post:
POST v2/payments-kit/consume-entitlement
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <YOUR_API_TOKEN>' \
--data-raw '{
"entitlement_id": "00000000-0000-0000-0000-000000000000"
}'
Resolving unconsumed entitlements
Sometimes, an entitlement doesn't get consumed (e.g., Internet connectivity issues, a crash, or the user quits early), which is why it is important that your game always checks if there are any unconsumed entitlements on startup, and if there any proceeds to consume them using the same process as if they had just been purchased.
To check for unconsumed entitlements use the following SDK method.
// Call the following method as soon as the game has booted
// and the SDK initialized.
Trail.PaymentsKit.GetEntitlements(
(Result result, PaymentsKit.Entitlement[] entitlements) =>
{
// First, check that there was not unexpected error.
if (result == Result.IsOK()) {
// The function below is just a placeholder.
// You will have to replace it with whatever method you use
// to send entitlements to your backend.
MyGameBackend.ConsumeEntitlements(entitlements);
}
else
{
Debug.LogError("Something went wrong. ", result);
}
}
);
AuthKit and PaymentsKit
As you may have noticed, ποΈ AuthKit works very well with π°οΈ PaymentsKit. We've designed both so that you can verify and authenticate a user using ποΈ AuthKit and then process any monetization needs you may have using π°οΈ PaymentsKit.
Updated 6 months ago