Economy
Read more about the Economy system in Hiro here
.
Store type configuration
#
When making hard currency purchases, set the correct EHiroEconomyStoreType based on the player’s platform. The store type determines which platform’s receipt validation endpoint the server uses.
| Value | Description |
|---|
ECONOMY_STORE_TYPE_APPLE_APPSTORE | Apple App Store |
ECONOMY_STORE_TYPE_GOOGLE_PLAY | Google Play Store |
ECONOMY_STORE_TYPE_FBINSTANT | Facebook Instant Games |
ECONOMY_STORE_TYPE_UNSPECIFIED | Defaults to Apple App Store |
For more details on store types and purchase validation, see Virtual Store
.
Initializing the economy system
#
The economy system requires a logger, the Nakama system, and the store type for receipt validation.
1
2
3
4
5
6
7
8
9
10
11
12
| EEconomyStoreType StoreType;
#if PLATFORM_ANDROID
StoreType = EEconomyStoreType::GooglePlay;
#elif PLATFORM_IOS
StoreType = EEconomyStoreType::AppleAppstore;
#else
StoreType = EEconomyStoreType::Unspecified;
#endif
auto EconomySystem = MakeShared<FHiroEconomySystem>(Logger, NakamaSystem, StoreType);
Systems.Add(EconomySystem);
|
Donation claim
#
Claim one or more rewards which are partially or full donated by other players.
1
2
3
4
5
6
7
8
9
10
11
12
13
| FHiroEconomyDonationClaimRequest Request;
Request.Items = {TEXT("donation_1"), TEXT("donation_2")};
FHiroOnEconomyDonationClaim OnEconomyDonationClaim;
OnEconomyDonationClaim.AddDynamic(this, &AMyActor::OnEconomyDonationClaim);
FOnError OnError;
HiroClient->EconomyDonationCLaim(Session, Request, OnEconomyDonationClaim, OnError);
void AMyActor::OnEconomyDonationClaim(const FHiroEconomyDonationClaimRewards& EconomyDonationClaimRewards)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyDonationClaimRewards.ToJson());
}
|
Donate to a user
#
Donate some resource (currencies, items, etc.) to a user by donation ID.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| FHiroEconomyDonationGiveRequest Request;
Request.UserId = TEXT("user_1");
Request.DonationId = TEXT("donation_1");
FHiroOnEconomyDonationGive OnEconomyDonationGive;
OnEconomyDonationGive.AddDynamic(this, &AMyActor::OnEconomyDonationGive);
FOnError OnError;
HiroClient->EconomyDonationGive(Session, Request, OnEconomyDonationGive, OnError);
void AMyActor::OnEconomyDonationGive(const FHiroEconomyUpdateAck& EconomyUpdateAck)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyUpdateAck.ToJson());
}
|
Get donation progress
#
Get progress on one or more donations for a set of players by their IDs.
1
2
3
4
5
6
7
8
9
10
11
12
13
| FHiroEconomyDonationGetRequest Request;
Request.Ids = {TEXT("donation_1"), TEXT("donation_2")};
FHiroOnEconomyDonationGet OnEconomyDonationGet;
OnEconomyDonationGet.AddDynamic(this, &AMyActor::OnEconomyDonationGet);
FOnError OnError;
HiroClient->EconomyDonationGet(Session, Request, OnEconomyDonationGet, OnError);
void AMyActor::OnEconomyDonationGet(const FHiroEconomyDonationsByUserList& EconomyDonationsByUserList)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyDonationsByUserList.ToJson());
}
|
Request a donation
#
Request a donation which other players can contribute into.
1
2
3
4
5
6
7
8
9
10
11
12
13
| FHiroEconomyDonationRequest Request;
Request.DonationId = TEXT("donation_1");
FHiroOnEconomyDonationRequest OnEconomyDonationRequest;
OnEconomyDonationRequest.AddDynamic(this, &AMyActor::OnEconomyDonationRequest);
FOnError OnError;
HiroClient->EconomyDonationRequest(Session, Request, OnEconomyDonationRequest, OnError);
void AMyActor::OnEconomyDonationRequest(const FHiroEconomyDonationAck& EconomyDonationAck)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyDonationAck.ToJson());
}
|
Get store items
#
Get all store items defined in the Virtual Store.
1
2
3
4
5
6
7
8
9
10
11
12
13
| FHiroEconomyListRequest Request;
Request.StoreType = EHiroEconomyStoreType::ECONOMY_STORE_TYPE_APPLE_APPSTORE;
FHiroOnEconomyStoreGet OnEconomyStoreGet;
OnEconomyStoreGet.AddDynamic(this, &AMyActor::OnEconomyStoreGet);
FOnError OnError;
HiroClient->EconomyStoreGet(Session, Request, OnEconomyStoreGet, OnError);
void AMyActor::OnEconomyStoreGet(const FHiroEconomyList& EconomyList)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyList.ToJson());
}
|
Get store items by category
#
Get store items from the Virtual Store filtered to a specific category.
1
2
3
4
5
6
7
| HiroClientExtension->EconomyStoreGetByCategory(HiroClient, Session, Request, TEXT("coin_packs"),
OnEconomyStoreGet, OnError);
void AMyActor::OnEconomyStoreGet(const FHiroEconomyList& EconomyList)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyList.ToJson());
}
|
Passing an empty category returns all store items.
Grant currencies or reward modifiers
#
Grant one or more currencies or reward modifiers to the player.
1
2
3
4
5
6
7
8
9
10
11
12
13
| FHiroEconomyGrantRequest Request;
Request.Currencies.Add(TEXT("coins"), 100);
FHiroOnEconomyGrant OnEconomyGrant;
OnEconomyGrant.AddDynamic(this, &AMyActor::OnEconomyGrant);
FOnError OnError;
HiroClient->EconomyGrant(Session, Request, OnEconomyGrant, OnError);
void AMyActor::OnEconomyGrant(const FHiroEconomyUpdateAck& EconomyUpdateAck)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyUpdateAck.ToJson());
}
|
Send a purchase intent
#
Send a marker of intent to purchase by the player.
1
2
3
4
5
6
7
8
9
10
| FHiroEconomyPurchaseIntentRequest Request;
Request.ItemId = TEXT("item_1");
Request.StoreType = EHiroEconomyStoreType::ECONOMY_STORE_TYPE_APPLE_APPSTORE;
Request.Sku = TEXT("sku_1");
FHiroOnEconomyPurchaseIntent OnEconomyPurchaseIntent;
OnEconomyPurchaseIntent.AddDynamic(this, &AMyActor::OnEconomyPurchaseIntent);
FOnError OnError;
HiroClient->EconomyPurchaseIntent(Session, Request, OnEconomyPurchaseIntent, OnError);
|
Purchase a store item
#
Purchase a store item by the player.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| FHiroEconomyPurchaseRequest Request;
Request.ItemId = TEXT("item_1");
Request.StoreType = EHiroEconomyStoreType::ECONOMY_STORE_TYPE_APPLE_APPSTORE;
Request.Receipt = TEXT("<receipt>");
FHiroOnEconomyPurchaseItem OnEconomyPurchaseItem;
OnEconomyPurchaseItem.AddDynamic(this, &AMyActor::OnEconomyPurchaseItem);
FOnError OnError;
HiroClient->EconomyPurchaseItem(Session, Request, OnEconomyPurchaseItem, OnError);
void AMyActor::OnEconomyPurchaseItem(const FHiroEconomyPurchaseAck& EconomyPurchaseAck)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyPurchaseAck.ToJson());
}
|
The server populates Inventory only when the purchase changes the player’s inventory. Purchases that grant currency alone leave it unpopulated.
When populated, Inventory holds the player’s complete inventory, not only the items the purchase added. Replace your local copy instead of merging into it.
An unpopulated Inventory means the purchase left it unchanged. It doesn’t mean the player owns nothing, so don’t clear cached inventory state when this field is empty.
Get ad placement status
#
Get the current status on an Ad placement which may have been rewarded.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| FHiroEconomyPlacementStatusRequest Request;
Request.RewardId = TEXT("reward_1");
Request.PlacementId = TEXT("placement_1");
Request.Count = 0;
FHiroOnEconomyPlacementStatus OnEconomyPlacementStatus;
OnEconomyPlacementStatus.AddDynamic(this, &AMyActor::OnEconomyPlacementStatus);
FOnError OnError;
HiroClient->EconomyPlacementStatus(Session, Request, OnEconomyPlacementStatus, OnError);
void AMyActor::OnEconomyPlacementStatus(const FHiroEconomyPlacementStatus& EconomyPlacementStatus)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyPlacementStatus.ToJson());
}
|
Start a new ad placement
#
Start a new Ad placement by placement ID.
1
2
3
4
5
6
7
8
9
10
11
12
13
| FHiroEconomyPlacementStartRequest Request;
Request.PlacementId = TEXT("placement_1");
FHiroOnEconomyPlacementStart OnEconomyPlacementStart;
OnEconomyPlacementStart.AddDynamic(this, &AMyActor::OnEconomyPlacementStart);
FOnError OnError;
HiroClient->EconomyPlacementStart(Session, Request, OnEconomyPlacementStart, OnError);
void AMyActor::OnEconomyPlacementStart(const FHiroEconomyPlacementStatus& EconomyPlacementStatus)
{
UE_LOG(LogTemp, Log, TEXT("%s"), *EconomyPlacementStatus.ToJson());
}
|
Placement success
#
Webhook RPC to handle Rewarded Video Ad placement success callbacks.
1
2
3
4
5
| FHiroOnEconomyPlacementSuccess OnEconomyPlacementSuccess;
OnEconomyPlacementSuccess.AddDynamic(this, &AMyActor::OnEconomyPlacementSuccess);
FOnError OnError;
HiroClient->EconomyPlacementSuccess(Session, OnEconomyPlacementSuccess, OnError);
|
Placement fail
#
Webhook RPC to handle Rewarded Video Ad placement failure callbacks.
1
2
3
4
5
| FHiroOnEconomyPlacementFail OnEconomyPlacementFail;
OnEconomyPlacementFail.AddDynamic(this, &AMyActor::OnEconomyPlacementFail);
FOnError OnError;
HiroClient->EconomyPlacementFail(Session, OnEconomyPlacementFail, OnError);
|