# PC SDK Unreal Integration Guide
# Introduction
The STOVE platform for games provides integrated services. All processes of game release, including game distribution and sales, community, and indicator analysis, can be handled in one-stop.
With the STOVE PC SDK (Unreal version, hereafter referred to as PC SDK), you can easily integrate the services provided by the Stove platform into your game.
This section describes how to integrate the PC SDK.
if this is your first time integrating the PC SDK, please first read PC SDK Unreal Walkthrough
# Preparation in advance
- Only works with UNREAL Engine 4.22.3 and above, lower versions require the [Native StovePCSDK] (../Integration/native.md) integration.
- Check that you have issued the stove subscription account and the App key, App secret, and Game Id for the released game from STOVE Studio (opens new window).
- Make sure you have Visual Studio 2015 Update 3 or higher compiler installed.
- Download the latest
Unreal
distribution file (Shown asPlugin
) from the PC SDK Download page.
# Plugin
Distribution File Configuration
# 1) include folder
After downloading and unpacking Plugin
, the following files are included in Plugins\StoveSDKPlugin\Binaries\ThirdParty\StoveSDKPluginLibrary\include
folder.
StovePCCallback.h
- Header file for callback definitions to receive callbacks after calls to the Stove plugin and NativeSDK API.
StovePCEnum.h
- This header file contains enumerations defined by the NativeSDK, such as error, API type, and asynchronous status values.
StovePCDefine.h
- Declared API call result (StovePCResult), error result structure (FStoveError), callback function, API request/response parameters, etc. used for communication between Stove plugin and NativePCSDK.
StovePCSDK.h
- API functions used for communication between the Stove plugin and NativePCSDK are declared.
# 2) Unreal API Include folder
After downloading and extracting Plugin
, the following files are included in Plugins\StoveSDKPlugin\Source\StoveSDKPlugin\Public
folder.
StoveSDKEnum.h
- Enum defined in stove plug-in is declared.
StoveSDKNativeCallback.h
- This is a file that implements a callback function that delivers events between the stove plug-in and NativePCSDK.
StoveSDKObject.h
- This is a UObject-type class that receives callbacks and UE4 API that wraps the NativePCSDK API that inherits from UObject.
StoveSDKPlugin.h
- Module wrapper class to load NativePCSDK module from Stove plugin.
StoveSDKStruct.h
- Struct set header to pass after API call from stove plugin.
StoveSDKVersion.h
- This file is used to check the Unreal version in Stove.
StoveSDKWebInterface.h
- This is an interface class for linking with StoveWebPlugin provided by Stove.
# 3) Bin folder
Under the Plugins\StoveSDKPlugin\Binaries\ThirdParty\StoveSDKPluginLibrary\bin
folder, binaries required for each platform (x64) and configuration (Release) are included.
concrt140.dll
msvcp100.dll
msvcp140.dll
msvcr100.dll
sgup_api(64).dll
StovePCSDK.dll
vcruntime140.dll
Except for StovePCSDK.lib
, the files in the list above must be distributed together when distributing the game client to end users.
# 4) StoveSDKPlugin.uplugin
This file is for recognizing plugins in Unreal. It should be placed inside Plugins
within your game project.
# Integration
StovePCSDK_Unreal
uses Unreal Engine'sUStoveSDKObject
class which is anUObject
type class. Here, we have redefined the data types, interfaces, and callback functions of the StovePCSDK library. Before integrating, use after inheriting the definedUStoveSDKObject
ofPlugin
and configuringUMyStoveSDKObject
in the game engine.Prefix
There is a rule with Unreal Engine that the prefixU
is added to the classes that inherit theUObject
type.
We call the interface imported from the inherited UObject to the Plugin through Super.
Super
The keyword provided by Unreal to call an inherited parent's function isSuper
.
FStoveResult UMyStoveSDKObject::StoveSDKInit(const FStoveConfig& fConfig)
{
FStoveResult fResult = Super::StoveSDKInit(fConfig);
}
2
3
4
For the
Plugin
environment configuration, refer to theConfiguring the project environment
, categories 1 to 3, in PC SDK Unreal Walkthrough
# 1) Config, Callback Settings
Suppose you wish to initialize the PC SDK. In that case, you must fill the FStoveConfig
values and call the UStoveSDKObject::StoveSDKInit
function of the inherited Actor.
Refer to the code below and fill in the field values of the FStoveConfig
structures.
FStoveConfig fConfig{"LIVE",
"YOUR_APP_KEY",
"YOUR_SECRET_KEY",
"YOUR_GAME_ID",
StovePCLogLevel::STOVE_PC_LOG_LEVEL_DEBUG,
""};
2
3
4
5
6
For the description of the FStoveConfig
structure, refer to the StoveSDKStruct.h
file in the Plugins\StoveSDKPlugin\Source\StoveSDKPlugin\Public
folder.
To call the API of the PC SDK in the game project and check the result, you need to use the callback function. The callback function used in the game project is as follows.
//StovePCSDK Callback
public:
void OnError(FStoveError Error) final;
void OnInitComplete() final;
void OnToken(FStoveToken Token) final;
void OnUser(FStoveUser User) final;
void OnOwnership(int Size, FStoveOwnership* Ownerships) final;
2
3
4
5
6
7
The OnError
, OnInitComplete
and OnOwnership
callback functions must work together. You can integrate the rest of the callback functions only when necessary.
For example, suppose you only use the Ownership function. In that case, you can implement it by defining it in the game project, as shown below.
/*As for when only using the Ownership function,
apart from the essential callbacks OnError, OnInitcomplte,
connect only the OnOwnership callback additionally.*/
void UMyStoveSDKObject::OnInitComplete()
{
// Process detail after successful initialization
}
void UMyStoveSDKObject::OnError(FStoveError Error)
{
// Process detail of the error
}
void UMyStoveSDKObject::OnOwnership(int Size, FStoveOwnership* Ownerships)
{
// Process detail after the viewing ownership
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2) SDK Initialization
Before using the API of PC SDK, enter the initialization code as shown below in the UMyStoveSDKObject::StoveSDKInit
function of MyStoveSDKObject.cpp
for initialization.
FStoveResult UMyStoveSDKObject::StoveSDKInit(const FStoveConfig& Config)
{
FStoveResult ErrorResult = Super::StoveSDKInit(Config);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
/*StovePCSDK init Success*/
}
}
2
3
4
5
6
7
8
9
The UMyStoveSDKObject::StoveSDKInit
function immediately returns the FStovePCResult
enum type value after checking only the validity of config and callback.
In case of success, it returns a value of STOVE_PC_NO_ERROR
. In case of failure, it returns the corresponding error code, and you need to quit the game.
For the entire list of error codes, refer to the StovePCDefine.h
file.
Precautions
Please be sure to write your code to call the StovePC_RunCallback
function and other callback functions that work with the PCSDK from the main thread
.
The UMyStoveSDKObject::StoveSDKInit
function handles other operations asynchronously, except config and callback validation.
When you have completed the asynchronous operation, it calls the UMyStoveSDKObject::OnInitComplete
callback. And it calls UMyStoveSDKObject::OnError
callback when there is an error.
If an error occurs during initialization, you can check the error code and message through the StovePCError
structure passed to the UMyStoveSDKObject::OnError
function.
The fError.result.result value of the StovePCError
structure parameter is the same as the StovePCResult enum. So you can infer the error condition from the error code.
void UMyStoveSDKObject::OnInitComplete()
{
OnLog("[OnInitComplete]");
}
void UMyStoveSDKObject::OnError(const FStoveError& Error)
{
switch (Error.FunctionType)
{
case STOVE_PC_INIT:
case STOVE_PC_GET_USER:
case STOVE_PC_GET_OWNERSHIP:
QuitApplicationDueToError();
break;
}
}
void UMyStoveSDKObject::QuitApplicationDueToError()
{
// After showing the user a message about app outage rather than stopping it immediately
// Depending on user action (e.g. clicking the exit button), you may want to terminate the app.
// If so, implement your own logic.
// Recommended messages for required pre-task errors are as follows.
// Korean: The required pre-task failed to operate and the game has been terminated.
// Other Languages: The required pre-task fails and exits the game.
OnStoveLog("QuitApplicationDueToError");
FGenericPlatformMisc::RequestExit(false);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Before the UMyStoveSDKObject::OnInitComplete
callback comes, if it is necessary to view the initialization state value of the PC SDK, you can use the UMyStoveSDKObject::GetInitState
function.
/*After calling StovePC.Init..*/
while (Super::GetInitState().state
== StovePCInitState::STOVE_PC_INIT_PENDING)
{
FPlatformProcess::Sleep(0.5f);
RunCallback();
}
if (Super::GetInitState().state
== StovePCInitState::STOVE_PC_INIT_COMPLETE)
{
/*Initialization Complete
OnInitComplete callback is called*/
return FStoveResult{STOVE_PC_NO_ERROR};
}
else
{
/*Initialization failed
OnError callback is called*/
return FStoveResult{ STOVE_PC_NO_ERROR };;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3) Cautions when integrating the SDK
When setting the log level of the
FStovePCConfig
structure, which is a parameter of theStoveSDKInit
function, enter the valueStovePCLogLevel::STOVE_PC_LOG_LEVEL_DEBUG
for the Debug build. For the official build, please setStovePCLogLevel::STOVE_PC_LOG_LEVEL_ERROR
to prevent unnecessary log creation.
If the
GetToken
,GetUser
,GetOwnership
methods are called before initialization is complete, it may not return normal results. In other words, you must call theGetToken
,GetUser
,GetOwnership
methods after receiving the callback ofOnInitComplete
to receive normal results.
# 4) SDK Termination
After using the PC SDK, call the StoveSDKUnInit
function to clean up the resources in use. After reaching the StoveSDKUnInit
function, the API of PC SDK does not work.
FStoveResult UMyStoveSDKObject::StoveSDKUnInit()
{
FStoveResult ErrorResult = Super::StoveSDKUnInit();
if (ErorrResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
/*Success Process*/
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
# 5) Receive user information
Use the UMyStoveSDKObject::StoveSDKGetUser
function to retrieve the logged-in user information in STOVE Launcher.
FStoveResult UMyStoveSDKObject::StoveSDKGetUser()
{
FStoveResult ErrorResult = Super::StoveSDKGetUser();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
/*Success Process*/
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
The UMyStoveSDKObject::OnUser
callback is called when the UMyStoveSDKObject::StoveSDKGetUser
function is processed properly.
You can know the user's memberNo, Nickname, Game User ID information through the StovePCUser
structure passed to the callback.
void UMyStoveSDKObject::OnUser(FStoveUser User)
{
/*User Information Output*/
OnLog("[User]");
OnLog("MemberNo : %u", User.MemberNo);
OnLog("Nickname : %s", *(User.Nickname));
OnLog("GameUserId: %s", *(User.GameUserId));
}
2
3
4
5
6
7
8
# 6) Get Token Information
Get token information of the user who logged in to STOVE launcher with UMyStoveSDKObject::StoveSDKGetToken
function.
FStoveResult UMyStoveSDKObject::StoveSDKGetToken()
{
FStoveResult ErrorResult = Super::StoveSDKGetToken();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
/*Success Process*/
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
The UMyStoveSDKObject::OnToken
callback is called when the UMyStoveSDKObject::StoveSDKGetToken
function is processed properly.
It contains the token string in the StovePCToken
structure delivered to the callback.
void UMyStoveSDKObject::OnToken(FStoveToken Token)
{
/*Token Information Output*/
OnLog("AccessToken : %s", *(Token.AccessToken));
}
2
3
4
5
What is a token? It is the access token of the logged-in user in
STOVE Launcher
, and the game server passes this access token to the stove authentication server to validate the logged-in user.
For a detailed explanation of Access Token, please get in touch with store.support@smilegate.com for technical support.
# 7) Get ownership information
With the UMyStoveSDKObject::StoveSDKGetOwnership
function, you can inquire whether the user of the STOVE launcher has purchased and owns a game registered in STOVE Studio.
FStoveResult UMyStoveSDKObject::StoveSDKGetOwnership()
{
FStoveResult Result = Super::StoveSDKGetOwnership();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
/*Success Process*/
/*It delivers information about ownership to the OnOwnership callback.*/
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
The UMyStoveSDKObject::OnOwnership
callback is called when the UMyStoveSDKObject::StoveSDKGetOwnership
function is processed properly.
For detailed information on the StovePCOwnership
structure, refer to the StovePCDefine.h
file.
Below is an example code that determines the purchase status of a game in the OnOwnership callback. If the game is without DLC, the confirmation code for lines 20 to 23 is unnecessary.
void UMyStoveSDKObject::OnOwnership(int size, FStoveOwnership* Ownership)
{
bool owned = false;
FStoveOwnership* data = fOwnership;
for (int i = 0; i < size; i++, data++)
{
if ((data->MemberNo != LOGIN_USER_MEMBER_NO /* StovePCUser Structural memberNo*/)
|| (data->OwnershipCode != 1 /* 1: Having the ownership, 2: Ownership removed (Cancelling the purchase)*/))
{
continue;
}
if (0 == wcscmp(L"YOUR_GAME_ID", *(data->GameId)) && data->GameCode == 3 /*3: BASIC, 4: DEMO*/)
{
owned = true; // Set ownership verification variable to true
}
/*Required only for games selling DLC*/
if (0 == wcscmp(L"YOUR_DLC_ID", *(data->GameId)) && data->GameCode == 5 /* 5: DLC*/)
{
/*User owns YOUR_DLC_ID(DLC). allow DLC play*/
}
}
if(owned)
{
// Write game entry logic after ownership verification is usually completed
}
else
{
// After ownership verification fails, end the game and write an error message display logic
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
You can play the game after logging in to the STOVE launcher with the account that purchased the game (with ownership).
After logging in to the STOVE launcher with an account that does not own the game, the following guide message (example) is output when you execute the exe and then terminate the game.
- "Please log in to STOVE Client with the account that has purchased the game."
You don't need an account with game ownership to test the ownership feature. See FAQ.
# 9) Language translation 2.6.0
Translate languages with UMyStoveSDKObject::StoveSDKTranslateLanguage
function.
PC SDK provides a translation for a specific string based on the set language information.
A specific string is managed as a String ID managed by the PC SDK.
If the game implements the PC SDK popup UI directly, the string displayed in the UI must display the translated string through the UMyStoveSDKObject::StoveSDKTranslateLanguage
function.
FString Translated=UMyStoveSDKObject::StoveSDKTranslateLanguage("STRING_ID");
Precautions
Returns an English translation if there is no translation of a specific string for the language set in the PC SDK.
For exceptions or unsupported string IDs, the input parameter (string ID) is returned as it is.
# Check Error
The errors that occur while using the PC SDK are usually one of two cases.
# StovePCResult enum value returned after calling the function
All PC SDK's functions will return a StovePCResult
enum value immediately after calling to mark whether the call was successful.
The entire value can be checked in the PC SDK Error Code page.
# The StovePCError structure delivered through the OnError callback.
Suppose an error occurs in an asynchronous function during the PC SDK function. In that case, it calls a UMyStoveSDKObject::OnError
callback and delivers a StovePCError
structure with a description of the error.
/*Delivered when an OnError callback is called.*/
struct StovePCError
{
/*enum value which indicates the called function*/
StovePCFunctionType functionType;
/*enum value which indicates the occurred error type*/
StovePCResult result;
/*Occurred Error Message*/
char* message;
/*The corresponding error code if an external error (http error, external module error) has occurred*/
int externalError;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Integrating pop-ups
The PC SDK provides APIs to integrate popups into your game. Pop-ups supported by PC SDK include automatic, manual, news, coupon, and community.
The PC SDK provides data for popups to the game. The game creates a pop-up view using the provided data.
Each popup is defined as follows.
- Automatic pop-up: Pop-up that is most exposed on the game lobby screen and shows advertisements and events
- Manual pop-up: Pop-up showing registered events corresponding to the resource key -News pop-up: A pop-up that collects and shows announcement posts at once
- Coupon pop-up: Pop-up showing the coupon registration page
- Community popup: Popup showing the game community page
In order to use the PC SDK popup API, the metadata registration of the popup integrated with Partners must be preceded.
# 1) Callback setting
To communicate with the PC SDK using the pop-up API, the game must override the callback function defined in the UStoveSDKObject
class below.
{
//StovePCSDK Callback
public:
void OnError(FStoveError Error) final;
void OnInitComplete() final;
void OnToken(FStoveToken Token) final;
void OnUser(FStoveUser User) final;
void OnOwnership(int Size, FStoveOwnership* Ownerships) final;
}
2
3
4
5
6
7
8
9
You are not required to implement the OnAutoPopup
, OnManualPopup
, OnNewsPopup
, OnCouponPopup
, OnCommunityPopup
callbacks.
You only need to implement and connect the necessary callback functions according to the pop-up used in the game.
/*As for when only using the Ownership function,
apart from the essential callbacks OnError, OnInitcomplte,
connect only the OnOwnership callback additionally.*/
void UMyStoveSDKObject::OnInitComplete()
{
// Process details after successful initialization
}
void UMyStoveSDKObject::OnError(FStoveError fError)
{
// Process details of the error
}
void UMyStoveSDKObject::OnOwnership(int size, FStoveOwnership* fOwnership)
{
// Process details after ownership has been viewed
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2) Game Profile Settings
Set game world and character information with UMyStoveSDKObject::StoveSDKSetGameProfile
function.
Set information is used in pop-ups, so it must be set before using pop-ups.
The validity of the game profile is not checked separately. Therefore, you must enter the correct value by proceeding with validation (null) when entering.
The entered game profile is only valid for the life cycle of PCSDK.
That is, whenever PCSDK is initialized, the game world and character information must be set by calling the UMyStoveSDKObject::StoveSDKSetGameProfile
function.
// input parameters
// const FString& WorldId: The game's world identifier
// const FString& CharacterNo: character identifier
FStoveResult UMyStoveSDKObject::StoveSDKSetGameProfile(const FString & WorldId, const FString & CharactorNo)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKSetGameProfile(WorldId, CharactorNo);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3) Get automatic pop-up information
Search information about auto popup with UMyStoveSDKObject::StoveSDKGetAutoPopup
function.
FStoveResult UMyStoveSDKObject::StoveSDKGetAutoPopup()
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKGetAutoPopup();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
When the UMyStoveSDKObject::StoveSDKGetAutoPopup
function is successfully processed, the UMyStoveSDKObject::OnAutoPopup
callback is called.
The FStoveAutoPopup
structure passed to the callback contains the URL to the autopopup.
The FStovePopupRequestHeader
structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.
void UMyStoveSDKObject::OnAutoPopup(int Size, FStoveAutoPopup * AutoPopups, int HeaderSize, FStovePopupRequestHeader * Headers)
{
OnLog("[AutoPopup]");
OnLog("AutoPopup size = %d ", Size);
for (int i = 0; i < Size; i++, AutoPopups++)
{
OnLog("- AutoPopup[%d].Origin : %s", i, *(AutoPopups->Origin));
OnLog("- AutoPopup[%d].Id : %d", i, AutoPopups->Id);
OnLog("- AutoPopup[%d].Url : %s", i, *(AutoPopups->Url));
OnLog("- AutoPopup[%d].Control.UI.DisallowedDay :%d", i, AutoPopups->Control.UI.DisallowedDay);
OnLog("- AutoPopup[%d].Control.UI.Visible.BackButton :%s", i, AutoPopups->Control.UI.Visible.BackButton ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopup[%d].Control.UI.Visible.CloseButton :%s", i, AutoPopups->Control.UI.Visible.CloseButton ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopup[%d].Control.UI.Visible.DisallowedButton :%s", i, AutoPopups->Control.UI.Visible.DisallowedButton ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopup[%d].Control.UI.Visible.ForwardButton :%s", i, AutoPopups->Control.UI.Visible.ForwardButton ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopup[%d].Control.UI.Visible.HomeButton :%s", i, AutoPopups->Control.UI.Visible.HomeButton ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopup[%d].Control.UI.Visible.NavigationBar :%s", i, AutoPopups->Control.UI.Visible.NavigationBar ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopup[%d].Control.UI.Visible.RefreshButton :%s", i, AutoPopups->Control.UI.Visible.RefreshButton ? TEXT("true") : TEXT("false"));
OnLog("- AutoPopups[%d].Control.UI.CloseButtonImage.Normal.FileId :%s", i, *(AutoPopups->Control.UI.CloseButtonImage.Normal.FileId));
OnLog("- AutoPopups[%d].Control.UI.CloseButtonImage.Normal.FileUrl :%s", i, *(AutoPopups->Control.UI.CloseButtonImage.Normal.FileUrl));
OnLog("- AutoPopups[%d].Control.UI.CloseButtonImage.Pressed.FileId :%s", i, *(AutoPopups->Control.UI.CloseButtonImage.Pressed.FileId));
OnLog("- AutoPopups[%d].Control.UI.CloseButtonImage.Pressed.FileUrl :%s", i, *(AutoPopups->Control.UI.CloseButtonImage.Pressed.FileUrl));
OnLog("- AutoPopup[%d].Control.UI.CloseButtonImage.Type :%d", i, AutoPopups->Control.UI.CloseButtonImage.Type);
}
OnLog(" - RequestHeader size = %d ", HeaderSize);
for (int i = 0; i < HeaderSize; i++, Headers++)
{
OnLog(" - Header[%d].Name : %s", i, *(Headers->Name));
OnLog(" - Header[%d].Value : %s", i, *(Headers->Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Precautions
Even if the success callback (OnAutoPopup) is executed, there are cases where the size callback parameter is 0. At this time, an empty array is passed to the AutoPopups
callback parameter.
Before using the AutoPopups
callback parameter, you must first check the Size callback parameter and decide whether or not to open a popup. In this case, check Partners' automatic pop-up settings.
The exposure order of auto popups must be the same as the order of AutoPopups
array elements. For example, if the AutoPopups array contains three elements [A,B,C], then the popups should be exposed in the order A, B, C.
If an error occurs while running the UMyStoveSDKObject::StoveSDKGetAutoPopup
function, the UMyStoveSDKObject::OnError
callback is called.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
403000 | Invalid Access Error |
400000 | Wrong API usage Error |
400001 | Not Found Error |
400002 | Not Match Error |
400003 | Already exist |
500001 | Internal Interaction Error |
900000 | Unknown Service Error |
# 4) Obtain manual pop-up information
Use the UMyStoveSDKObject::StoveSDKGetManualPopup
function to retrieve information about manual popup.
// input parameters
// const FString& ResourceKey: Manual pop-up identifier registered by Partners
FStoveResult UMyStoveSDKObject::StoveSDKGetManualPopup(const FString& ResourceKey)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKGetManualPopup(ResourceKey);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
When the UMyStoveSDKObject::StoveSDKGetManualPopup
function is successfully processed, the UMyStoveSDKObject::OnManualPopup
callback is called.
The FStoveManualPopup
structure passed to the callback contains the URL for the manual popup.
The FStovePopupRequestHeader
structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.
void UMyStoveSDKObject::OnManualPopup(int Size, FStoveManualPopup* ManualPopups, int HeaderSize, FStovePopupRequestHeader* Headers)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[ManualPopup]");
OnLog("ManualPopup Size = %d ", Size);
for (int i = 0; i < Size; i++, ManualPopups++)
{
OnLog("- ManualPopup[%d].Origin : %s", i, *(ManualPopups->Origin));
OnLog("- ManualPopup[%d].ResourceKey : %s", i, *(ManualPopups->ResourceKey));
OnLog("- ManualPopup[%d].Id : %d", i, ManualPopups->Id);
OnLog("- ManualPopup[%d].Url : %s", i, *(ManualPopups->Url));
OnLog("- ManualPopup[%d].Control.UI.DisallowedDay :%d", i, ManualPopups->Control.UI.DisallowedDay);
OnLog("- ManualPopup[%d].Control.UI.Visible.BackButton :%s", i, ManualPopups->Control.UI.Visible.BackButton ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.Visible.CloseButton :%s", i, ManualPopups->Control.UI.Visible.CloseButton ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.Visible.DisallowedButton :%s", i, ManualPopups->Control.UI.Visible.DisallowedButton ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.Visible.ForwardButton :%s", i, ManualPopups->Control.UI.Visible.ForwardButton ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.Visible.HomeButton :%s", i, ManualPopups->Control.UI.Visible.HomeButton ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.Visible.NavigationBar :%s", i, ManualPopups->Control.UI.Visible.NavigationBar ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.Visible.RefreshButton :%s", i, ManualPopups->Control.UI.Visible.RefreshButton ? TEXT("true") : TEXT("false"));
OnLog("- ManualPopup[%d].Control.UI.CloseButtonImage.Normal.FileId :%s", i, *(ManualPopups->Control.UI.CloseButtonImage.Normal.FileId));
OnLog("- ManualPopup[%d].Control.UI.CloseButtonImage.Normal.FileUrl :%s", i, *(ManualPopups->Control.UI.CloseButtonImage.Normal.FileUrl));
OnLog("- ManualPopup[%d].Control.UI.CloseButtonImage.Pressed.FileId :%s", i, *(ManualPopups->Control.UI.CloseButtonImage.Pressed.FileId));
OnLog("- ManualPopup[%d].Control.UI.CloseButtonImage.Pressed.FileUrl :%s", i, *(ManualPopups->Control.UI.CloseButtonImage.Pressed.FileUrl));
OnLog("- ManualPopup[%d].Control.UI.CloseButtonImage.Type :%d", i, ManualPopups->Control.UI.CloseButtonImage.Type);
}
OnLog("- RequestHeader Size = %d ", HeaderSize);
for (int i = 0; i < HeaderSize; i++, Headers++)
{
OnLog("- Header[%d].Name : %s", i, *(Headers->Name));
OnLog("- Header[%d].Value : %s", i, *(Headers->Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Precautions
Even if the success callback (OnManualPopup) is executed, there are cases where the size callback parameter is 0.
At this time, an empty array is passed to the ManualPopups
callback parameter. Before using the ManualPopups
callback parameter, you must first check the Size callback parameter and decide whether or not to open a popup.
In this case, check the manual pop-up settings of Partners.
The display order of manual popups must be the same as the order of ManualPopups
array elements. For example, if the ManualPopups
array contains three elements [A,B,C], then the popups should be exposed in A, B, C order.
If an error occurs while executing the UMyStoveSDKObjcet::StoveSDKGetManualPopup
function, the UMyStoveSDKObjcet::OnError
callback is called.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
403000 | Invalid Access Error |
400000 | Wrong API usage Error |
400001 | Not Found Error |
400002 | Not Match Error |
400003 | Already exist |
500001 | Internal Interaction Error |
900000 | Unknown Service Error |
# 5) Get news pop-up information
Use the UMyStoveSDKObject::StoveSDKGetNewsPopup
function to retrieve information about the news popup.
FStoveResult UMyStoveSDKObject::StoveSDKGetNewsPopup()
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKGetNewsPopup();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
}
2
3
4
5
6
7
8
9
10
11
When the UMyStoveSDKObject::StoveSDKGetNewsPopup
function is successfully processed, the UMyStoveSDKObject::OnNewsPopup
callback is called.
The FStoveNewsPopup
structure passed to the callback contains the URL to the newspopup.
The FStovePopupRequestHeader
structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.
void UMyStoveSDKObject::OnNewsPopup(FStoveNewsPopup NewsPopup, int HeaderSize, FStovePopupRequestHeader* Headers)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[NewsPopup]");
OnLog("- NewsPopup.Origin : %s", *(NewsPopup.Origin));
OnLog("- NewsPopup.Id : %d", NewsPopup.Id);
OnLog("- NewsPopup.Url : %s", *(NewsPopup.Url));
OnLog("- NewsPopup.Control.UI.DisallowedDay :%d", NewsPopup.Control.UI.DisallowedDay);
OnLog("- NewsPopup.Control.UI.Visible.BackButton :%s", NewsPopup.Control.UI.Visible.BackButton ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.Visible.CloseButton :%s", NewsPopup.Control.UI.Visible.CloseButton ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.Visible.DisallowedButton :%s", NewsPopup.Control.UI.Visible.DisallowedButton ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.Visible.ForwardButton :%s", NewsPopup.Control.UI.Visible.ForwardButton ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.Visible.HomeButton :%s", NewsPopup.Control.UI.Visible.HomeButton ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.Visible.NavigationBar :%s", NewsPopup.Control.UI.Visible.NavigationBar ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.Visible.RefreshButton :%s", NewsPopup.Control.UI.Visible.RefreshButton ? TEXT("true") : TEXT("false"));
OnLog("- NewsPopup.Control.UI.CloseButtonImage.Normal.FileId :%s", *(NewsPopup.Control.UI.CloseButtonImage.Normal.FileId));
OnLog("- NewsPopup.Control.UI.CloseButtonImage.Normal.FileUrl :%s", *(NewsPopup.Control.UI.CloseButtonImage.Normal.FileUrl));
OnLog("- NewsPopup.Control.UI.CloseButtonImage.Pressed.FileId :%s", *(NewsPopup.Control.UI.CloseButtonImage.Pressed.FileId));
OnLog("- NewsPopup.Control.UI.CloseButtonImage.Pressed.FileUrl :%s", *(NewsPopup.Control.UI.CloseButtonImage.Pressed.FileUrl));
OnLog("- NewsPopup.Control.UI.CloseButtonImage.Type :%d", NewsPopup.Control.UI.CloseButtonImage.Type);
OnLog("- RequestHeader size = %d", HeaderSize);
for (int i = 0; i < HeaderSize; i++, Headers++)
{
OnLog(" - Header[%d].Name : %s", i, *(Headers->Name));
OnLog(" - Header[%d].Value : %s", i, *(Headers->Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Precautions
Even if the success callback (OnNewsPopup) is executed, NewsPopup
callback parameter properties may be default values (empty string or 0).
You need to check the url property of the NewsPopup
callback parameter before deciding whether to open a popup.
In this case, check the news pop-up settings of Partners.
If an error occurs while running the UMyStoveSDKObject::StoveSDKGetNewsPopup
function, the UMyStoveSDKObject::OnError
callback is called.
You can check external errors through the ExternalError
field of the FStoveError
structure.
ExternalError | Description |
---|---|
403000 | Invalid Access Error |
400000 | Wrong API usage Error |
400001 | Not Found Error |
400002 | Not Match Error |
400003 | Already exist |
500001 | Internal Interaction Error |
900000 | Unknown Service Error |
# 6) Get coupon pop-up information
Search coupon popup information with UMyStoveSDKObject::StoveSDKGetCouponPopup
function.
void UMyStoveSDKObject::OnCouponPopup(FStoveCouponPopup CouponPopup, int HeaderSize, FStovePopupRequestHeader* Headers)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[CouponPopup]");
OnLog("- CouponPopup.Url : %s", *(CouponPopup.Url));
OnLog("- CouponPopup.Control.UI.DisallowedDay :%d", CouponPopup.Control.UI.DisallowedDay);
OnLog("- CouponPopup.Control.UI.Visible.BackButton :%s", CouponPopup.Control.UI.Visible.BackButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.CloseButton :%s", CouponPopup.Control.UI.Visible.CloseButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.DisallowedButton :%s", CouponPopup.Control.UI.Visible.DisallowedButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.ForwardButton :%s", CouponPopup.Control.UI.Visible.ForwardButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.HomeButton :%s", CouponPopup.Control.UI.Visible.HomeButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.NavigationBar :%s", CouponPopup.Control.UI.Visible.NavigationBar ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.RefreshButton :%s", CouponPopup.Control.UI.Visible.RefreshButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Normal.FileId :%s", *(CouponPopup.Control.UI.CloseButtonImage.Normal.FileId));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Normal.FileUrl :%s", *(CouponPopup.Control.UI.CloseButtonImage.Normal.FileUrl));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Pressed.FileId :%s", *(CouponPopup.Control.UI.CloseButtonImage.Pressed.FileId));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Pressed.FileUrl :%s", *(CouponPopup.Control.UI.CloseButtonImage.Pressed.FileUrl));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Type :%d", CouponPopup.Control.UI.CloseButtonImage.Type);
OnLog(" - RequestHeader size = %d", HeaderSize);
for (int i = 0; i < HeaderSize; i++, Headers++)
{
OnLog(" - Header[%d].Name : %s", i, *(Headers->Name));
OnLog(" - Header[%d].Value : %s", i, *(Headers→Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
When the UMyStoveSDKObject::StoveSDKGetCouponPopup
function is successfully processed, the UMyStoveSDKObject::OnCouponPopup
callback is called.
The FStoveCouponPopup
structure passed to the callback contains the URL to the coupon popup.
The FStovePopupRequestHeader
structure passed to the callback contains name/value pairs of headers to be set when requesting URLs.
void UMyStoveSDKObject::OnCouponPopup(FStoveCouponPopup CouponPopup, int HeaderSize, FStovePopupRequestHeader* Headers)
{
/*Add the 'walkthrough' codes here.*/ OnLog("[CouponPopup]");
OnLog("- CouponPopup.Url : %s", *(CouponPopup.Url));
OnLog("- CouponPopup.Control.UI.DisallowedDay :%d", CouponPopup.Control.UI.DisallowedDay);
OnLog("- CouponPopup.Control.UI.Visible.BackButton :%s", CouponPopup.Control.UI.Visible.BackButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.CloseButton :%s", CouponPopup.Control.UI.Visible.CloseButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.DisallowedButton :%s", CouponPopup.Control.UI.Visible.DisallowedButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.ForwardButton :%s", CouponPopup.Control.UI.Visible.ForwardButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.HomeButton :%s", CouponPopup.Control.UI.Visible.HomeButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.NavigationBar :%s", CouponPopup.Control.UI.Visible.NavigationBar ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.Visible.RefreshButton :%s", CouponPopup.Control.UI.Visible.RefreshButton ? TEXT("true") : TEXT("false"));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Normal.FileId :%s", *(CouponPopup.Control.UI.CloseButtonImage.Normal.FileId));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Normal.FileUrl :%s", *(CouponPopup.Control.UI.CloseButtonImage.Normal.FileUrl));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Pressed.FileId :%s", *(CouponPopup.Control.UI.CloseButtonImage.Pressed.FileId));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Pressed.FileUrl :%s", *(CouponPopup.Control.UI.CloseButtonImage.Pressed.FileUrl));
OnLog("- CouponPopup.Control.UI.CloseButtonImage.Type :%d", CouponPopup.Control.UI.CloseButtonImage.Type);
OnLog(" - RequestHeader size = %d", HeaderSize);
for (int i = 0; i < HeaderSize; i++, Headers++)
{
OnLog(" - Header[%d].name : %s", i, *(Headers->Name));
OnLog(" - Header[%d].value : %s", i, *(Headers->Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
If an error occurs while running the UStoveSDKObject::StoveSDKGetCouponPopup
function, the UStoveSDKObject::OnError
callback is called.
# 7) Get community pop-up information
Use the UMyStoveSDKObject::StoveSDKGetCommunityPopup
function to query community popup information.
FStoveResult UMyStoveSDKObject::StoveSDKGetCommunityPopup()
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKGetCommunityPopup();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
When the UMyStoveSDKObject::StoveSDKGetCommunityPopup
function is successfully processed, the UStoveSDKObject::OnCommunityPopup
callback is called.
The FStoveCommunityPopup
structure passed to the callback contains the URL to the community popup.
The FStovePopupRequestCookie
structure passed to the callback contains the cookie name/value pair to be set when requesting the URL.
void UMyStoveSDKObject::OnCommunityPopup(FStoveCommunityPopup CommunityPopup, int CookieSize, FStovePopupRequestCookie* Cookies)
{
OnLog("[CommunityPopup]");
OnLog("- CommunityPopup.Url : %s", *(CommunityPopup.Url));
OnLog("- CommunityPopup.Control.UI.DisallowedDay :%d", CommunityPopup.Control.UI.DisallowedDay);
OnLog("- CommunityPopup.Control.UI.Visible.BackButton :%s", CommunityPopup.Control.UI.Visible.BackButton ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.Visible.CloseButton :%s", CommunityPopup.Control.UI.Visible.CloseButton ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.Visible.DisallowedButton :%s", CommunityPopup.Control.UI.Visible.DisallowedButton ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.Visible.ForwardButton :%s", CommunityPopup.Control.UI.Visible.ForwardButton ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.Visible.HomeButton :%s", CommunityPopup.Control.UI.Visible.HomeButton ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.Visible.NavigationBar :%s", CommunityPopup.Control.UI.Visible.NavigationBar ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.Visible.RefreshButton :%s", CommunityPopup.Control.UI.Visible.RefreshButton ? TEXT("true") : TEXT("false"));
OnLog("- CommunityPopup.Control.UI.CloseButtonImage.Normal.FileId :%s", *(CommunityPopup.Control.UI.CloseButtonImage.Normal.FileId));
OnLog("- CommunityPopup.Control.UI.CloseButtonImage.Normal.FileUrl :%s", *(CommunityPopup.Control.UI.CloseButtonImage.Normal.FileUrl));
OnLog("- CommunityPopup.Control.UI.CloseButtonImage.Pressed.FileId :%s", *(CommunityPopup.Control.UI.CloseButtonImage.Pressed.FileId));
OnLog("- CommunityPopup.Control.UI.CloseButtonImage.Pressed.FileUrl :%s", *(CommunityPopup.Control.UI.CloseButtonImage.Pressed.FileUrl));
OnLog("- CommunityPopup.Control.UI.CloseButtonImage.Type :%d", CommunityPopup.Control.UI.CloseButtonImage.Type);
OnLog("- RequestCookie size = %d", CookieSize);
for (int i = 0; i < CookieSize; i++, Cookies++)
{
OnLog(" - Cookie[%d].Name : %s", i, *(Cookies->Name));
OnLog(" - Cookie[%d].Value : %s", i, *(Cookies->Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
If an error occurs while running the UMyStoveSDKObject::StoveSDKGetCommunityPopup
function, the UStoveSDKObject::OnError
callback is called.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
13008 | Mandatory Parameter missing |
90001 | AccessToken invalid |
40101 | Invalid token |
# 8) Disable pop-ups 2.6.0
With the UMyStoveSDKObject::StoveSDKSetPopupDisallowed
function, set a specific pop-up not to be displayed for a certain period of time.
If the game directly implements the PC SDK pop-up UI, configure the UI by referring to the Control.UI.Visible.DisallowedButton
value of the pop-up UI information
Call the UMyStoveSDKObject::StoveSDKSetPopupDisallowed
function in the button click handler.
When calling the UMyStoveSDKObject::StoveSDKSetPopupDisallowed
function, the days parameter uses the Control.UI.DisallowedDay value of the popup information.
If pop-up disallow is set, the relevant pop-up information will not be searched during the disallow period.
// input parameters
// const int PopupId : Popup identifier issued by Partners
//const int Days : the number of days that Partners has registered as unavailable (once) or -1 (don't look again)
// const int Days : Unacceptable period registered by Partners (in days)
FStoveResult UMyStoveSDKObject::StoveSDKSetPopupDisallowed(const int PopupId, const int Days)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKSetPopupDisallowed(PopupId, Days);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Integrate billing 2.6.0
The PC SDK provides APIs to integrate Stove Platform's billing service into games. There is a shop as a billing service.
A typical scenario for a store is below. This may vary slightly depending on the game situation (e.g. whether or not there is a game server).
- Information for store configuration is acquired through store category search and product search APIs.
- The game organizes the store through the acquired category and product information and displays the UI.
- Purchases for each product call the purchase start API to obtain a one-time payment URL.
- In the case of a product with a selling price of 0
- The purchase is completed when the purchase start API response is received.
- For products with a selling price greater than 0
- Obtain the one-time payment URL from the response of the purchase start API.
- The game browses the one-time payment URL with an external browser. Supported browsers: Chrome (75+), Edge (42+)
- Subsequent payment process will be completed through the web page.
- In the case of a product with a selling price of 0
- When the payment is complete, the game calls the Purchase Status Check API to check the purchase status.
- If the payment is confirmed to have been completed normally, the game will provide the product.
- You can check the product purchase history (whether purchased more than once) through the purchase verification API.
- It can be used to restore items through the library inquiry API.
In order to use the PC SDK billing service API, you must register the metadata of the billing service through Partners in advance.
Also, if you use the store through the PC SDK, you must call the UMyStoveSDKObject::StoveSDKIAPInit
function and pass the ShopKey issued from the partners.
An error will be returned if the billing service API is called without ShopKey settings.
The game must check whether you agree to the terms of service every time you open the store.
If the game user does not agree to the service terms and conditions, open the browser using the terms and conditions agreement page URL provided by PCSDK so that the game user can agree to the service terms and conditions.
When a game user agrees to the terms of service and opens the store, he or she enters the store.
PC SDK operates internal cache for store support.
Using the isRefresh parameter of the UMyStoveSDKObject::StoveSDKFetchProducts
function, you can determine whether to retrieve product information from the cache or via Web API.
The product information retrieved through the Web API is updated in whole or in part (by category) in the cache, and then the product information is passed to the game as a callback.
(However, if the cache is empty, the product information is retrieved through the Web API and updated to the cache regardless of the value of the isRefresh parameter.)
In addition, the PC SDK updates the purchase/sale quantity and purchase status of each product in the cache through the Web API response at the time of calling the UMyStoveObject::StoveSDKConfirmPurchase
function.
# (Example) Flow chart of billing integration
- Initialize PC_SDK when starting the game
- Initialize IAP through
UMyStoveSDKObject::StoveSDKIAPInit
function. - When IAP is initialized, the entire item list is retrieved and stored in the built-in cache.
- Initialize IAP through
- Handling non-payment inquiries when entering the in-game shop page (optional)
- If there are unpaid items after completing payment through
UMyStoveSDKObject::StoveSDKFetchInventory
storage check, re-supply is processed.
- If there are unpaid items after completing payment through
- After entering the store, search the category list for store composition.
- Search categories in the store through
UMyStoveSDKObject::StoveSDKFetchShopCategories
function.
- Search categories in the store through
- Search the item information through the category information in the store inquired in number 3.
- Search product information included in the category through
UMyStoveSDKObject::StoveSDKFetchProducts
function.
- Search product information included in the category through
- Select an item to purchase from the store.
- Purchase product information must be composed directly in an array. (ProductId/SalePrice/Quantity)
- Quantity must be specified as 1.
- Search for one-time payment URL information to start product purchase.
- Search the one-time payment window URL information through
UMyStoveSDKObject::StoveSDKStartPurchase
function.
- Search the one-time payment window URL information through
- Process the product payment information pop-up within the game. (It must be processed to check the payment result in an external browser.)
- Pop up an external browser with the one-time payment URL information obtained through step 6.
- Proceed with product payment through the payment window of Stove billing.
- Close the browser after payment is completed in the payment window.
- When you click the "Payment Complete" button on the product payment information pop-up created in step 7 in-game, the purchase status information is searched.
- Search information on the payment status through
UMyStoveSDKObject::StoveSDKConfirmPurchase
function. - After checking the payment completion status, close the pop-up and return to the store page.
- The purchase flow is complete.
reference
Stove payment is not in progress through an external browser and the payment result is not known through UMyStoveSDKObject::StoveSDKStartPurchase
When entering the store page (2 times), the item is re-issued through UMyStoveSDKObject::StoveSDKFetchInventory
inventory inquiry.
The sequence diagram below shows a hypothetical store operation scenario.
This is an example of a general case and may differ slightly depending on the game situation (e.g. store category structure, store UI creation time, etc.).
- PCSDK IAP initialization
- Check to accept the Terms of Service
- Open shop
- Purchase goods
- Check product purchase status
- Verification of product purchase history
- Handle item restoration
# 1) Callback setting
In order to communicate with the PC SDK using the billing service API, the game must override the callback function defined in the UMyStoveSDKObject
class below.
//StoveCallback
UCLASS()
class HELLOSTOVE_API UMyStoveSDKObject : public UStoveSDKObject
{
GENERATED_BODY()
public:
void OnInitComplete() final;
void OnError(FStoveError Error) final;
void OnToken(FStoveToken Token) final;
void OnUser(FStoveUser User) final;
void OnOwnership(int Size, FStoveOwnership* Ownerships) final;
// Callback called when FetchShopCategories processing is complete
void OnFetchShopCategories(int Size, FStoveShopCategories* Categories) final;
// Callback called when FetchProducts processing is complete
void OnFetchProducts(int Size, FStoveProduct* Products) final;
// Callback called when StartPurchase processing is complete
void OnStartPurchase(FStovePurchase Purchase) final;
// Callback called when ConfirmPurchase processing is complete
void OnConfirmPurchase(int Size, FStovePurchaseProduct* PurchaseProducts, bool Status, FString ShopKey) final;
// Callback called when FetchInventory processing is complete
void OnFetchInventory(int Size, FStoveInventoryItem* InventoryItems) final;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
As in ‘Interlocking 2) Config, Callback setting’, override the callback function to receive the event.
// billing service
void UMyStoveSDKObject::OnFetchTermsAgreement(const FStoveTermsAgreement TermsAgreement)
{
// Terms of Service
}
void UMyStoveSDKObject::OnFetchShopCategories(int Size, FStoveShopCategories* Categories)
{
// After calling the store category API
}
void UMyStoveSDKObject::OnFetchProducts(int Size, FStoveProduct* Products)
{
// After calling the product API registered in the store
}
void UMyStoveSDKObject::OnStartPurchase(FStovePurchase Purchase)
{
// After trying to pay for the product
}
void UMyStoveSDKObject::OnConfirmPurchase(int Size, FStovePurchaseProduct* PurchaseProducts, bool Status, FString ShopKey)
{
// after product purchase confirmation
}
void UMyStoveSDKObject::OnFetchInventory(int Size, FStoveInventoryItem* InventoryItems)
{
// After calling the archive search API
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
You are not required to implement the OnFetchTermsAgreement
, OnFetchShopCategories
, OnFetchProducts
, OnStartPurchase
, OnConfirmPurchase
, OnFetchInventory
callbacks.
You only need to connect the store when the game needs it. However, for the store function, all 5 callbacks must be implemented and connected.
# 2) Initialize IAP
If the game decides to use PCSDK to provide billing service, try initializing billing with the UMyStoveSDKObject::StoveSDKIAPInit
function with the ShopKey
factor value of the store key issued by the stove.
When billing initialization is attempted, the product list registered on the Stove platform is automatically retrieved and stored in the Stove PCSDK internal cache.
Call the UMyStoveSDKObject::StoveSDKIAPInit
function, and if it fails, send the error details to the FStoveResult
and OnError
callbacks.
// input parameters
// FString ShopKey: ShopKey issued by the stove
FStoveResult UMyStoveSDKObject::StoveSDKIAPInit(const FString& ShopKey)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKIAPInit(ShopKey);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ExternalError | Description |
---|---|
500 | Internal Server Error |
50001 | Store does not exist, or is under maintenance |
50002 | Product does not exist or is unavailable for sale |
999999 | undefined error |
# 3) Game profile settings
Set game world and character information with UMyStoveSDKObject::StoveSDKSetGameProfile
function.
This is to determine the level of the product purchasing entity. The PC SDK prioritizes the purchaser of the product as follows.
- Character No. > Guid > Member No.
When character information is set through UMyStoveSDKObject::StoveSDKSetGameProfile
function, PC SDK proceeds with purchase based on Character No. when purchasing a product.
On the other hand, if character information is not set through UMyStoveSDKObject::StoveSDKSetGameProfile
function, PC SDK proceeds with purchase based on Guid or Member No.
Therefore, in order to ensure that the purchasing subject is properly applied when purchasing a product, you should consider whether to call the UMyStoveSDKObject::StoveSDKSetGameProfile
API before calling the PC SDK billing service API.
Normally, UMyStoveSDKObject::StoveSDKSetGameProfile
function only needs to be called once per world/character change.
# 4) Get store category information
Use the UMyStoveSDKObject::StoveSDKFetchShopCategories
function to retrieve store category information for the game.
Category information includes the ID of the parent category, so you can organize your store in a hierarchical structure.
FStoveResult UMyStoveSDKObject::StoveSDKFetchShopCategories()
{
FStoveResult ErrorResult = Super::StoveSDKFetchShopCategories();
if(ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// Success processing
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
If the UMyStoveSDKObject::StoveSDKFetchShopCategories
function is processed successfully, the OnFetchShopCategories
callback is called.
The FStoveShopCategory
structure passed to the callback contains meta information about the store category.
- FStoveShopCategory.CategoryId: Category ID
- FStoveShopCategory.ParentCategoryId: Parent category ID
- FStoveShopCategory.DisplayNo: Category order
- FStoveShopCategory.Name: Category name
- FStoveShopCategory.Depth: Category depth (1 for top level category)
void UMyStoveSDKObject::OnFetchShopCategories(int Size, FStoveShopCategories* Categories)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[OnFetchShopCategories]");
OnLog("ShopCategories size = %d ", Size);
for (int i = 0; i < Size; i++, Categories++)
{
OnLog(" -> Index: %d", i);
OnLog("-------------------------------------------------------------- --------");
OnLog(" CategoryId : %s", *(Categories->CategoryId));
OnLog(" ParentCategoryId : %s", *(Categories->ParentCategoryId));
OnLog(" DisplayNo : %d", Categories->DisplayNo);
OnLog(" Name : %s", *(Categories->Name));
OnLog(" Depth : %d", Categories->Depth);
OnLog("-------------------------------------------------------------- --------");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
If an error occurs during execution of the UMyStoveSDKObejct::StoveSDKFetchShopProducts
function, the OnError
callback is called.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
500 | Internal Server Error |
999999 | undefined error |
# 5) Get store category information
Use the UMyStoveSDKObject::StoveSDKFetchShopCategories
function to retrieve store category information for the game.
Category information includes the ID of the parent category, so you can organize your store in a hierarchical structure.
FStoveResult UMyStoveSDKObject::StoveSDKFetchShopCategories()
{
FStoveResult ErrorResult = Super::StoveSDKFetchShopCategories(StatId, StatValue);
if(ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// handle success
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
When the UMyStoveSDKObject::StoveSDKFetchShopCategories
function is successfully processed, the OnFetchShopCategories
callback is called.
The FStoveShopCategory
structure passed to the callback contains meta information about the store category.
- FStoveShopCategory.CategoryId : Category ID
- FStoveShopCategory.ParentCategoryId: Parent category ID
- FStoveShopCategory.DisplayNo: Category order
- FStoveShopCategory.Name: category name
- FStoveShopCategory.Depth: category depth (1 for top level category)
void UMyStoveSDKObject::OnFetchShopCategories(int Size, FStoveShopCategories* Categories)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[OnFetchShopCategories]");
OnLog("ShopCategories size = %d ", Size);
for (int i = 0; i < Size; i++, Categories++)
{
OnLog(" -> Index: %d", i);
OnLog("---------------------------------------------- --------");
OnLog(" CategoryId : %s", *(Categories->CategoryId));
OnLog(" ParentCategoryId : %s", *(Categories->ParentCategoryId));
OnLog(" DisplayNo : %d", Categories->DisplayNo);
OnLog(" Name : %s", *(Categories->Name));
OnLog(" Depth : %d", Categories->Depth);
OnLog("---------------------------------------------- --------");
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
The OnError
callback is called if an error occurs while running the UMyStoveSDKObejct::StoveSDKFetchShopProducts
function.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
500 | Internal Server Error |
999999 | undefined error |
# 6) Get product information
Search product information for the game with UMyStoveSDKObject::StoveSDKFetchProducts
function.
// input parameters
// FString CategoryId: Category identifier registered by Partners (search all categories when passing an empty string)
// bool IsRefresh : If true, search Web API, if false, search PC SDK Cache
FStoveResult UMyStoveSDKObject::StoveSDKFetchProducts(const FString& CategoryId, const bool IsRefresh)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKFetchProducts(CategoryId, IsRefresh);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
When the UMyStoveSDKObject::StoveSDKFetchProducts
function is successfully processed, the OnFetchProducts
callback is called.
The FStoveProduct
structure passed to the callback contains meta information about the product.
- FStoveProduct.ProductId: Product ID
- FStoveProduct.GameItemId: In-game item ID mapped to product ID
- FStoveProduct.Name : product name
- FStoveProduct.Description : product description
- FStoveProduct.Quantity: Quantity of each product
- FStoveProduct.ProductTypeCode : Product type code (1: game product, 2: in-game product, 3: package item)
- FStoveProduct.CategoryId : Category ID
- FStoveProduct.CurrencyCode : Currency code
- FStoveProduct.Price: List price of the product (when displaying, if the CurrencyCode is equal to "KRW", the decimal point is omitted; if it is different, the second decimal place is indicated)
- FStoveProduct.SalePrice: Product sales price (when displaying, if the CurrencyCode is equal to "KRW", the decimal point is omitted; if it is different, it is indicated to the second decimal place)
- FStoveProduct.IsDiscount: Whether discount
- FStoveProduct.DiscountType: Discount type (1: flat rate, 2: flat rate)
- FStoveProduct.DiscountTypeValue: discount value
- FStoveProduct.DiscountBeginDate : Discount start date (UTC+0)
- FStoveProduct.DiscountEndDate : Discount end date (UTC+0)
- FStoveProduct.TotalQuantity: total sales quantity of the product
- FStoveProduct.MemberQuantity: Member purchase quantity
- FStoveProduct.GuidQuantity: Guid purchase quantity (purchase quantity of product purchase subject [CharacterNo/Guid/MemberNo])
- FStoveProduct.ThumbnailUrl : Representative product image
void UMyStoveSDKObject::OnFetchProducts(int Size, FStoveProduct* Products)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[OnFetchProducts]");
OnLog("Products Size = %d ", Size);
FString Builder;
for (int i = 0; i < Size; i++, Products++)
{
Builder.Append(FString::Printf(TEXT("-> Index : %d\n"), i));
Builder.Append(FString::Printf(TEXT("-------------------------------------- -----------------\n")));
Builder.Append(FString::Printf(TEXT(" ProductId : %I64d\n"), Products->ProductId));
Builder.Append(FString::Printf(TEXT(" GameItemId : %s\n"), *(Products->GameItemId)));
Builder.Append(FString::Printf(TEXT(" Name : %s\n"), *(Products->Name)));
Builder.Append(FString::Printf(TEXT(" Description : %s\n"), *(Products->Description)));
Builder.Append(FString::Printf(TEXT(" Quantity : %d\n"), Products->Quantity));
Builder.Append(FString::Printf(TEXT(" ProductTypeCode : %hd\n"), Products->ProductTypeCode));
Builder.Append(FString::Printf(TEXT(" CategoryId : %s\n"), *(Products->CategoryId)));
Builder.Append(FString::Printf(TEXT(" CurrencyCode : %s\n"), *(Products->CurrencyCode)));
if (Products->CurrencyCode.Compare(TEXT("KRW"), ESearchCase::IgnoreCase) == 0)
{
Builder.Append(FString::Printf(TEXT(" Price : %.0lf\n"), Products->Price));
Builder.Append(FString::Printf(TEXT(" SalePrice : %.0lf\n"), Products->SalePrice));
}
else
{
Builder.Append(FString::Printf(TEXT(" Price : %.2lf\n"), Products->Price));
Builder.Append(FString::Printf(TEXT(" SalePrice : %.2lf\n"), Products->SalePrice));
}
Builder.Append(FString::Printf(TEXT(" IsDiscount : %s\n"), Products->bIsDiscount ? TEXT("true") : TEXT("false")));
Builder.Append(FString::Printf(TEXT(" DiscountType : %hd\n"), Products->DiscountType));
Builder.Append(FString::Printf(TEXT(" DiscountTypeValue : %d\n"), Products->DiscountTypeValue));
Builder.Append(FString::Printf(TEXT(" DiscountBeginDate : %I64d\n"), Products->DiscountBeginDate));
Builder.Append(FString::Printf(TEXT(" DiscountEndDate : %I64d\n"), Products->DiscountEndDate));
Builder.Append(FString::Printf(TEXT(" TotalQuantity : %d\n"), Products->TotalQuantity));
Builder.Append(FString::Printf(TEXT(" MemberQuantity : %d\n"), Products->MemberQuantity));
Builder.Append(FString::Printf(TEXT(" GuidQuantity : %d\n"), Products->GuidQuantity));
Builder.Append(FString::Printf(TEXT(" ThumbnailUrl : %s\n"), *(Products->ThumbnailUrl)));
Builder.Append(FString::Printf(TEXT(" CanWithdraw : %s\n"), Products->bCanWithdraw ? TEXT("true") : TEXT("false")));
Builder.Append(FString::Printf(TEXT("-------------------------------------- -----------------\n")));
}
OnLog("%s", *Builder);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
The OnError
callback is called if an error occurs while running the UMyStoveSDKObject::StoveSDKFetchProducts
function.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
500 | Internal Server Error |
50001 | Store does not exist, or is under maintenance |
50002 | Product does not exist or is unavailable for sale |
999999 | undefined error |
# 7) Start purchasing products
Start product purchase with UMyStoveSDKObject::StoveSDKStartPurchase
function.
// input parameters
// const TArray<FStoveOrderProduct> Products: Order product information
// ProductSize: number of ordered products
FStoveResult UMyStoveSDKObject::StoveSDKStartPurchase(const TArray<FStoveOrderProduct> Products, const int ProductSize)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKStartPurchase(Products, ProductSize);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
When the UMyStoveSDKObject::StoveSDKStartPurchase
function is successfully processed, the OnStartPurchase
callback is called.
The FStovePurchase
structure passed to the callback contains meta information about product purchase.
- FStovePurchase.TransactionMasterNo: Transaction unique master number
- FStovePurchase.TempPaymentUrl : One-time payment URL
- FStovePurchase.PurchaseProgress : Purchase progress status
- 1: Payment in progress (page displayed in external browser)
- 2: Purchase completed (Payment is completed due to the purchase of a product with a selling price of 0, so it is not necessary to display the page in an external browser using TempPaymentUrl)
When necessary, the game browses the one-time payment URL through an external browser. Supported browsers: Chrome (75+), Edge (42+)
void UMyStoveSDKObject::OnStartPurchase(FStovePurchase Purchase)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[OnStartPurchase]");
OnLog(" TransactionMasterNo : %I64d", Purchase.TransactionMasterNo);
OnLog(" TempPaymentUrl : %s", *(Purchase. TempPaymentUrl));
OnLog(" PurchaseProgress : %d", Purchase. PurchaseProgress);
if (Purchase. PurchaseProgress == 1)
{
FWindowsPlatformProcess::LaunchURL(*(Purchase. TempPaymentUrl), nullptr, nullptr);
}
else if(Purchase. PurchaseProgress == 2)
{
//Process purchase completion (e.g. purchase completion message box)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
The OnError
callback is called if an error occurs while the UMyStoveSDKObject::StoveSDKStartPurchase'
function is running.
External errors can be checked through the ExternalError field of the FStoveError
structure.
Normally, when the OnError
callback is called for the UMyStoveSDKObject::StoveSDKStartPurchase
function call, the game exposes a message about the failure to the game user.
The table below provides a guide on what messages to display to game users.
| ExternalError | Description | Check the exposure message for game users | |:-------------|:-----------------------------|:- ------------------------------------| | 500 | Internal Server Error | This is a temporary phenomenon or the service is not smooth due to network reasons. | | 50001 | Store does not exist, or is under maintenance | The service is under maintenance, or the service does not exist. | | 50002 | Product does not exist or is unavailable for sale | This product cannot be purchased due to its condition. | | 50003 | non-exhibition products | This product is not currently on sale. | | 50004 | Products outside the sale period | This is not a product sale period. | | 50005 | Product price inconsistency (if product price is changed) | Product price information has been changed. | | 50009 | Exceeds the number of sales per member that can be purchased | The number of purchases per person has been exceeded. | | 50010 | Exceeds the total number of sales available for purchase | All prepared quantities have been sold. | | 50031 | Purchase quantity is '0' | Please enter at least one quantity to purchase. | | 999999 | undefined error | The service is not smooth due to other errors.
# 8) Check product purchase status
Check the product purchase status with UMyStoveSDKObject::StoveSDKConfirmPurchase
function.
// input parameters
// FString TransactionMasterNo : Unique transaction master number (obtained through OnStartPurchase callback parameter FStovePCPurchase.transactionMasterNo)
FStoveResult UMyStoveSDKObject::StoveSDKConfirmPurchase(const FString& TransactionMasterNo)
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKConfirmPurchase(TransactionMasterNo);
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// handle success
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
When the UMyStoveSDKObject::StoveSDKConfirmPurchase
function is successfully processed, the OnConfirmPurchase
callback is called.
The FStovePurchaseProduct
structure passed to the callback contains meta information about the purchased product, and the status callback parameter delivers the product purchase status.
- FStovePurchaseProduct.TotalQuantity: Total product sales quantity
- FStovePurchaseProduct.MemberQuantity : Member purchase quantity
- FStovePurchaseProduct.GuidQuantity: Guid purchase quantity (purchase quantity of product purchase subject [CharacterNo/Guid/MemberNo])
In the case of a game without a separate game server, if the purchase result is successful, the game may provide an item.
In the case of a game with a game server, the game server can receive a notification about the purchase and can provide the item at this time.
void UMyStoveSDKObject::OnConfirmPurchase(int Size, FStovePurchaseProduct* PurchaseProducts, bool Status, FString ShopKey)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[OnConfirmPurchase]");
OnLog(" Status : %s", Status ? TEXT("true") : TEXT("false"));
OnLog(" ShopKey : %s", *(ShopKey));
OnLog(" PurchaseProduct size : %d", Size);
for (int i = 0; i < Size; i++, PurchaseProducts++)
{
OnLog(" -> Index: %d", i);
OnLog("---------------------------------------------- --------");
OnLog(" CategoryId : %s", *(PurchaseProducts->CategoryId));
OnLog(" ProductId : %I64d", PurchaseProducts->ProductId);
OnLog(" TotalQuantity : %d", PurchaseProducts->TotalQuantity);
OnLog(" MemberQuantity : %d", PurchaseProducts->MemberQuantity);
OnLog(" GuidQuantity : %d", PurchaseProducts->GuidQuantity);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
reference
In the above sample code, FString shopKey
in the function is the same value as YOUR_SHOP_KEY
called by StoveSDKIAPInit
function.
You need to send YOUR_SHOP_KEY
with shopKey
as an input parameter.
If an error occurs while executing UMyStoveSDKObject::OnConfirmPurchase
function, OnError
callback will be called.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
500 | Internal Server Error |
999999 | undefined error |
# 9) Verification of product purchase history
Use the UMyStoveSDKObject::StoveSDKVerifyPurchase
function to verify product purchase history.
The value of the IsPurchased field is true for products that have been purchased more than once.
Verification of product purchase history is performed targeting the cache within the PC SDK.
At this time, if you explicitly enter the value of the CategoryId
parameter, only that category will be searched.
If you enter an empty string ("") in the value of the CategoryId
parameter, the search will be conducted for all categories.
Therefore, it may be advantageous in terms of search speed to accurately enter the category ID to search.
// input parameters
// const FString& CategoryId: Category ID to search for products
// const FString& ProductId : Product ID
const FStovePurchaseVerification UMyStoveSDKObject::StoveSDKVerifyPurchase(const FString& CategoryId, const FString& ProductId)
{
/*Add the 'walkthrough' codes here.*/
FStovePurchaseVerification Verify = Super::StoveSDKVerifyPurchase(CategoryId, ProductId);
if (Verify.ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
OnLog("[Success] StoveSDKVerifyPurchase");
OnLog("%s product in %s category was %s", *ProductId, *CategoryId, Verify.IsPurchased ? TEXT("purchased") : TEXT("not purchased"));
}
else
{
//failure handling
}
return Verify;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
The UMyStoveSDKObject::StoveSDKVerifyPurchase
function returns a FStovePurchaseVerification
structure.
The returned FStovePurchaseVerification
structure contains the product purchase history.
Also, error codes for function calls are included.
# 10) Search archives
Use the UMyStoveSDKObject::StoveSDKFetchInventory
function to retrieve the inventory.
Items that have been purchased are stored in the storage box.
You can process product payment by using the list of purchased products in the storage box.
Normally, games call the UMyStoveSDKObject::StoveSDKFetchInventory
function to check the product purchase status and immediately deliver the product.
If the product information provided is lost due to an error, game reinstallation, etc., it can be used for recovery work using the storage box information.
FStoveResult UMyStoveSDKObject::StoveSDKFetchInventory()
{
/*Add the 'walkthrough' codes here.*/
FStoveResult ErrorResult = Super::StoveSDKFetchInventory();
if (ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
// success handling
}
return ErrorResult;
}
2
3
4
5
6
7
8
9
10
11
12
When the UMyStoveSDKObject::StoveSDKFetchInventory
function is successfully processed, the OnFetchInventory
callback is called.
The FStoveInventoryItem
structure passed to the callback contains meta information about the purchased product.
- FStoveInventoryItem.TransactionMasterNo: Transaction unique master number
- FStoveInventoryItem.TransactionDetailNo: transaction specific detail number
- FStoveInventoryItem.ProductId: Product ID
- FStoveInventoryItem.GameItemId: In-game item ID mapped to product ID
- FStoveInventoryItem.ProductName: product name
- FStoveInventoryItem.Quantity: Quantity of individual product
- FStoveInventoryItem.ThumbnailUrl: Representative product image
void UMyStoveSDKObject::OnFetchInventory(int Size, FStoveInventoryItem* InventoryItems)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[OnFetchInventory]");
OnLog("InventoyItem size : %d", Size);
for (int i = 0; i < Size; i++, InventoryItems++)
{
OnLog(" -> Index: %d", i);
OnLog("---------------------------------------------- --------");
OnLog(" TransactionMasterNo : %I64d", InventoryItems->TransactionMasterNo);
OnLog(" TransactionDetailNo : %I64d", InventoryItems->TransactionDetailNo);
OnLog(" ProductId : %I64d", InventoryItems->ProductId);
OnLog(" GameItemId : %s", *(InventoryItems->GameItemId));
OnLog(" ProductName : %s", *(InventoryItems->ProductName));
OnLog(" Quantity : %d", InventoryItems->Quantity);
OnLog(" ThumnailUrl : %s", *(InventoryItems->ThumbnailUrl));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
If an error occurs while executing UMyStoveSDKObject::StoveSDKFetchInventory
function, OnError
callback will be called.
External errors can be checked through the ExternalError field of the FStoveError
structure.
ExternalError | Description |
---|---|
500 | Internal Server Error |
999999 | undefined error |
# Integrating additional services
The PC SDK provides APIs to integrate additional services into games.
Additional services supported by PC SDK include custom event log, PC SDK version inquiry, over-immersion prevention notification, shutdown notification, tracking clue inquiry.
Games can send custom in-game events (game logs) to the Stove platform. Also, the game can query the semantic version of the PC SDK currently in use.
PC SDK semantic version inquiry can be obtained as a return value, not a callback.
The Over Immersion Prevention Alert delivers a warning phrase about over immersion in the game through a callback every hour.
Shutdown notification is a system that restricts children under the age of 18 from using the game at a specific time per day of the week by parents. When the requirements are met, notifications are delivered through callbacks up to 4 times.
# 1) Callback setting
In order to communicate with the PC SDK using the additional service API, the game must redefine the callback function connected to the UMyStovePCSDKObject
class below.
UCLASS()
class HELLOSTOVE_API UMyStoveSDKObject : public UStoveSDKObject
{
GENERATED_BODY()
public:
//StovePCSDK Event
void OnInitComplete() final;
void OnError(FStoveError Error) final;
void OnToken(FStoveToken Token) final;
void OnUser(FStoveUser User) final;
void OnOwnership(int Size, FStoveOwnership* Ownerships) final;
//Callback called when StashCustomEvent processing is complete
void OnStashCustomEvent(FStoveCustomEvent CustomEvent, int ParameterSize, FStoveCustomEventParameter* Parameters) final;
// ADD 2.6.0 Start
// Callback that is called every hour to prevent over-immersion
void OnOverImmersion(FStoveOverImmersion OverImmersion) final;
// Callback to be called on shutdown limit
void OnShutdown(FStoveShutdown Shutdown) final;
// 2.6.0 End
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Link events by overriding the callback function of the 'UMyStoveSDKObject' class inherited from 'UStoveSDKObject' as in Connection 1) Config, Callback Settings
.
/* In the case of using only the Ownership function,
In addition to the mandatory implementation callbacks OnError and OnInitComplete
Connect by implementing an additional OnOwnership callback.*/
void UMyStoveSDKObject::OnInitComplete()
{
// Process contents after successful initialization
}
void UMyStoveSDKObject::OnError(FStoveError Error)
{
// handling of errors
}
void UMyStoveSDKObject::OnOwnership(int Size, FStoveOwnership* Ownerships)
{
// Process details after checking ownership
}
void UMyStoveSDKObject::OnStashCustomEvent(FStoveCustomEvent CustomEvent, int ParameterSize, FStoveCustomEventParameter* Parameters)
{
// After sending the logs, check the delivered contents
}
// ADD 2.6.0 Start
void UMyStoveSDKObject::OnOverImmersion(FStoveOverImmersion OverImmersion)
{
// Callback that is called every hour to prevent over-immersion
}
void UMyStoveSDKObject::OnShutdown(FStoveShutdown Shutdown)
{
// Implement if selective shutdown is required by law.
}
// 2.6.0 End
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
You are not required to implement the OnStashCustomEvent
, OnOverImmersion
, OnShutdown
callbacks. You only need to connect if your game uses the custom event log feature.
warning
The OnOverImmersion
callback must be implemented in cases where game overimmersion/addiction precautions are required by law.
The OnShutdown
callback must be implemented if a selective shutdown is required by law.
# 2) Logging custom events
Log custom events (game logs) with UMyStoveSDKObject::StoveSDKStashCustomEvent
function.
// input parameters
// const FString& Name: event name
// const FString& Category1: primary category name
// const FString& Category2 : 2nd category name
// const FString& SimpleValue : simple value
// const TArray<FStoveCustomEventParameter> Params: Detailed parameter information
// int paramsSize: Number of detailed parameter information
FStoveResult ErrorResult = UMyStoveSDKObject::StoveSDKStashCustomEvent("EVENT_NAME", "CATEGORY1", "CATEGORY2", 1.0f, params, PARAMS_SIZE);
if(ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
/* handle success */
}
2
3
4
5
6
7
8
9
10
11
12
When the StoveSDKStashCustomEvent
function is successfully processed, the OnStashCustomEvent
callback is called.
The FStoveCustomEvent
structure passed to the callback contains the event name passed when calling the API, the primary category name, the secondary category name, and a simple value.
The FStoveCustomEventParameter
structure passed to the callback contains the parameter information passed when calling the API.
void UMyStoveSDKObject::OnStashCustomEvent(FStoveCustomEvent CustomEvent, int ParameterSize, FStoveCustomEventParameter* Parameters)
{
/*Add the 'walkthrough' codes here.*/
OnLog("[StashCustomEvent]");
OnLog(" - CustomEvent.Name : %s", *(CustomEvent.Name));
OnLog(" - CustomEvent.Category1 : %s", *(CustomEvent.Category1));
OnLog(" - CustomEvent.Category2 : %s", *(CustomEvent.Category2));
OnLog(" - CustomEvent.SimpleValue : %f", CustomEvent.SimpleValue);
for (int i = 0; i < ParameterSize; i++, Parameters++)
{
OnLog(" - Parameter[%d].Name : %s", i, *(Parameters->Name));
OnLog(" - Parameter[%d].Value : %s", i, *(Parameters->Value));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Precautions
Callback Parameter The valid scope of FStoveCustomEvent/FStoveCustomEventParameter
structure is limited to the callback function scope.
PC SDK frees internally allocated memory as soon as callback function execution is completed.
Therefore, if you need to save the information of FStoveCustomEvent/FStoveCustomEventParameter
structure outside the scope of the callback function, you must create a copy through deep copy, and
When the use of the copy is complete, the memory must be freed.
# 3) Get PC SDK semantic version
Use the UMyStoveSDKObject::GetSDKVersion
function to retrieve the version information of the PC SDK currently being integrated.
FString Version = UMyStoveSDKObject::StoveSDKGetSDKVersion();
if (Version.IsEmpty() == false)
{
/* handle success */
}
2
3
4
5
# 4) Prevention of excessive immersion in games 2.6.0
The OnOverImmersion
callback is called every hour after starting the game.
The FStoveOverImmersion
structure passed to the callback contains the message, the elapsed time of using the game, and the minimum exposure time (in seconds) of the message.
The message is translated based on the language set in the PC SDK.
- FStoveOverImmersion.Message: Overimmersion message
- FStoveOverImmersion.ElapsedTimeInHours : elapsed time
- FStoveOverImmersion.MinExposureTimeInSeconds : Minimum exposure time of message (in seconds)
void UMyStoveSDKObject::OnOverImmersion(FStoveOverImmersion OverImmersion)
{
OnLog("[OverImmersion]");
OnLog("- Message : %s", *(OverImmersion.Message));
OnLog("- ElapsedTimeInHours : %d", OverImmersion. ElapsedTimeInHours);
OnLog("- MinExposureTimeInSeconds : %d", OverImmersion.MinExposureTimeInSeconds);
// Guidance on preventing excessive immersion in games
}
2
3
4
5
6
7
8
9
Guide to over-immersion messages
과몰입 메시지 : 게임을 플레이한 지 1 시간이 지났습니다. 과도한 게임이용은 정상적인 일상생활에 지장을 줄 수 있습니다.
# 5) shutdown
After starting the game, the OnShutdown
callback is called based on the timetable registered in the shutdown system only for those subject to selective shutdown.
The OnShutdown
callback can be called up to 4 times, and the time it is called and the actions to be taken in the game are as follows.
- Shutdown event after successful PCSDK initialization
- Shutdown notification 10 minutes ago: Shows only notification that you will be logged out after 10 minutes
- Notification of shutdown 5 minutes ago: Shows only notification that you will be logged out after 5 minutes
- Shutdown notification 1 minute ago: Displays only notification that you will be logged out after 1 minute
- Shutdown Notification: Displays a notification that you will be logged out and ends the game immediately upon user confirmation
The FStoveShutdown
structure passed to the callback contains the remaining time until shutdown, the message, and the message exposure time (seconds).
- FStoveShutdown.InadvanceTimeInMinutes: The remaining time (minutes) until the user shuts down. If 0, the game ends immediately.
- FStoveShutdown.Message : Shutdown notification message
- FStoveShutdown.ExposureTimeInSeconds: message exposure time (seconds)
void UMyStoveSDKObject::OnShutdown(const FStoveShutdown Shutdown)
{
//print shutdown information
OnLog("[Shutdown]");
OnLog("- InAdvanceTimeInMinutes : %d", Shutdown. InAdvanceTimeInMinutes);
OnLog("- Message : %s", *(Shutdown.Message));
OnLog("- ExposureTimeInSeconds : %d", Shutdown. ExposureTimeInSeconds);
}
2
3
4
5
6
7
8
9
Precautions
The valid scope of the callback parameter FStoveShutdown
structure is limited to the scope of the callback function.
PC SDK frees internally allocated memory as soon as callback function execution is completed.
Therefore, if you need to save the information of the FStoveShutdown
structure outside the scope of the callback function, you must create a copy through deep copy.
When the use of the copy is complete, the memory must be freed.
Shutdown Message Information
10 minutes : 회원님은 게임 시간 선택제 적용 대상으로 10 분 후 게임 이용이 제한됩니다.
5 minutes : 회원님은 게임 시간 선택제 적용 대상으로 5 분 후 게임 이용이 제한됩니다.
1 minutes : 회원님은 게임 시간 선택제 적용 대상으로 1 분 후 게임 이용이 제한됩니다.
0 minutes : 회원님은 게임 시간 선택제 적용 대상으로 게임 이용이 제한되어 게임을 종료합니다.
# 6) Lookup Tracking Clues
The UMyStoveSDKObject::StoveSDKGetTraceHint
function retrieves a set of clues for tracing the stove platform logs.
FStoveTraceHint TraceHint = UStoveSDKObject::StoveSDKGetTraceHint();
if (TraceHint.ErrorResult.Result == StovePCResult::STOVE_PC_NO_ERROR)
{
OnLog("[GetTraceHint]");
OnLog(" - TraceHint.SessionId : %s", *(TraceHint.SessionId));
OnLog(" - TraceHint.RefSessionId : %s", *(TraceHint.RefSessionId));
OnLog(" - TraceHint.Uuid : %s", *(TraceHint.Uuid));
OnLog(" - TraceHint.ServiceProtocol : %s", *(TraceHint.ServiceProtocol));
OnLog(" - TraceHint.RefResourceType : %s", *(TraceHint.RefResourceType));
}
else
{
/* handle failure */
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
The UStoveSDKObject::StoveSDKGetTraceHint
function returns a FStoveTraceHint
structure.
The returned FStoveTraceHint
structure includes the session ID and reference session ID.
Also included are error codes for function calls.
# Updating Unreal Plugins
Guide for updating an existing Unreal Plugin to the new version. The StoveSDKPluing.uplugin file specifies the current version of the PCSDK.
{
"FileVersion": 3,
"Version": 1,
"VersionName": "v2.5.0",
"FriendlyName": "StoveSDKPlugin",
"Description": "StoveSDK API for integrating Stove Client",
"Category": "StoveSDK",
"CreatedBy": "© Smilegate. All Rights Reserved.",
"CreatedByURL": "https://www.onstove.com/",
"DocsURL": "https://studio-docs.onstove.com/pc/GettingStarted/",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": true,
"Modules": [
{
"Name": "StoveSDKPlugin",
"Type": "Runtime",
"LoadingPhase": "Default",
"WhitelistPlatforms": [
"Win64"
]
}
],
"Plugins": [
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Check the current version and download the latest version to update. After downloading and unzipping, a Plugins folder will be created.
Copy the latest version of the Pluings
folder and overwrite the Plugins
folder in the game engine.
The Plugins
folder linked to the game may also contain third-party plug-ins, so only StoveSDKPlugin
is overwritten.
Once overwriting is complete, rebuild according to the Unreal Engine version from the right-click menu of the .uproject currently being used in the game project.
When upgrading to Unreal v2.6.0 or higher
- From v2.6.0, the spelling of function arguments, structure fields, etc. has changed according to the Unreal coding convention, so please check the coding convention in the latest guide.
- If the version is PCSDK v2.0 or higher, it can be updated using the guide above.