Set up the grants #

You will need to map your order mapping SKUs to item grants in Pragma.

This is done by

  1. Creating player data operations that will grant the items
  2. Adding a fulfillment mapping content catalog that glues everything together.

Define operations #

You need to define player data operations that will be called by the Fulfillment service.

The example below shows how to implement a grantCoins operation.

Please note that this example is not intended for production and only includes the basic implementation for granting coins. You may want to add additional validation, custom errors, and platform tracking.

[project]/[project]-player-data/player-data/src/main/kotlin/[project]/FulfillmentOperations.kt

package documentation

import pragma.playerdata.Component
import pragma.playerdata.Context
import pragma.playerdata.FieldNumber
import pragma.playerdata.PlayerDataContentLibrary
import pragma.playerdata.PlayerDataOperation
import pragma.playerdata.PlayerDataRequest
import pragma.playerdata.PlayerDataResponse
import pragma.playerdata.PlayerDataSubService
import pragma.rpcs.SessionType
import pragma.types.SerializedName

// Component that track a currency type, balance, and platform
@SerializedName("<CURRENT-EPOCH-SECONDS>")
data class Currency(
    @FieldNumber(1) val id: String,
    @FieldNumber(2) var balance: Int,
    @FieldNumber(3) var platformId: String,
): Component

data class GrantCoins(
    val id: String,
    val amount: Int
): PlayerDataRequest
class GrantCoinsResponse: PlayerDataResponse

class FulfillmentOperations(
    contentLibrary: PlayerDataContentLibrary
) : PlayerDataSubService(contentLibrary) {

    // Requirement: you must allow SessionType.SERVICE
    // this provides access for the Fulfillment Service to call player data
    @PlayerDataOperation(sessionTypes = [SessionType.SERVICE])
    fun grantCoins(
        request: GrantCoins,
        context: Context
    ): GrantCoinsResponse {
        /**
         * All operations called through the fulfillment service
         * include the platformId the order was made through
          */
         val platformId = context.getDataBy("platformId") ?: "IN-GAME"

        val entity = context.snapshot.getOrCreateUniqueEntity("Currencies")
        var coinsComponent = entity
            .getComponentsByType<Currency>()
            .singleOrNull { it.id == request.id && it.platformId == platformId }
        if (coinsComponent == null) {
            val id = entity.addComponent(Currency(request.id, 0, platformId))
            coinsComponent = entity.getComponentById(id)
        }
        coinsComponent!!.balance += request.amount
        return GrantCoinsResponse()
    }
}

Build the project to run player data code generation.

./pragma build -s

See the Player Data Overview page for more information on player data.

Add fulfillment mapping content #

Once you have defined the fulfillment operations, you can create the fulfillment mapping content catalog.

Below is an example of a fulfillment spec configured to use the grant coins operation.

The content catalog must be defined in the FulfillmentMappingSpecs.json.

[project]/content/src/FulfillmentMappingSpecs.json

[
  {
    "skuId": "GoldBundle100",
    "operations": {
      "fulfillmentOperation": {
        "grantCoins": {
          "id": "gold",
          "amount": "100"
        }
      }
    }
  }
]

Run the content apply command to validate and generate content catalogs.

./pragma content apply