Implementing Payments

A guide on how to implement IAPs in your game

In this article, you'll learn how to implement payments using PaymentsKit. In no time players in your game will easily be able to make purchases of items, cosmetics, currencies, or anything else you want to offer them.

Read more about payments and purchases on Pley.
Looking to test payments on Pley? Read the payment test documentation how-to here!

How-to Implement Pley Payments

1) Create a product in the Pley Game Manager.
2) Display the product in your game by fetching the price & currency.
3) Trigger the purchase in the game code.
4) Consume entitlements in your backend.
5) Grant the item to the player.

πŸ“˜

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 Game To Web sections first.

Creating a product

First, let's navigate to the Game Manager. Select your project (game) and then click on In-game purchases:

1) Click on the Create product button.

2) Add your IAP information: Name, Icon, and Price Tier (Price Tiers?).

πŸ“˜

Price Tiers

As mentioned in πŸ’° Monetization article, Pley uses tiers for pricing. This removes the burden of caring about currencies, taxes, and localization; your IAP price will always look good for the user in any currency without any work from you.

πŸ“˜

Manage Products

  • You can use the "Import from Google Play Console" feature to automatically edit or import your products.
  • You can edit name, price, and image for products.
  • To change the product ID of a product, simply duplicate and re-create the product.

Once a product is created, it is marked as consumable and its unique product ID is generated. The product ID is vital as you'll be using it to reference your product in code when calling for either pricing information or initializing a purchase.

Displaying a product in-game

πŸ“˜

API References

You can find the methods for PaymentsKit in the references for the Unity SDK and for the C SDK.

Now that we've set up a product, the next step is to show the product to the user so they can buy it. Here, we'll look at how you can obtain the information from Pley so you can use it in your game UI.

The main piece of information you'd need from Pley is the price, so let's request a product price:

// Remember to initialize the SDK first.
// using Pley;
private string[] productIds = []
{
	"ff148434-9d1c-11eb-b2d9-c7e44343d0cd",
};
private async void RequestProductPriceFromPley()
{
	// We tell Pley to send us the product ID
  var (result, data) = await Pley.PaymentsKit.GetProductsAsync(productIds);

	if(result.IsOk())
  {
    // We then pass the price data and the information to the game so it displays it for the player
    DisplayItem(itemName, itemDescription, data[0].ToString());
  }
  else
  {
    Debug.Log($"Error occured when fetching price information: {result}");
  }
}

Here is a coding recipe that walks you through the process of implementing price fetching using Pley!

πŸ“˜

What is price.ToString()

price.ToString() combines the price and currency into 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 and price.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 return to Unity and request payment when your players click the purchase button.

// Remember to initialize the SDK first.
// using Pley;

string productId = "ff148434-9d1c-11eb-b2d9-c7e44343d0cd";
// Calling the method below will show the payment dialog to the user.
var (result, data) = await Pley.PaymentsKit.RequestPaymentAsync(productId);

// First, check that there was not unexpected error.
if (result.IsOk())
{
  // The function below is just a placeholder.
  // You will have to replace it with the method you use
  // to send entitlements to your backend.
  MyGameBackend.ConsumeEntitlement(data.entitlementId);
} 
else 
{
  Debug.LogError($"Payment Error: {result}");
}

We send a RequestPayment using the payment ID . Once it is done, the callback RequestPaymentCallback will run. W If RequestPayment returns an 'Ok', we report it to our back end. Finally, you receive both the orderID and entitlementID in the callback. If not, we print the error out for debug purposes.

Purchase Modal on Pley

Pley Payments Modal for logged-in users with a saved payment method.

Consuming the Entitlement

As discussed in the πŸ’° Monetization article; a consumable product produces an entitlement (a receipt stating the player's ownership of the items bought) so you can consume it in your backend when the item is granted to the player.

Consuming a product is done through an HTTP cURL post:

curl \
-X POST \
--location 'https://api.pley.com/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, 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.
// using Pley;

var (result, entitlements) = await Pley.PaymentsKit.GetEntitlementsAsync();
// First, check that there was not unexpected error.
if (result.IsOk())
{
  // The function below is just a placeholder.
  // You will have to replace it with the  method you use
  // to send entitlements to your backend.
  MyGameBackend.ConsumeEntitlements(entitlements);
}
else
{
  Debug.LogError($"Something went wrong: {result}");
}

What’s Next