From 5dd80d4626019ca3733a5903b89edb90d9bf52b6 Mon Sep 17 00:00:00 2001 From: Junesig Kong Date: Tue, 26 May 2026 12:32:49 +0900 Subject: [PATCH 1/2] Update reward rate card flow and BillingClient logic --- .../Blueprints/Game/BP_GameInstance.uasset | 4 +- .../Blueprints/Widgets/WBP_Store.uasset | 4 +- .../GameInstances/TrivialKartGameInstance.cpp | 44 +++++++++++++++++++ .../GameInstances/TrivialKartGameInstance.h | 2 +- .../TrivialKart_Unreal.Build.cs | 7 +-- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/trivialkart/trivialkart_unreal/Content/Blueprints/Game/BP_GameInstance.uasset b/trivialkart/trivialkart_unreal/Content/Blueprints/Game/BP_GameInstance.uasset index b1bfbaa1..4e96c8a3 100644 --- a/trivialkart/trivialkart_unreal/Content/Blueprints/Game/BP_GameInstance.uasset +++ b/trivialkart/trivialkart_unreal/Content/Blueprints/Game/BP_GameInstance.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2dd643244fe507e5e7b58d4d6d6754a43df1b8fd9ee09fa6549ca697578431ca -size 6232 +oid sha256:6cd514997ea43a57197cb88bfe9e8c813e565b0c1e0fb3f7e8f70ce24568f1ab +size 6249 diff --git a/trivialkart/trivialkart_unreal/Content/Blueprints/Widgets/WBP_Store.uasset b/trivialkart/trivialkart_unreal/Content/Blueprints/Widgets/WBP_Store.uasset index 1e0026fe..459dabcf 100644 --- a/trivialkart/trivialkart_unreal/Content/Blueprints/Widgets/WBP_Store.uasset +++ b/trivialkart/trivialkart_unreal/Content/Blueprints/Widgets/WBP_Store.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9a3649d582676e91ab81ec283d13b03d7677c15ad088946dd7124866fb8292f5 -size 260559 +oid sha256:23f18ee2816b929883fa17ea67c97380b13981df62f594cd5fd21097c9ad2038 +size 265608 diff --git a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp index 7e99bc65..6a3a99ea 100644 --- a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp +++ b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp @@ -47,6 +47,9 @@ void UTrivialKartGameInstance::Init() FOnReadUserFileCompleteDelegate::CreateUObject(this, &UTrivialKartGameInstance::OnCloudWriteComplete)); } InitiateAutoLogin(); + // Check unacknowledged purchases on start or foreground + CheckPendingPurchases(); + FCoreDelegates::ApplicationHasEnteredForegroundDelegate.AddUObject(this, &UTrivialKartGameInstance::CheckPendingPurchases); } void UTrivialKartGameInstance::Shutdown() @@ -60,6 +63,8 @@ void UTrivialKartGameInstance::Shutdown() CloudInterface->ClearOnReadUserFileCompleteDelegate_Handle(ReadSaveHandle); CloudInterface->ClearOnWriteUserFileCompleteDelegate_Handle(WriteSaveHandle); } + FCoreDelegates::ApplicationHasEnteredForegroundDelegate.RemoveAll(this); + Super::Shutdown(); } void UTrivialKartGameInstance::InitiateAutoLogin() @@ -161,6 +166,45 @@ void UTrivialKartGameInstance::StartPurchasing(const FUniqueOfferId& OfferID, co } } +void UTrivialKartGameInstance::CheckPendingPurchases() +{ + if (const IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld())) + { + if (const IOnlineIdentityPtr IdentityInterface = Online::GetIdentityInterface(GetWorld())) + { + if (const TSharedPtr UserId = IdentityInterface->GetUniquePlayerId(0); UserId.IsValid()) + { + if (const IOnlinePurchasePtr PurchaseInterface = Online::GetPurchaseInterface(GetWorld()); PurchaseInterface.IsValid()) + { + PurchaseInterface->QueryReceipts(*UserId, true, + FOnQueryReceiptsComplete::CreateWeakLambda(this, + [this, PurchaseInterface, UserId](const FOnlineError& OnlineError) + { + if (!OnlineError.WasSuccessful()) + return; + + TArray Receipts; + PurchaseInterface->GetReceipts(*UserId, Receipts); + + for (const FPurchaseReceipt& Receipt : Receipts) + { + for (const FPurchaseReceipt::FReceiptOfferEntry& Offer : Receipt.ReceiptOffers) + { + if (OnPurchaseReceived.IsBound()) + { + OnPurchaseReceived.Broadcast(Offer.OfferId, 1); + FPlatformMisc::LowLevelOutputDebugStringf(TEXT(" Pending purchase restored - Offer ID:: %s"), *Offer.OfferId); + } + // The Purchase Token is passed as the ReceiptId to tell the platform which purchase to finalize (consume/acknowledge). + PurchaseInterface->FinalizePurchase(*UserId, Receipt.TransactionId); + } + } + })); + } + } + } + } +} UTrivialKartSaveGame* UTrivialKartGameInstance::LoadGame() { #if WITH_EDITOR diff --git a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Public/GameInstances/TrivialKartGameInstance.h b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Public/GameInstances/TrivialKartGameInstance.h index 1bbcec9c..943f5ab5 100644 --- a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Public/GameInstances/TrivialKartGameInstance.h +++ b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Public/GameInstances/TrivialKartGameInstance.h @@ -54,7 +54,7 @@ class TRIVIALKART_UNREAL_API UTrivialKartGameInstance : public UPlatformGameInst void AddAchievementProgress(const float Progress, const FString& AchievementName); void StartPurchasing(const FUniqueOfferId& OfferID, const int32 Quantity, bool bIsConsumable); - + void CheckPendingPurchases(); UTrivialKartSaveGame* LoadGame(); void SaveGame(UTrivialKartSaveGame* SaveData); diff --git a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/TrivialKart_Unreal.Build.cs b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/TrivialKart_Unreal.Build.cs index 26ed4808..cdfb7dde 100644 --- a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/TrivialKart_Unreal.Build.cs +++ b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/TrivialKart_Unreal.Build.cs @@ -37,13 +37,14 @@ public TrivialKart_Unreal(ReadOnlyTargetRules Target) : base(Target) PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", - "OnlineSubsystemUtils" - }); + "OnlineSubsystemUtils", + "Json", + "JsonUtilities" + }); if (Target.Platform == UnrealTargetPlatform.Android) { DynamicallyLoadedModuleNames.Add("OnlineSubsystemGooglePlay"); - DynamicallyLoadedModuleNames.Add("OnlineSubsystemGooglePlayExtension"); } } } From 808cfd012e918b98d9542ae95aaffe352b1452a9 Mon Sep 17 00:00:00 2001 From: Junesig Kong Date: Tue, 26 May 2026 17:06:47 +0900 Subject: [PATCH 2/2] Fixed CheckPendingPurchases which is happening before login --- .../Private/GameInstances/TrivialKartGameInstance.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp index 6a3a99ea..0ba1860f 100644 --- a/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp +++ b/trivialkart/trivialkart_unreal/Source/TrivialKart_Unreal/Private/GameInstances/TrivialKartGameInstance.cpp @@ -48,7 +48,6 @@ void UTrivialKartGameInstance::Init() } InitiateAutoLogin(); // Check unacknowledged purchases on start or foreground - CheckPendingPurchases(); FCoreDelegates::ApplicationHasEnteredForegroundDelegate.AddUObject(this, &UTrivialKartGameInstance::CheckPendingPurchases); } @@ -274,6 +273,8 @@ void UTrivialKartGameInstance::OnLoginCompleted(int32 LocalUserNum, bool bWasSuc CloudInterface->ReadUserFile(*IdentityInterface->GetUniquePlayerId(0), "TrivialKartCloudSave"); } } + // Check unacknowledged purchases on start or foreground + CheckPendingPurchases(); } }