Discord offers a Monetization API that allows developers to earn revenue through their applications. In this guide, we will be learning how to implement this in your Phaser game. You can find the full code for this guide here.

To utilize this API effectively, you need to understand three key concepts:

  • SKU (stock-keeping unit): These represent specific items or subscription options your app offers. Each SKU is a unique offering. At the time of writing this tutorial, you can have up to 50 SKUs.
  • Entitlements: These indicate whether a user has access to a specific premium offering or SKU.
  • Subscriptions: As the name implies, these represent an ongoing agreement where a user commits to paying for an entitlement on a recurring basis until canceled.

You can get more information about Monetization in the Discord Developer Docs.

Set Up Your Activity & Development Environment

If you're unfamiliar with Discord Activities or need guidance on creating one, refer to this comprehensive guide on building Discord Activities with Phaser.

Requirements

  • 1) Your app needs to be verified and payout information should be set. Discord uses Stripe for the payments, which only works in certain countries. Check this list to learn which countries they currently support.

image

How to Create a SKU Item

Go to Monetization -> Manage SKUS in the Discord dashboard. Here, you can create Durable or Consumable SKUs representing the items or features users can purchase. You will see a Create SKU button which will open a dropdown list. Select Durable for the sake of this guide. Then, you will see the details you can set: Name, description, image, price, etc. Once entered, make sure that your SKU is published too! Otherwise users won't be able to use it.

image

SKU Types

Every SKU has it's own type that you'll see on your API calls. Here are their values:

  • DURABLE: 2
  • CONSUMABLE: 3
  • SUBSCRIPTION: 5
  • SUBSCRIPTION_GROUP: 6

Testing In-Application Purchases

Due to Discord’s testing limitations, it’s recommended to use SKU type 5 (Subscription) for integration and entitlement testing. One-time payments are unavailable for testing purposes and will incur charges. What you can do for one-time payment tests is set your app in Test Mode. Also check out how to create Test Entitlements.

How to Implement IAP in Our App

In our app, we want to add a basic button to buy a badge on our Phaser Discord. It will be one-time durable purchase (yes, you'll keep it forever!), which will give you a badge icon that everyone else will be able to see for super-duper Phaser fans!

Like we discussed in SKU types above, you can implement any of them right away. All we need is to get the "sku id".

How do we do that?

getSkus() will give you the list of all published SKUs.

Here is our sample code:

const skuList = await discordSdk.commands.getSkus();
const phaserFanSku = skuList.skus.find((sku) => sku.name === 'Phaser SuperFan Badge');

As you can see, after we get the list, we filter the data to get the one we want.

A typical array response will look like this:

application_id: "1230985589749498238"
flags: 4
id: "1234608976908234756"
name: "Phaser SuperFan Badge"
price: 
    amount: 0
    currency: "usd"
release_date: null
type: 2

Purchase time!

The Discord API gives us the startPurchase function to handle the payment within the Discord app itself:

const purchase = await discordSdk.commands.startPurchase({
    sku_id: phaserFanSku.id,
});

Perfect. Now, how can we check if our user already has the SKU?

When a purchase is complete, Discod will emit an ENTITLEMENT_CREATE event. We can subscribe to this event via Embedded App SDK.

const handleEntitlementCreate = () => {
  // do all the checks here
};

discordSdk.subscribe('ENTITLEMENT_CREATE', handleEntitlementCreate);

getEntitlements() returns the users current entitlements, which are subscriptions and one-time purchases.

const handleEntitlementCreate = () => {
  const entitlementList = await discordSdk.commands.getEntitlements();

  const isSuperFan = entitlementList.entitlements.find((entitlement) => entitlement.sku_id === selectedSku.id);
};

discordSdk.subscribe('ENTITLEMENT_CREATE', handleEntitlementCreate);

Note that our way is not the safest options for possible attackers! It is important to consider security when we are working with SKUs and entitlements and not fully rely on SDK itself. The best bet would be combining both SDK commands and Gateway API requests to ensure the data with the server. You can read more to see what can be done about this.

And that's it for the check! The rest is all how you shape it for your user flow.

The array response will look like this:

application_id: "1235678908495193584"
deleted: false
ends_at: null
gift_code_flags: 0
id: "1348770093284092846"
sku_id: "1545992732949795748"
starts_at: null
type: 4
user_id: "584812085982487912"

Let's Test!

Once we deploy our app to Discord, we can test if our purchase pop-up will appear or not:

image

Here it comes!

image

Discord will automatically convert the currency based on the players location.

Once the purchase is complete, you will see this message:

image