# PC SDK Native 연동 가이드

# 소개

STOVE 플랫폼은 게임 배포 및 판매, 커뮤니티, 지표분석 등을 포함한, 게임 출시의 모든 과정을 원스탑으로 처리할 수 있는 통합 서비스를 제공합니다. PC SDK(Native)를 사용하면 Stove 플랫폼이 제공하는 서비스를 게임에 쉽게 통합할 수 있습니다.

여기서는 PC SDK(Native)를 연동하는 방법에 대해 설명합니다.

참고

confirm PC SDK(Native) 연동이 처음이라면, PC SDK Native 따라하기를 먼저 읽어보기 바랍니다.

# 사전준비

  • 스토브 가입 계정과 출시 게임용 App key, App secret, Game Id를 STOVE Studio (opens new window)에서 발급받았는지 확인합니다.
  • PC SDK 다운로드 페이지에서, 최신 버전의 Native(C/C++) 배포 파일(이하 StovePCSDK로 표기)을 다운로드 합니다.

# StovePCSDK 배포 파일 구성

# 1) include 폴더

StovePCSDK를 다운로드하고 압축을 풀면 include 폴더에 아래 파일들이 포함되어 있습니다.

  • StovePCCallback.h 연동된 게임과 NativeSDK API 호출 후 콜백을 전달받기 위한 콜백정의 헤더 파일입니다.
  • StovePCEnum.h NativeSDK 에서 에러, API타입, 비동기 상태 값등 Enum으로 정의 되어 있는 헤더 파일입니다.
  • StovePCDefine.h 연동된 게임과 NativePCSDK 간의 커뮤니케이션을 위해 사용되는 API 호출결과(StovePCResult), 에러결과 구조체(StovePCError), 콜백 함수, API 요청/응답 파라미터 등이 선언되어 있습니다.
  • StovePCSDK.h 연동된 게임과 NativePCSDK 간의 커뮤니케이션을 위해 사용되는 API 함수가 선언되어 있습니다.

# 2) bin 폴더

bin 폴더 하위에는 플랫폼(Win32/x64) 및 구성(Debug/Release)별로 필요한 바이너리가 포함되어 있습니다.

  • concrt140.dll
  • msvcp100.dll
  • msvcp140.dll
  • msvcr100.dll
  • sgup_api(64).dll
  • StovePCSDK.dll
  • vcruntime140.dll

confirm StovePCSDK.lib을 제외한 위 목록의 Dll 파일들은 게임 클라이언트를 최종 사용자에게 배포할 때, 반드시 포함되어야 합니다.

# 3) sample 폴더

sample 폴더 하위에는 StovePCSDK의 동작을 확인해 볼 수 있는 StovePCSDKTestMfc.exe GUI 애플리케이션이 각 플랫폼(Win32/x64)마다 Release 빌드로 포함되어 있습니다.
먼저, StovePCConfig.MFC.ini 파일에 App key, App secret등을 입력한 다음, StovePCSDKTestMfc.exe를 실행합니다. 또한 StovePCSDKTestMfc를 직접 실행해서 Setting UI에 AppKey, SecretKey 등을 직접 입력할 수 있습니다.

# StovePCSDK 빌드 환경 구성하기

빌드 환경 구성은 PC SDK Native 따라하기프로젝트 환경 구성하기 항목을 참고하세요.

# 연동하기

# 1) Config, Callback 설정

PC SDK를 초기화하기 위해서는, 먼저 StovePCConfigStovePCCallback 구조체에 값을 채운 뒤, StovePC_Init 함수를 호출합니다.
아래 코드를 참고하여 StovePCConfig 구조체의 각 필드 값을 채웁니다.

StovePCConfig config{"live",
                    "YOUR_APP_KEY",
                    "YOUR_SECRET_KEY",
                    "YOUR_GAME_ID",
                    StovePCLogLevel::STOVE_PC_LOG_LEVEL_DEBUG,
                    ""};
1
2
3
4
5
6

StovePCConfig 구조체에 대한 설명은 StovePCDefine.h 파일을 참고하세요.

게임과 PC SDK간의 커뮤니케이션은 StovePCCallback 구조체와 연결된 콜백함수들을 사용합니다. 게임 코드에서는 아래 StovePCCallback 구조체의 콜백 포인터에 연결할 함수 포인터를 사전에 정의하고 정의된 함수의 포인터를 연결시켜 줘야해야 합니다.

struct StovePCCallback
{
    /// StovePCSDK 에서 에러발생시 호출되는 콜백
    void(*OnError)(const StovePCError error);

    /// PC SDK 초기화가 완료됐을 때 호출되는 콜백
    void(*OnInitComplete)();

    /// GetToken 처리가 완료됐을 때 호출되는 콜백
    void(*OnToken)(const StovePCToken token);

    /// GetUser 처리가 완료됐을 때 호출되는 콜백
    void(*OnUser)(const StovePCUser user);

    /// GetOwnership 처리가 완료됐을 때 호출되는 콜백
    void(*OnOwnership)(int size, StovePCOwnership* ownership);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

StovePCCallback 구조체의 instance는 사용하기 전에 반드시 NULL 초기화가 필요합니다.

/* StovePCCallback 구조체 instance 생성*/
StovePCCallback callback;
/* 모든 함수 포인터를 NULL로 초기화*/
memset(&callback, 0, sizeof(StovePCCallback));
/* 구현한 함수 포인터를 연결*/
callback.OnError = OnMyErrorCallback;
callback.OnInitComplete = OnMyInitCompleteCallback;
callback.OnToken = OnMyTokenCallback;
callback.OnUser = OnMyUserInfoCallback;
callback.OnOwnership = OnMyOwnershipCallback;
1
2
3
4
5
6
7
8
9
10

필수적으로 연동해야 하는 OnError, OnInitComplete, OnOwnership 콜백함수 외의 나머지 콜백함수는 필요 시에만 연동을 하면 됩니다. 예를 들어, 소유권(Ownership) 기능만 사용하는 경우, 아래와 같이 연결하면 됩니다.

/*소유권(Ownership) 기능만 사용하는 경우는,
필수 구현 콜백인 OnError, OnInitcomplte외에
OnOwnership 콜백만 추가로 구현해서 연결합니다.*/
callback.OnError = OnMyErrorCallback;
callback.OnInitComplete = OnMyInitCompleteCallback;
callback.OnOwnership = OnMyOwnershipCallback;
1
2
3
4
5
6

# 2) SDK 초기화

StovePCConfig와 StovePCCallback 구조체 초기화 및 콜백함수 연결이 완료되었으면 PC SDK를 초기화하기 위해 StovePC_Init 함수를 호출합니다.

StovePCResult result = StovePC_Init(config, callback);
if (result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /*StovePCSDK init 성공
    타이머 등을 이용해서 일정 주기로 StovePC_RunCallback() 호출*/

}
1
2
3
4
5
6
7

StovePC_Init 함수는 config와 callback의 유효성 여부만 확인한 후, 즉시 StovePCResult enum 타입 값을 반환합니다.
성공한 경우, STOVE_PC_NO_ERROR 값이 반환됩니다. 실패한 경우는 해당 에러 코드를 반환하며 게임 종료를 처리해야 합니다. 전체 에러 코드 목록은 StovePCDefine.h 파일의 StovePCResult enum을 확인하면 됩니다.

반환값이 STOVE_PC_NO_ERROR, 즉 '성공'인 경우, StovePC_RunCallback 함수를 주기적으로 호출해 줍니다.
StovePC_RunCallback 함수를 주기적으로 호출해야만, 연결된 콜백이 정상적으로 호출됩니다.
호출 주기가 길면 콜백의 응답 속도도 느려지게 되므로, 적당한 호출 주기를 유지하는 것이 좋습니다. 본 가이드의 예제 코드는 호출 주기를 0.5초로 설정했습니다.

confirm PC SDK에 연결된 콜백함수는 StovePC_RunCallback 함수를 호출한 스레드에서만 호출됩니다.

StovePC_Init 함수는 config와 callback 유효성 확인을 제외한, 그 외의 작업을 비동기로 처리합니다.
비동기 작업이 성공적으로 완료된 경우, OnInitComplete 콜백이 호출되며, 에러가 발생한 경우는 OnError 콜백이 호출됩니다.
에러가 발생한 경우, 전달된 StovePCError 구조체를 통해 에러 코드, 메시지 등을 확인할 수 있습니다.

void OnInitComplete()
{
    printf("pc sdk init success");
}

void OnError(const StovePCError error)
{
	switch (Error.functionType)
	{
	case STOVE_PC_INIT:
	case STOVE_PC_GET_USER:
	case STOVE_PC_GET_OWNERSHIP:
		QuitApplicationDueToError();
		break;
	}
}

void QuitApplicationDueToError()
{
	// 어쩌면 당신은 즉시 앱을 중단하기보다는 사용자에게 앱 중단에 대한 메시지를 보여준 후
	// 사용자 액션(e.g. 종료 버튼 클릭)에 따라 앱을 중단하고 싶어 할지도 모릅니다.
	// 그렇다면 여기에 QuitApplication을 지우고 당신만의 로직을 구현하십시오.
	// 권장하는 필수 사전 작업 오류에 대한 메시지는 아래와 같습니다.
	// 한국어 : 필수 사전 작업이 실패하여 게임을 종료합니다.
	// 그 외 언어 : The required pre-task fails and exits the game.
	OnStoveLog("QuitApplicationDueToError");
	exit(0)
}
1
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

OnInitComplete 콜백이 오기 전, PC SDK의 초기화 상태 값을 조회할 필요가 있는 경우, StovePC_GetInitState 함수를 사용할 수 있습니다.

/*StovePC_Init 호출 후...*/
while(StovePC_GetInitState()
        == StovePCInitState::STOVE_PC_INIT_PENDING)
{
    sleep(500ms);
    StovePC_RunCallback();
}

if (StovePC_GetInitState()
            == StovePCInitState::STOVE_PC_INIT_COMPLETE)
{
    /*초기화 완료
    OnInitComplete 콜백이 호출됨*/
}
else
{
    /*초기화 실패
    OnError 콜백이 호출됨*/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 3) SDK 연동시 주의사항

주의사항

StovePCConfig 구조체의 로그레벨 설정시 테스트 시에는 StovePCLogLevel::STOVE_PC_LOG_LEVEL_DEBUG 값으로 설정하고, 정식 출시 시에는 StovePCLogLevel::STOVE_PC_LOG_LEVEL_ERROR 값으로 설정하기 바랍니다.

PC SDK 초기화가 완료되기 전에 GetToken, GetUser, GetOwnership 함수를 호출하면 정상적으로 결과를 받지 못할 수 있습니다. 즉, OnInitComplete 콜백이 정상적으로 수신된 이후에 GetToken, GetUser, GetOwnership 함수를 호출해야 정상적으로 결과를 받을 수 있습니다.

# 4) SDK 종료

PC SDK 사용이 끝난 뒤에 StovePC_UnInit 함수를 호출하여 사용중인 리소스를 정리합니다.

StovePCResult result = StovePC_UnInit();
if (result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /*성공 처리*/
}
...
1
2
3
4
5
6

# 5) 사용자 정보 얻기

StovePC_GetUser 함수로 STOVE 런처에 로그인한 사용자 정보를 조회합니다.

StovePCResult result = StovePC_GetUser();
if (result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /*성공 처리*/
}
1
2
3
4
5

StovePC_GetUser 함수가 정상적으로 처리되면 OnUser 콜백이 호출됩니다.
콜백에 전달되는 StovePCUser 구조체를 통해 사용자의 멤버넘버, 닉네임, 게임사용자아이디 정보들을 알 수 있습니다. StovePCUser 구조체에 대한 설명은 StovePCDefine.h 파일에 설명되어 있습니다.

void OnUser(const StovePCUser user)
{
    /*사용자 정보 출력*/
    printf("User Info(memberNo = %I64d, nickname = %S, gameUserId = %s)",
                      user.memberNo, user.nickname, user.gameUserId);
}
1
2
3
4
5
6

# 6) 토큰 정보 얻기

StovePC_GetToken 함수로 STOVE 런처에 로그인한 사용자의 토큰 정보를 확인할 수 있습니다.

StovePCResult result = StovePC_GetToken();
if (result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /*성공 처리*/
}
1
2
3
4
5

StovePC_GetToken 함수가 정상적으로 처리되면 OnToken 콜백이 호출됩니다.
콜백에 전달되는 StovePCToken 구조체에는 토큰 문자열이 포함되어 있습니다.

void OnToken(const StovePCToken token)
{
    /*토큰 정보 출력*/
    printf("Token : %s", token.accessToken);
}
1
2
3
4
5

confirm 토큰이란? STOVE 런처에 로그인된 사용자의 엑세스토큰(Access Token)으로 게임서버가 이 엑세스토큰을 스토브 인증서버로 전달해서 로그인한 사용자의 유효성 검증을 수행할 수 있습니다. 엑세스토큰에 대한 상세한 설명은 store.support@smilegate.com으로 기술지원을 받으시길 바랍니다

# 7) 소유권 정보 얻기

StovePC_GetOwnership 함수로 사용자가 해당 게임을 구매해서 소유하고 있는지 여부를 확인할 수 있습니다.


StovePCResult result = StovePC_GetOwnership();
if (result == STOVE_PC_NO_ERROR)
{
    /*성공 처리*/
    /*소유권에 관한 정보는 OnOwnership 콜백으로 전달됩니다.*/ 
}
1
2
3
4
5
6
7

StovePC_GetOwnership 함수가 정상적으로 처리되면 OnOwnership 콜백이 호출됩니다.
OnOwnership 콜백의 파라미터인 StovePCOwnership 구조체에 대한 세부 정보는 StovePCDefine.h 파일을 참고하세요.

아래는 OnOwnership 콜백에서 게임 구매 여부를 판단하는 예시 코드입니다.
DLC가 없는 패키지게임인 경우, 20~23 line의 확인 코드는 불필요합니다.

void OnOwnership(int size, StovePCOwnership* ownership)
{
    bool owned = false;
 
    StovePCOwnership* data = ownership;
    for (int i = 0; i < size; i++, data++)
    {
        if ((data->memberNo != LOGIN_USER_MEMBER_NO /*StovePCUser 구조체의 memberNo*/)
            || (data->ownershipCode != 1 /*1:소유권 획득, 2:소유권 해제(구매 취소한 경우)*/))
        {
            continue;
        }
 
        if (0 == wcscmp(L"YOUR_GAME_ID", data->gameId) && data->gameCode == 3 /* 3: 정식게임, 4: DEMO*/)
        {
            owned = true; // 소유권 확인 변수 true로 설정
        }
 
        /*DLC를 판매하는 게임일 때만 필요*/
        if (0 == wcscmp(L"YOUR_DLC_ID", data->gameId) && data->gameCode == 5 /* 5: DLC*/)
        {
            // YOUR_DLC_ID(DLC) 소유권이 있기에 DLC 플레이 허용
        }
    }
 
    if(owned)
    {
        // 소유권 검증이 정상적으로 완료된 이후 게임진입 로직 작성
    }
    else
    {
        // 소유권 검증실패 후 게임을 종료하고 에러메세지 표출 로직 작성
    }
     
     
}
1
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
  • 게임을 구매한 계정(소유권 보유)으로 STOVE 런처에 로그인한 후 게임을 플레이를 할 수 있습니다.
  • 게임 소유권이 없는 계정으로 STOVE 런처에 로그인한 후 exe 실행 시 아래 안내 메시지(예시)를 출력한 후 게임을 종료합니다.
    • 한국어 외의 OS : Please log in to STOVE Client with the account that has purchased the game.
    • 한국어 : 게임을 구매한 계정으로 STOVE 클라이언트에 로그인하시기 바랍니다.

confirm 게임 소유권이 있는 계정이 없어도 소유권 기능을 테스트할 수 있으며, 자세한 방법은 FAQ를 확인하시기 바랍니다.

# 8) 언어 설정

StovePC_SetLanguage 함수로 언어를 설정합니다.
PC SDK는 초기화시 시스템 언어(운영체제 언어)를 이용하여 언어를 기본으로 설정합니다.
명시적으로 시스템 언어(운영체제 언어)를 설정하려면 파라미터로 "system"을 입력합니다.
특정 언어를 설정하기 위해서는 초기화 성공 이후(e.g. OnInitComplete) StovePC_SetLanguage 함수를 호출합니다.

StovePCResult result = StovePC_SetLanguage("LANGUAGE_CODE");
if (result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5

# 9) 언어 번역

StovePC_TranslateLanguage 함수로 언어를 번역합니다.
PC SDK는 설정된 언어 정보를 기반으로 특정 문자열에 대한 번역본을 제공합니다.
특정 문자열은 PC SDK 에서 관리하는 문자열 아이디(String Id)로 관리됩니다.
게임에서 PC SDK 팝업 UI 를 직접 구현하는 경우 UI에 표시되는 문자열은 StovePC_TranslateLanguage 함수를 통해 번역된 문자열을 표시해야 합니다.

wchar_t* translated = StovePC_TranslateLanguage("STRING_ID");
1

주의사항

PC SDK에 설정된 언어에 대해 특정 문자열의 번역본이 없는 경우 영어 번역본을 리턴하며,
예외 발생 또는 지원하지 않는 문자열 아이디에 대해서는 입력 파라미터(문자열 아이디)를 그대로 리턴합니다.

# 에러 확인

PC SDK 사용 중 발생하는 에러는 크게 두 가지 경우로 구분해서 확인할 수 있습니다.

# 함수 호출 후 반환되는 StovePCResult enum 값

PC SDK의 모든 함수는 호출 직후, 호출이 성공했는지 여부를 나타내는 StovePCResult enum 값을 반환합니다.
전체값은 PC SDK 오류 코드 페이지에서 확인 할 수 있습니다.

# OnError 콜백을 통해 전달되는 StovePCError 구조체

PC SDK 함수 중, 비동기로 동작하는 함수에서 에러가 발생한 경우는 OnError 콜백이 호출되며, 에러에 대한 설명이 포함된 StovePCError 구조체가 전달됩니다.

/*OnError 콜백이 호출될 때 전달 됩니다.*/
struct StovePCError
{
    /*호출된 함수를 나타내는 enum 값*/
    StovePCFunctionType functionType;

    /*발생한 에러 유형을 나타내는 enum 값*/
    StovePCResult result;

    /*발생한 에러 메시지*/
    char* message;

    /*외부 에러(http 에러, 외부 모듈 에러)가 발생한 경우, 해당하는 에러 코드*/
    int externalError; 
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 게임지원서비스 연동하기

PC SDK는 스토브 플랫폼의 게임지원서비스를 게임에 통합할 수 있도록 API를 제공합니다. PC SDK가 지원하는 게임지원서비스로는 스탯, 업적, 리더보드가 있습니다. 각각의 서비스는 아래와 같이 정의합니다.

  • 스탯 : 유저의 다양한 게임 Play Data를 수치로 기록해 주는 서비스
  • 업적 : 게임 Play 도전 과제를 설정하고, 유저 별 달성 정보를 제공해 주는 서비스
  • 리더보드 : 특정 게임 Play Data의 유저 랭킹 정보를 제공해 주는 서비스

PC SDK 게임지원서비스 API를 사용하기 위해서는 스튜디오를 통한 게임지원서비스의 메타데이터 등록이 선행되어야 합니다.

메타데이터 관리에 대한 내용은 간단한 콘솔 사용 매뉴얼을 참고하시기 바랍니다.

# 1) Callback 설정

게임지원서비스 API를 사용하여 PC SDK와 커뮤니케이션 하기 위하여, 게임에서는 아래 StovePCCallbak 구조체의 콜백 포인터에 연결할 콜백함수를 정의해야 합니다.

struct StovePCCallback
{
    void(*OnError)(const StovePCError error);
    void(*OnInitComplete)();
    void(*OnToken)(const StovePCToken token);
    void(*OnUser)(const StovePCUser user);
    void(*OnOwnership)(int size, StovePCOwnership* ownership);

    // GetStat 처리가 완료됐을 때 호출되는 콜백
    void(*OnStat)(const StovePCStat stat);

    // SetStat 처리가 완료됐을 때 호출되는 콜백
    void(*OnSetStat)(const StovePCStatValue statValue);

    // GetAchievement 처리가 완료됐을 때 호출되는 콜백
    void(*OnAchievement)(StovePCAchievement achievement);

    // GetAllAchievement 처리가 완료됐을 때 호출되는 콜백
    void(*OnAllAchievement)(int size, StovePCAchievement* achievement);

    // GetRank API 호출시 응답받는 콜백 함수 포인터
    void(*OnRank)(int size, StovePCRank* rank, unsigned int rankTotalCount);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

연동하기 1) Config, Callbak 설정에서와 같이 StovePCCallback 구조체의 콜백 포인터에 콜백함수를 연결합니다.

// StovePCCallback 구조체 instance 생성
StovePCCallback callback;

// 모든 함수 포인터를 NULL로 초기화
memset(&callback, 0, sizeof(StovePCCallback));

// 구현한 함수 포인터를 연결
callback.OnError = OnMyErrorCallback; /*전역에서 정의한 콜백함수*/
callback.OnInitComplete = OnMyInitCompleteCallback; /*전역에서 정의한 콜백함수*/
callback.OnToken = OnMyTokenCallback; /*전역에서 정의한 콜백함수*/
callback.OnUser = OnMyUserInfoCallback; /*전역에서 정의한 콜백함수*/
callback.OnOwnership = OnMyOwnershipCallback; /*전역에서 정의한 콜백함수*/
 
 // 게임지원서비스 
callback.OnStat = OnMyStat; /*전역에서 정의한 콜백함수*/ 
callback.OnSetStat = OnMySetStat; /*전역에서 정의한 콜백함수*/
callback.OnAchievement = OnMyAchievement; /*전역에서 정의한 콜백함수*/
callback.OnAllAchievement = OnMyAllAchievement; /*전역에서 정의한 콜백함수*/
callback.OnRank = OnMyRank; /*전역에서 정의한 콜백함수*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

OnStat, OnSetStat, OnAchievement, OnAllAchievement, OnRank 콜백함수를 반드시 구현할 필요는 없습니다.

게임에서 사용하는 게임지원서비스에 맞게 필요한 콜백함수만 구현하여 연결하면 됩니다.

# 2) 사용자 스탯 업데이트 하기

StovePC_SetStat 함수로 로그인한 사용자의 해당 게임에 대한 특정 스탯을 업데이트 합니다.

// 입력 파라미터
// const char* statId : 스튜디오에서 등록한 스탯 식별자
// const int statValue : 업데이트할 스탯값
StovePCResult result = StovePC_SetStat("STAT_ID", STAT_VALUE);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7
8

StovePC_SetStat 함수가 정상적으로 처리되면 OnSetStat 콜백이 호출됩니다.
콜백에 전달되는 StovePCStatValue 구조체에는 현재 스탯값과 업데이트 상태를 나타내는 플래그 및 에러메세지가 포함되어 있습니다.

스탯값이 완전하게 반영되어 업데이트 되었다면 Updated 필드는 true, ErrorMessage 필드는 빈문자열이 포함되며, 스탯값이 부분적으로 업데이트 되었다면 Updated 필드는 true, ErrorMessage 필드는 "integer overflow" 와 같은 문자열이 포함됩니다.

예를들어 INCREMENT 유형 스탯의 현재 스탯값이 2,147,483,000 라고 가정하고 StovePC_SetStat API를 통해 1,000을 합산하려 한다면 Int32 타입이 가질 수 있는 값의 범위를 벗어나게 되므로 업데이트를 요청한 값(1,000)의 일부만 반영되어 현재값이 Int32 타입의 최대값인 2,147,483,647로 업데이트 되는 경우 ErrorMessage 필드에 "integer overflow" 와 같은 문자열이 포함됩니다.

아래 표는 StovePCStatValue 구조체를 통해 얻을 수 있는 결과의 목록입니다.

스탯유형 Updated ErrorMessage 결과
모든유형 True ""(빈문자열) 요청값이 현재값에 완전히 업데이트 됨
INCREMENT True "integer overflow" 저장 공간 초과로 부분(partial) 업데이트 됨
INCREMENT False "integer overflow" 저장 공간 초과로 업데이트 안됨
MIN False ""(빈문자열) 요청값이 현재값보다 큼
MAX False ""(빈문자열) 요청값이 현재값보다 작음
REPLACE Fasle ""(빈문자열) 요청값이 현재값과 동일함
void OnSetStat(const StovePCStatValue statValue)
{
    // 스탯 업데이트 결과 정보 출력
    printf("OnSetStat");
    printf(" - statValue.currentValue : %d", statValue.currentValue);
    printf(" - statValue.updated : %s", statValue.updated ? "true" : "false");
    printf(" - statValue.errorMessage : %s", statValue.errorMessage);
}
1
2
3
4
5
6
7
8

confirm 주의사항) 콜백파라미터 StovePCStatValue 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다. PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다. 따라서 콜백함수 스코프 밖에서 StovePCStatValue 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_SetStat 함수가 실행 중에 오류가 발생하면 OnError 콜백이 호출됩니다.

StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
2000 Invalid Access
3000 Wrong API Usage
4000 Stats ID Not Found
9000 Service Error

# 3) 사용자 스탯 정보 얻기

StovePC_GetStat 함수로 로그인한 사용자의 해당 게임에 대한 특정 스탯 정보를 조회합니다.

// 입력 파라미터
// const char* statId : 스튜디오에서 등록한 스탯 식별자
StovePCResult result = StovePC_GetStat("STAT_ID");
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7

StovePC_GetStat 함수가 정상적으로 처리되면 OnStat 콜백이 호출됩니다.

콜백에 전달되는 StovePCStat 구조체에는 현재 스탯값이 포함되어 있습니다.

void OnStat(const StovePCStat stat)
{
    // 스탯 정보 출력
    printf("OnStat");
    wprintf(L" - stat.statFullId.gameId : %s", stat.statFullId.gameId);
    printf(" - stat.statFullId.statId : %s", stat.statFullId.statId);
    printf(" - stat.memberNo : %llu", stat.memberNo);
    printf(" - stat.currentValue : %d", stat.currentValue);
    printf(" - stat.updatedAt : %llu", stat.updatedAt);
}
1
2
3
4
5
6
7
8
9
10

confirm 주의사항) 콜백파라미터 StovePCStat 구조체의 유효한 범위는 콜백 스코프로 한정됩니다. PC SDK는 콜백 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다. 따라서 콜백 스코프 밖에서 StovePCStat 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_GetStat 함수가 실행 중에 오류가 발생하면 OnError 콜백이 호출됩니다.

StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
2000 Invalid Access
3000 Wrong API Usage
4000 Stats ID Not Found
9000 Service Error

# 4) 사용자 단일 업적 정보 얻기

StovePC_GetAchievement 함수로 로그인한 사용자의 해당 게임에 대한 특정 단일 업적 정보를 조회합니다.

// 입력 파라미터
// const char* achievementId : 스튜디오에서 생성한 업적 식별자
StovePCResult result = StovePC_GetAchievement("ACHIEVEMENT_ID");
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7

StovePC_GetAchievement 함수가 정상적으로 처리되면 OnAchievement 콜백이 호출됩니다.

콜백에 전달되는 StovePCAchievement 구조체에는 현재 업적값과 업적 달성 상태 및 업적의 메타정보가 포함되어 있습니다.

void OnAchievement(const StovePCAchievement achievement)
{
    // 단일 업적 정보 출력
    printf("OnAchievement");

    printf(" - achievement.achievementId : %s", achievement.achievementId);
    wprintf(L" - achievement.name : %s", achievement.name);
    wprintf(L" - achievement.description : %s", achievement.description);
    wprintf(L" - achievement.defaultImage : %s", achievement.defaultImage);
    wprintf(L" - achievement.achievedImage : %s", achievement.achievedImage);
    printf(" - achievement.condition.goalValue : %d", achievement.condition.goalValue);
    printf(" - achievement.condition.valueOperation : %s", achievement.condition.valueOperation);
    printf(" - achievement.condition.type : %s", achievement.condition.type);
    printf(" - achievement.value : %d", achievement.value);
    printf(" - achievement.status : %s", achievement.status);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

confirm 주의사항) 콜백파라미터 StovePCAchievement 구조체의 유효한 범위는 콜백 스코프로 한정됩니다. PC SDK는 콜백 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다. 따라서 콜백 스코프 밖에서 StovePCAchievement 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_GetAchievement 함수가 실행 중에 오류가 발생하면 OnError 콜백이 호출됩니다.

StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
1200 Not found achievement
9000 Service Error

# 5) 사용자 전체 업적 정보 얻기

StovePC_GetAllAchievement 함수로 로그인한 사용자의 해당 게임에 대한 모든 업적 정보를 조회합니다.

StovePCResult result = StovePC_GetAllAchievement();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5

StovePC_GetAllAchievement 함수가 정상적으로 처리되면 OnAllAchievement 콜백이 호출됩니다.

콜백에 전달되는 StovePCAchievement 구조체에는 현재 업적값과 업적 달성 상태 및 업적의 메타정보가 포함되어 있습니다.

void OnAllAchievement(int size, StovePCAchievement* achievements)
{
    // 모든 업적 정보 출력
    printf("OnAllAchievement");
    printf(" - achievements size : %d", size);

    for (int i = 0; i < size; i++, achievements++)
    {
        printf(" - achievements[%d].achievementId : %s", i, achievements->achievementId);
        wprintf(L" - achievements[%d].name : %s", i, achievements->name);
        wprintf(L" - achievements[%d].description : %s", i, achievements->description);
        wprintf(L" - achievements[%d].defaultImage : %s", i, achievements->defaultImage);
        wprintf(L" - achievements[%d].achievedImage : %s", i, achievements->achievedImage);
        printf(" - achievements[%d].condition.goalValue : %d", i, achievements->condition.goalValue);
        printf(" - achievements[%d].condition.valueOperation : %s", i, achievements->condition.valueOperation);
        printf(" - achievements[%d].condition.type : %s", i, achievements->condition.type);
        printf(" - achievements[%d].value : %d", i, achievements->value);
        printf(" - achievements[%d].status : %s", i, achievements->status);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

confirm 주의사항) 콜백파라미터 StovePCAchievement 구조체 배열의 유효한 범위는 콜백함수 스코프로 한정됩니다. PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다. 따라서 콜백함수 스코프 밖에서 StovePCAchievement 구조체 배열의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_GetAllAchievement 함수가 실행 중에 오류가 발생하면 OnError 콜백이 호출됩니다.

StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
9000 Service Error

# 6) 리더보드 랭킹 정보 얻기

StovePC_GetRank 함수로 해당 게임에 대한 특정 리더보드의 순위 정보를 조회합니다.

// 입력 파라미터
// const char* leaderboardId : 스튜디오에서 생성한 리더보드 식별자
// const unsigned int pageIndex : 조회할 페이지 번호 (1 <= pageIndex)
// const unsigned int pageSize : 조회할 순위의 개수 (1 <= pageSize <= 50)
// const bool includeMyRank : 조회결과에 로그인한 사용자의 순위를 포함할지 여부
StovePCResult result = StovePC_GetRank("LEADERBOARD_ID", PAGE_INDEX, PAGE_SIZE, INCLUDE_MY_RANK);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7
8
9
10

StovePC_GetRank 함수가 정상적으로 처리되면 OnRank 콜백이 호출됩니다.

콜백에 전달되는 StovePCRank 구조체에는 특정 사용자에 대한 점수 및 순위 정보가 포함됩니다.

// 콜백 파라미터
// unsigned int rankTotalCount : 조회한 리더보드에 집계된 전체 순위 개수
void OnRank(int size, StovePCRank* ranks, unsigned int rankTotalCount)
{
    // 순위 정보 출력
    printf("OnRank");
    printf(" - ranks.Length : %d", size);

    for (int i = 0; i < size; i++, ranks++)
    {
        printf(" - ranks[%d].memberNo : %llu", i, ranks->memberNo);
        printf(" - ranks[%d].score : %d", i, ranks->score);
        printf(" - ranks[%d].rank : %u", i, ranks->rank);
        wprintf(L" - ranks[%d].nickname : %s", i, ranks->nickname);
        wprintf(L" - ranks[%d].profileImage : %s", i, ranks->profileImage);
    }

    printf(" - rankTotalCount : %u", rankTotalCount);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

confirm 주의사항) 콜백파라미터 StovePCRank 구조체 배열의 유효한 범위는 콜백함수 스코프로 한정됩니다. PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다. 따라서 콜백함수 스코프 밖에서 StovePCRank 구조체 배열의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_GetRank 함수가 실행 중에 오류가 발생하면 OnError 콜백이 호출됩니다.

StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
1251 Invalid Parameter
1252 CannotFindData
3603 ErrorLeaderBoardNotFound
3631 ErrorMembershipAPI
500 External Server Error

# 팝업 연동하기

PC SDK는 팝업을 게임에 통합할 수 있도록 API를 제공합니다. PC SDK가 지원하는 팝업으로는 자동, 수동, 뉴스, 쿠폰, 커뮤니티가 있습니다.
PC SDK는 팝업을 위한 데이터를 게임에 제공합니다. 게임은 제공받은 데이터를 이용해 팝업뷰를 생성합니다.
각각의 팝업은 아래와 같이 정의합니다.

  • 자동 팝업 : 게임 로비화면에 가장 많이 노출하며 광고와 이벤트 등을 보여주는 팝업
  • 수동 팝업 : 리소스키에 해당하는 등록된 이벤트를 보여주는 팝업
  • 뉴스 팝업 : 공지성 게시글을 한 번에 모아서 보여주는 팝업
  • 쿠폰 팝업 : 쿠폰 등록 페이지를 보여주는 팝업
  • 커뮤니티 팝업 : 게임 커뮤니티 페이지를 보여주는 팝업

PC SDK 팝업 API를 사용하기 위해서는 파트너스를 통합 팝업의 메타데이터 등록이 선행되어야 합니다.

# 1) Callback 설정

팝업 API를 사용하여 PC SDK와 커뮤니케이션 하기 위하여, 게임에서는 아래 StovePCCallback 구조체의 콜백 포인터에 연결할 콜백함수를 정의해야 합니다.

struct StovePCCallback
{
    void(*OnError)(const StovePCError error);
    void(*OnInitComplete)();
    void(*OnToken)(const StovePCToken token);
    void(*OnUser)(const StovePCUser user);
    void(*OnOwnership)(int size, StovePCOwnership* ownership);
 
    /// GetAutoPopup 처리가 완료됐을 때 호출되는 콜백
    void(*OnAutoPopup)(int size, StovePCAutoPopup* autoPopup, int headerSize, StovePCPopupRequestHeader* header);
 
    /// GetManualPopup 처리가 완료됐을 때 호출되는 콜백
    void(*OnManualPopup)(int size, StovePCManualPopup* manualPopup, int headerSize, StovePCPopupRequestHeader* header);
 
    /// GetNewsPopup 처리가 완료됐을 때 호출되는 콜백
    void(*OnNewsPopup)(StovePCNewsPopup newsPopup, int headerSize, StovePCPopupRequestHeader* header);
 
    /// GetCouponPopup 처리가 완료됐을 때 호출되는 콜백
    void(*OnCouponPopup)(StovePCCouponPopup couponPopup, int headerSize, StovePCPopupRequestHeader* header);
 
    /// GetCommunityPopup 처리가 완료됐을 때 호출되는 콜백
    void(*OnCommunityPopup)(StovePCCommunityPopup communityPopup, int cookieSize, StovePCPopupRequestCookie* cookie);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

연동하기 1) Config, Callbak 설정에서와 같이 StovePCCallback 구조체의 콜백 포인터에 콜백함수를 연결합니다.

// StovePCCallback 구조체 instance 생성
StovePCCallback callback;
 
// 모든 함수 포인터를 NULL로 초기화
memset(&callback, 0, sizeof(StovePCCallback));
 
// 구현한 함수 포인터를 연결
callback.OnError = OnMyErrorCallback; /*전역에서 정의한 콜백함수*/
callback.OnInitComplete = OnMyInitCompleteCallback; /*전역에서 정의한 콜백함수*/
callback.OnToken = OnMyTokenCallback; /*전역에서 정의한 콜백함수*/
callback.OnUser = OnMyUserInfoCallback; /*전역에서 정의한 콜백함수*/
callback.OnOwnership = OnMyOwnershipCallback; /*전역에서 정의한 콜백함수*/
  
 // 팝업
callback.OnAutoPopup = OnMyAutoPopup; /*전역에서 정의한 콜백함수*/
callback.OnManualPopup = OnMyManualPopup; /*전역에서 정의한 콜백함수*/
callback.OnNewsPopup = OnMyNewsPopup; /*전역에서 정의한 콜백함수*/
callback.OnCouponPopup = OnMyCouponPopup; /*전역에서 정의한 콜백함수*/
callback.OnCommunityPopup = OnMyCommunityPopup; /*전역에서 정의한 콜백함수*
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

OnAutoPopup, OnManualPopup, OnNewsPopup, OnCouponPopup, OnCommunityPopup 콜백을 반드시 구현할 필요는 없습니다.
게임에서 사용하는 팝업에 맞게 필요한 콜백 함수만 구현하여 연결하면 됩니다.

# 2) 게임프로필 설정

StovePC_SetGameProfile 함수로 게임의 월드와 캐릭터 정보를 설정합니다.
설정된 정보는 팝업에서 활용되므로 팝업을 사용하기 전에 반드시 설정되어야 합니다.
게임프로필의 유효성은 별도로 검사하고 있지 않습니다. 때문에 입력시 유효성 체크(null)를 진행하여 값을 정확히 입력해야 합니다.
입력한 게임프로필은 PCSDK 수명주기 동안만 유효합니다.
즉, PCSDK 를 초기화 할 때 마다 StovePC_SetGameProfile 함수를 호출하여 게임의 월드와 캐릭터 정보를 설정해야 합니다.

// 입력 파라미터
// const char* worldId: 게임의 월드 식별자
// const long characterNo: 캐릭터 식별자
StovePCResult result = StovePC_SetGameProfile("WORLD_ID", CHARACTER_NO);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7
8

# 3) 자동팝업 정보 얻기

StovePC_GetAutoPopup 함수로 자동팝업에 대한 정보를 조회합니다.

StovePCResult result = StovePC_GetAutoPopup();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5

StovePC_GetAutoPopup 함수가 정상적으로 처리되면 OnAutoPopup 콜백이 호출됩니다.
콜백에 전달되는 StovePCAutoPopup 구조체에는 자동팝업에 대한 URL이 포함되어 있습니다.
콜백에 전달되는 StovePCPopupRequestHeader 구조체에는 URL 요청시 셋팅할 헤더의 이름/값 쌍이 포함되어 있습니다.

void OnAutoPopup(int size, StovePCAutoPopup* autoPopup, int headerSize, StovePCPopupRequestHeader* header)
{  

    printf("OnAutoPopup");
    printf(" - autoPopup size = %d", size);
    
    for (int i = 0; i < size; i++, autoPopup++)
    {
        printf("- autoPopup[%d].origin : %s", i, autoPopup->origin);
        printf("- autoPopup[%d].id : %d", i, autoPopup->id);
        printf("- autoPopup[%d].url : %s", i, autoPopup->url);
        
        // ADD 2.6.0 Start
        printf("- autoPopup[%d].control.ui.visible.closeButton : %s", i, autoPopup->control.ui.visible.closeButton ? "true" : "false");
        printf("- autoPopup[%d].control.ui.visible.navigationBar : %s", i, autoPopup->control.ui.visible.navigationBar ? "true" : "false");
        printf("- autoPopup[%d].control.ui.visible.backButton : %s", i, autoPopup->control.ui.visible.backButton ? "true" : "false");
        printf("- autoPopup[%d].control.ui.visible.forwardButton : %s", i, autoPopup->control.ui.visible.forwardButton ? "true" : "false");
        printf("- autoPopup[%d].control.ui.visible.refreshButton : %s", i, autoPopup->control.ui.visible.refreshButton ? "true" : "false");
        printf("- autoPopup[%d].control.ui.visible.homeButton : %s", i, autoPopup->control.ui.visible.homeButton ? "true" : "false");
        printf("- autoPopup[%d].control.ui.visible.disallowedButton : %s", i, autoPopup->control.ui.visible.disallowedButton ? "true" : "false");
        printf("- autoPopup[%d].control.ui.disallowedDay : %d", i, autoPopup->control.ui.disallowedDay);
        printf("- autoPopup[%d].control.ui.closeButtonImage.normal.fileUrl : %s", i, autoPopup->control.ui.closeButtonImage.normal.fileUrl);
        printf("- autoPopup[%d].control.ui.closeButtonImage.normal.fileId : %s", i, autoPopup->control.ui.closeButtonImage.normal.fileId);
        printf("- autoPopup[%d].control.ui.closeButtonImage.pressed.fileUrl : %s", i, autoPopup->control.ui.closeButtonImage.pressed.fileUrl);
        printf("- autoPopup[%d].control.ui.closeButtonImage.pressed.fileId : %s", i, autoPopup->control.ui.closeButtonImage.pressed.fileId);
        printf("- autoPopup[%d].control.ui.closeButtonImage.type : %d", i, autoPopup->control.ui.closeButtonImage.type);
        printf("-------------------------------------------------");
        // 2.6.0 End
    }

    printf("header size = %d", headerSize);

    for (int i = 0; i < headerSize; i++, header++)
    {
        printf(" -> index: %d", i);
        printf("name : %s", header->name);
        printf("value : %s", header->value);
        printf("-------------------------------------------------");
    }

}
1
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

주의사항

콜백파라미터 StovePCAutoPopup/StovePCPopupRequestHeader 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCAutoPopup/StovePCPopupRequestHeader 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고,
사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

성공 콜백(OnAutoPopup)이 실행 되었다고 해도 size 콜백파라미터가 0 인 경우가 있습니다.
이때 autoPopup 콜백파라미터는 null 이 전달 됩니다. autoPopup 콜백파라미터를 사용하기 전에 size 콜백파라미터를 먼저 확인 후 팝업을 띄울지 말지를 결정해야 합니다.
이런 경우 파트너스의 자동팝업 설정을 확인합니다.

자동팝업의 노출 순서는 autoPopup 배열요소의 순서와 동일해야 합니다. 예를 들면 autoPopup 배열이 [A,B,C] 세개의 요소를 포함한다면 A, B, C 순서로 팝업을 노출해야 합니다.

StovePC_GetAutoPopup 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
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) 수동팝업 정보 얻기

StovePC_GetManualPopup 함수로 수동팝업에 대한 정보를 조회합니다.

// 입력 파라미터
// string resourceKey: 파트너스에서 등록한 수동팝업 식별자
StovePCResult result = StovePC_GetManualPopup("RESOURCE_KEY");
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7

StovePC_GetManualPopup 함수가 정상적으로 처리되면 OnManualPopup 콜백이 호출됩니다.
콜백에 전달되는 StovePCManualPopup 구조체에는 수동팝업에 대한 URL이 포함되어 있습니다.
콜백에 전달되는 StovePCPopupRequestHeader 구조체에는 URL 요청시 셋팅할 헤더의 이름/값 쌍이 포함되어 있습니다.

void OnManualPopup(int size, StovePCManualPopup* manualPopup, int headerSize, StovePCPopupRequestHeader* header)
{

    printf("OnManualPopup");
    printf(" - manualPopup size = %d", size);
    
    for (int i = 0; i < size; i++, manualPopup ++)
    {
        printf("- manualPopup[%d].origin : %s", i, autoPopup->origin);
        printf("- manualPopup[%d].id : %d", i, autoPopup->id);
        printf("- manualPopup[%d].url : %s", i, autoPopup->url);
        // ADD 2.6.0 Start
        printf("- manualPopup[%d].control.ui.visible.closeButton : %s", i, manualPopup->control.ui.visible.closeButton ? "true" : "false");
        printf("- manualPopup[%d].control.ui.visible.navigationBar : %s", i, manualPopup->control.ui.visible.navigationBar ? "true" : "false");
        printf("- manualPopup[%d].control.ui.visible.backButton : %s", i, manualPopup->control.ui.visible.backButton ? "true" : "false");
        printf("- manualPopup[%d].control.ui.visible.forwardButton : %s", i, manualPopup->control.ui.visible.forwardButton ? "true" : "false");
        printf("- manualPopup[%d].control.ui.visible.refreshButton : %s", i, manualPopup->control.ui.visible.refreshButton ? "true" : "false");
        printf("- manualPopup[%d].control.ui.visible.homeButton : %s", i, manualPopup->control.ui.visible.homeButton ? "true" : "false");
        printf("- manualPopup[%d].control.ui.visible.disallowedButton : %s", i, manualPopup->control.ui.visible.disallowedButton ? "true" : "false");
        printf("- manualPopup[%d].control.ui.disallowedDay : %d", i, manualPopup->control.ui.disallowedDay);
        printf("- manualPopup[%d].control.ui.closeButtonImage.normal.fileUrl : %s", i, manualPopup->control.ui.closeButtonImage.normal.fileUrl);
        printf("- manualPopup[%d].control.ui.closeButtonImage.normal.fileId : %s", i, manualPopup->control.ui.closeButtonImage.normal.fileId);
        printf("- manualPopup[%d].control.ui.closeButtonImage.pressed.fileUrl : %s", i, manualPopup->control.ui.closeButtonImage.pressed.fileUrl);
        printf("- manualPopup[%d].control.ui.closeButtonImage.pressed.fileId : %s", i, manualPopup->control.ui.closeButtonImage.pressed.fileId);
        printf("- manualPopup[%d].control.ui.closeButtonImage.type : %d", i, manualPopup->control.ui.closeButtonImage.type);
        printf("-------------------------------------------------");
        // 2.6.0 End
    }

    printf("header size = %d", headerSize);

    for (int i = 0; i < headerSize; i++, header++)
    {
        printf(" -> index: %d", i);
        printf("name : %s", header->name);
        printf("value : %s", header->value);
        printf("-------------------------------------------------");
    }

}
1
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

주의사항

콜백파라미터 StovePCManualPopup/StovePCPopupRequestHeader 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCManualPopup/StovePCPopupRequestHeader 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고,
사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

성공 콜백(OnManualPopup)이 실행 되었다고 해도 size 콜백파라미터가 0 인 경우가 있습니다. 이때 manualPopup 콜백파라미터는 null 이 전달 됩니다.
manualPopup 콜백파라미터를 사용하기 전에 size 콜백파라미터를 먼저 확인 후 팝업을 띄울지 말지를 결정해야 합니다. 이런 경우 파트너스의 수동팝업 설정을 확인합니다.

수동팝업의 노출 순서는 manualPopup 배열요소의 순서와 동일해야 합니다. 예를 들면 manualPopup 배열이 [A,B,C] 세개의 요소를 포함한다면 A, B, C 순서로 팝업을 노출해야 합니다.

StovePC_GetManualPopup 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
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) 뉴스팝업 정보 얻기

StovePC_GetNewsPopup 함수로 뉴스팝업에 대한 정보를 조회합니다.

StovePCResult result = StovePC_GetNewsPopup();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5

StovePC_GetNewsPopup 함수가 정상적으로 처리되면 OnNewsPopup 콜백이 호출됩니다.
콜백에 전달되는 StovePCNewsPopup 구조체에는 뉴스팝업에 대한 URL이 포함되어 있습니다.
콜백에 전달되는 StovePCPopupRequestHeader 구조체에는 URL 요청시 셋팅할 헤더의 이름/값 쌍이 포함되어 있습니다.

void OnNewsPopup(StovePCNewsPopup newsPopup, int headerSize, StovePCPopupRequestHeader* header)
{
    printf("OnNewsPopup");
   
    printf("- newsPopup.origin : %s", i, autoPopup->origin);
    printf("- newsPopup.id : %d", i, autoPopup->id);
    printf("- newsPopup.url : %s", i, autoPopup->url);
    // ADD 2.6.0 Start
    printf("- newsPopup.control.ui.visible.closeButton : %s", newsPopup.control.ui.visible.closeButton ? "true" : "false");
    printf("- newsPopup.control.ui.visible.navigationBar : %s", newsPopup.control.ui.visible.navigationBar ? "true" : "false");
    printf("- newsPopup.control.ui.visible.backButton : %s", newsPopup.control.ui.visible.backButton ? "true" : "false");
    printf("- newsPopup.control.ui.visible.forwardButton : %s", newsPopup.control.ui.visible.forwardButton ? "true" : "false");
    printf("- newsPopup.control.ui.visible.refreshButton : %s", newsPopup.control.ui.visible.refreshButton ? "true" : "false");
    printf("- newsPopup.control.ui.visible.homeButton : %s", newsPopup.control.ui.visible.homeButton ? "true" : "false");
    printf("- newsPopup.control.ui.visible.disallowedButton : %s", newsPopup.control.ui.visible.disallowedButton ? "true" : "false");
    printf("- newsPopup.control.ui.disallowedDay : %d", newsPopup.control.ui.disallowedDay);
    printf("- newsPopup.control.ui.closeButtonImage.normal.fileUrl : %s", newsPopup.control.ui.closeButtonImage.normal.fileUrl);
    printf("- newsPopup.control.ui.closeButtonImage.normal.fileId : %s", newsPopup.control.ui.closeButtonImage.normal.fileId);
    printf("- newsPopup.control.ui.closeButtonImage.pressed.fileUrl : %s", newsPopup.control.ui.closeButtonImage.pressed.fileUrl);
    printf("- newsPopup.control.ui.closeButtonImage.pressed.fileId : %s", newsPopup.control.ui.closeButtonImage.pressed.fileId);
    printf("- newsPopup.control.ui.closeButtonImage.type : %d", newsPopup.control.ui.closeButtonImage.type);
    printf("header size = %d", headerSize);
    // 2.6.0 End

    for (int i = 0; i < headerSize; i++, header++)
    {
        printf(" -> index: %d", i);
        printf("name : %s", header->name);
        printf("value : %s", header->value);
        printf("-------------------------------------------------");
    }

}
1
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

주의사항

콜백파라미터 StovePCNewsPopup/StovePCPopupRequestHeader 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCNewsPopup/StovePCPopupRequestHeader 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고,
사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

성공 콜백(OnNewsPopup)이 실행 되었다고 해도 newsPopup 콜백파라미터의 속성들이 기본값(빈 문자열 또는 0)인 경우가 있습니다.
newsPopup 콜백파라미터의 url 속성을 먼저 확인 후 팝업을 띄울지 말지를 결정해야 합니다. 이런 경우 파트너스의 뉴스팝업 설정을 확인합니다.

StovePC_GetNewsPopup 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
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) 쿠폰팝업 정보 얻기

StovePC_GetCouponPopup 함수로 쿠폰팝업에 대한 정보를 조회합니다.

StovePCResult result = StovePC_GetCouponPopup();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5

StovePC_GetCouponPopup 함수가 정상적으로 처리되면 OnCouponPopup 콜백이 호출됩니다.
콜백에 전달되는 StovePCCouponPopup 구조체에는 쿠폰팝업에 대한 URL이 포함되어 있습니다.
콜백에 전달되는 StovePCPopupRequestHeader 구조체에는 URL 요청시 셋팅할 헤더의 이름/값 쌍이 포함되어 있습니다.

void OnCouponPopup(StovePCCouponPopup couponPopup, int headerSize, StovePCPopupRequestHeader* header)
{
    printf("OnCouponPopup");

    printf("- couponPopup.origin : %s", i,  couponPopup.origin);
    printf("- couponPopup.id : %d", i,  couponPopup.id);
    printf("- couponPopup.url : %s", i,  couponPopup.url);
    // ADD 2.6.0 Start
    printf("- couponPopup.control.ui.visible.closeButton : %s", couponPopup.control.ui.visible.closeButton ? "true" : "false");
    printf("- couponPopup.control.ui.visible.navigationBar : %s", couponPopup.control.ui.visible.navigationBar ? "true" : "false");
    printf("- couponPopup.control.ui.visible.backButton : %s", couponPopup.control.ui.visible.backButton ? "true" : "false");
    printf("- couponPopup.control.ui.visible.forwardButton : %s", couponPopup.control.ui.visible.forwardButton ? "true" : "false");
    printf("- couponPopup.control.ui.visible.refreshButton : %s", couponPopup.control.ui.visible.refreshButton ? "true" : "false");
    printf("- couponPopup.control.ui.visible.homeButton : %s", couponPopup.control.ui.visible.homeButton ? "true" : "false");
    printf("- couponPopup.control.ui.visible.disallowedButton : %s", couponPopup.control.ui.visible.disallowedButton ? "true" : "false");
    printf("- couponPopup.control.ui.disallowedDay : %d", couponPopup.control.ui.disallowedDay);
    printf("- couponPopup.control.ui.closeButtonImage.normal.fileUrl : %s", couponPopup.control.ui.closeButtonImage.normal.fileUrl);
    printf("- couponPopup.control.ui.closeButtonImage.normal.fileId : %s", couponPopup.control.ui.closeButtonImage.normal.fileId);
    printf("- couponPopup.control.ui.closeButtonImage.pressed.fileUrl : %s", couponPopup.control.ui.closeButtonImage.pressed.fileUrl);
    printf("- couponPopup.control.ui.closeButtonImage.pressed.fileId : %s", couponPopup.control.ui.closeButtonImage.pressed.fileId);
    printf("- couponPopup.control.ui.closeButtonImage.type : %d", couponPopup.control.ui.closeButtonImage.type);
    printf("header size = %d", headerSize);
    // 2.6.0 End

    for (int i = 0; i < headerSize; i++, header++)
    {
        printf(" -> index: %d", i);
        printf("name : %s", header->name);
        printf("value : %s", header->value);
        printf("-------------------------------------------------");
    }

}
1
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

주의사항

콜백파라미터 StovePCCouponPopup/StovePCPopupRequestHeader 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCCouponPopup/StovePCPopupRequestHeader 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고,
사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_GetCouponPopup 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.

# 7) 커뮤니티팝업 정보 얻기

StovePC_GetCommunityPopup 함수로 커뮤니티팝업에 대한 정보를 조회합니다.

StovePCResult result = StovePC_GetCommunityPopup();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5

StovePC_GetCommunityPopup 함수가 정상적으로 처리되면 OnCommunityPopup 콜백이 호출됩니다.
콜백에 전달되는 StovePCCommunityPopup 구조체에는 커뮤니티팝업에 대한 URL이 포함되어 있습니다.
콜백에 전달되는 StovePCPopupRequestCookie 구조체에는 URL 요청시 셋팅할 쿠키의 이름/값 쌍이 포함되어 있습니다

void OnCommunityPopup(StovePCCommunityPopup communityPopup, int cookieSize, StovePCPopupRequestCookie* cookie)
{
    printf("OnCommunityPopup");

    printf("- communityPopup.url : %s", i,  couponPopup.url);
    // ADD 2.6.0 Start
    printf("- communityPopup.control.ui.visible.closeButton : %s", communityPopup.control.ui.visible.navigationBar ? "true" : "false");
    printf("- communityPopup.control.ui.visible.navigationBar : %s", communityPopup.control.ui.visible.navigationBar ? "true" : "false");
    printf("- communityPopup.control.ui.visible.backButton : %s", communityPopup.control.ui.visible.backButton ? "true" : "false");
    printf("- communityPopup.control.ui.visible.forwardButton : %s", communityPopup.control.ui.visible.forwardButton ? "true" : "false");
    printf("- communityPopup.control.ui.visible.refreshButton : %s", communityPopup.control.ui.visible.refreshButton ? "true" : "false");
    printf("- communityPopup.control.ui.visible.homeButton : %s", communityPopup.control.ui.visible.homeButton ? "true" : "false");
    printf("- communityPopup.control.ui.visible.disallowedButton : %s", communityPopup.control.ui.visible.disallowedButton ? "true" : "false");
    printf("- communityPopup.control.ui.disallowedDay : %d", communityPopup.control.ui.disallowedDay);
    printf("- communityPopup.control.ui.closeButtonImage.normal.fileUrl : %s", communityPopup.control.ui.closeButtonImage.normal.fileUrl);
    printf("- communityPopup.control.ui.closeButtonImage.normal.fileId : %s", communityPopup.control.ui.closeButtonImage.normal.fileId);
    printf("- communityPopup.control.ui.closeButtonImage.pressed.fileUrl : %s", communityPopup.control.ui.closeButtonImage.pressed.fileUrl);
    printf("- communityPopup.control.ui.closeButtonImage.pressed.fileId : %s", communityPopup.control.ui.closeButtonImage.pressed.fileId);
    printf("- communityPopup.control.ui.closeButtonImage.type : %d", communityPopup.control.ui.closeButtonImage.type);
    printf("cookie size = %d", cookieSize);
    // 2.6.0 End

    for (int i = 0; i < headerSize; i++, cookies++)
    {
        printf(" -> index: %d", i);
        printf("name : %s", header->name);
        printf("value : %s", header->value);
        printf("-------------------------------------------------");
    }

}
1
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

주의사항

콜백파라미터 StovePCCommunityPopup/StovePCPopupRequestCookie 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCcommunityPopup/StovePCPopupRequestCookie 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고,
사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_GetCommunityPopup 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
13008 Mandatory Parameter missing
90001 AccessToken invalid
40101 Invalid token

# 8) 팝업 불허 설정 2.6.0

StovePC_SetPopupDisallowed 함수로 일정기간 동안 특정 팝업이 표시되지 않도록 설정합니다.
게임에서 PC SDK 팝업 UI 를 직접 구현하는 경우 팝업 UI 정보의 control.ui.visible.disallowedButton 값을 참고하여 UI 를 구성하고
버튼 클릭 핸들러에서 StovePC_SetPopupDisallowed 함수를 호출합니다.
StovePC_SetPopupDisallowed 메서드를 호출시 days 파라미터는 팝업 정보의 control.UI.disallowedDay 값을 사용합니다.
팝업 불허가 설정되면 불허기간 동안 해당 팝업 정보는 조회되지 않습니다.

// 입력 파라미터
// int popupId : 파트너스에서 발급된 팝업 식별자
// int days : 파트너스에서 등록한 불허 기간(일단위)또는 -1(다시 보지 않기)
// int days : 파트너스에서 등록한 불허 기간(일단위)
StovePCResult result = StovePC_SetPopupDisallowed(POPUP_ID, DAYS);
if (result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5
6
7
8
9

# 빌링 연동하기 2.6.0

PC SDK는 스토브 플랫폼의 빌링서비스를 게임에 통합할 수 있도록 API를 제공합니다. 빌링서비스로는 상점이 있습니다. 상점에 대한 일반적인 시나리오는 아래와 같습니다. 이는 게임의 상황(e.g. 게임서버 유무)에 따라 조금씩 달라질 수 있습니다.

  • 상점 구성을 위한 정보는 상점 카테고리 조회 및 상품 조회 API를 통해 획득합니다.
  • 게임은 획득한 카테고리 및 상품 정보를 통해 상점을 구성하여 UI를 표시합니다.
  • 각 상품에 대한 구매는 구매 시작 API를 호출합니다.
    • 판매가격이 0 인 상품의 경우
      • 구매 시작 API 응답을 받는 시점에 구매가 완료되어 있습니다.
    • 판매가격이 0 보다 큰 상품의 경우
      • 구매 시작 API의 응답에서 1회용 결제 URL을 획득합니다.
      • 게임은 1회성 결제 URL을 외부브라우저로 탐색합니다. 지원브라우저 : Chrome(75이상), Edge(42이상)
      • 이후 결제 진행은 웹페이지를 통해 완료됩니다.
  • 결제가 완료되면 게임은 구매 상태 확인 API를 호출하여 구매 상태를 확인합니다.
  • 결제가 정상적으로 완료된 것으로 확인되면 게임은 상품을 지급합니다.
  • 구매 검증 API를 통해 상품 구매 이력(1회 이상 구매 여부)을 확인 할 수 있습니다.
  • 보관함 조회 API를 통해 아이템 복원등에 활용할 수 있습니다.

PC SDK 빌링서비스 API를 사용하기 위해서는 파트너스를 통한 빌링서비스의 메타데이터 등록이 선행되어야 합니다.
또한 PC SDK를 통해 상점을 이용하는 경우 StovePC_IAPInit 함수를 호출하여 파트너스로부터 발급 받는 ShopKey를 전달해야 합니다.
ShopKey 설정 없이 빌링서비스 API를 호출할 경우 에러가 반환됩니다.

게임은 상점 열기를 할 때마다 서비스 이용 약관 동의 여부를 체크하여야 합니다.
게임 이용자의 서비스 이용 약관 동의 여부가 미동의인 경우 PCSDK 가 제공하는 약관동의 페이지 Url을 이용하여 브라우저를 열어 게임 이용자가 서비스 이용 약관 동의를 할 수 있도록 합니다.
게임 이용자가 서비스 이용 약관을 동의 이후 상점 열기를 하면 상점으로 진입합니다.

PC SDK는 상점 지원을 위해 내부에 캐시를 운영합니다.

StovePC_FetchProducts 함수의 isRefresh 파라미터를 통해 상품 정보를 캐시에서 가져올지 Web API를 통해 가져올지 결정할 수 있습니다.
Web API를 통해 가져온 상품 정보는 캐시에 전체 또는 부분(카테고리별)적으로 업데이트 된 후 게임에 상품 정보를 콜백으로 전달합니다.
(다만, 캐시가 비어 있으면 isRefresh 파라미터 값과 관계없이 Web API를 통해 상품 정보를 조회하여 캐시에 업데이트 합니다.)
또한 PC SDK는 StovePC_ConfirmPurchase 함수 호출 시점에 Web API 응답을 통해 각 상품의 구매/판매수량 및 구매여부를 캐시에 업데이트 합니다.

# (예시)빌링 연동 흐름도

confirm confirm

  1. 게임 시작 시 PC_SDK 초기화
  • StovePC_IAPInit 함수를 통하여 IAP를 초기화 합니다.
  • IAP 초기화 시 전체 아이템 리스트를 조회 후 내장 캐시에 저장합니다.
  1. 인게임 내 상점 페이지 진입 시 미지급 조회 처리(선택사항)
  • StovePC_FetchInventory 보관함 조회를 통하여 결재 완료 후 미지급된 아이템이 있는 경우 재지급 처리 합니다.
  1. 상점 진입 후 상점구성을 위해 카테고리 리스트를 조회 합니다.
  • StovePC_FetchShopCategories 함수를 통하여 상점내 카테고리를 조회 합니다.
  1. 3번에서 조회 된 상점 내 카테고리 정보를 통해 아이템 정보를 조회 합니다.
  • StovePC_FetchProducts 함수를 통하여 카테고리에 포함된 상품 정보를 조회 합니다.
  1. 상점에서 구매상품을 선택합니다.
  • 구매 상품 정보는 배열로 직접 구성 하여야 합니다.(PruductId/SalePrice/Quantity)
  • Quantity는 반드시 1로 지정 필요 합니다.
  1. 상품구매 시작을 위해 1회용 결제 URL 정보를 조회 합니다.
  • StovePC_StartPurchase 함수를 통해서 1회용 결재창 URL 정보를 조회 합니다.
  1. 인게임 내에서 상품결제안내 팝업을 처리합니다.(외부 브라우져 결재 결과 체크를 위해 반드시 처리해야 합니다.)
  2. 6번을 통해 얻은 1회용 결제 URL 정보로 외부 브라우져를 팝업합니다.
  3. Stove 빌링의 결제창을 통해 제품 결제를 진행합니다.
  • 결제창에서 결재가 완료 된 후 브라우저를 종료 합니다.
  1. 인 게임내 7번에서 생성한 상품결제안내 팝업에서 "결재완료" 버튼을 클릭 시 구매상태 정보를 조회 합니다.
  • StovePC_ConfirmPurchase 함수를 통해서 결재 상태에 대한 정보를 조회 합니다.
  • 결재완료 상태 확인 후 팝업 종료 후 상점페이지로 돌아갑니다.
  1. 구매동선이 완료 됩니다.

참고

외부 브라우저를 통해 Stove 결재 미진행 및 StovePC_StartPurchase를 통해서 결재 결과를 알수 없는 경우
상점 페이지 진입(2번) 시 StovePC_FetchProducts 보관함 조회를 통하여 아이템을 재지급 처리 합니다.


아래 시퀀스 다이어그램은 가상의 상점 운용 시나리오를 보여줍니다.
이는 일반적인 케이스에 대한 일례로써 게임의 상황(e.g. 상점 카테고리 구조, 상점 UI 생성 시점 etc)에 따라 다소 차이가 있을 수 있습니다.

  • PCSDK IAP 초기화
  • 서비스 이용 약관 동의 여부 체크
  • 상점 열기
  • 상품 구매
  • 상품 구매 상태 확인
  • 상품 구매 이력 검증
  • 아이템 복원 처리

# 1) Callback 설정

빌링서비스 API를 사용하여 PC SDK와 커뮤니케이션 하기 위하여, 게임에서는 아래 StovePCCallback 클래스의 콜백에 연결할 콜백함수를 정의해야 합니다.

struct StovePCCallback
{
    void(*OnError)(const StovePCError error);
    void(*OnInitComplete)();
    void(*OnToken)(const StovePCToken token);
    void(*OnUser)(const StovePCUser user);
    void(*OnOwnership)(int size, StovePCOwnership* ownership);

    // FetchTermsAgreement 처리가 완료됐을 때 호출되는 콜백
    void(*OnFetchTermsAgreement ) OnFetchTermsAgreement;

    // FetchShopCategories 처리가 완료됐을 때 호출되는 콜백
    void(*OnFetchShopCategories) OnFetchShopCategories;

    // FetchProducts 처리가 완료됐을 때 호출되는 콜백    
    void(*OnFetchProducts) OnFetchProducts;

    // StartPurchase 처리가 완료됐을 때 호출되는 콜백
    void(*OnStartPurchase) OnStartPurchase;

    // ConfirmPurchase 처리가 완료됐을 때 호출되는 콜백
    void(*OnConfirmPurchase) OnConfirmPurchase;
    
    // FetchInventory 처리가 완료됐을 때 호출되는 콜백
    void(*OnFetchInventory) OnFetchInventory;
}
1
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

연동하기 2) Config, Callback 설정에서와 같이 StovePCCallback 구조체의 콜백포인터 콜백함수를 연결합니다.

// StovePCCallback 구조체 instance 생성
StovePCCallback callback;
  
// 모든 함수 포인터를 NULL로 초기화
memset(&callback, 0, sizeof(StovePCCallback));
  
// 구현한 함수 포인터를 연결
callback.OnError = OnMyErrorCallback; /*전역에서 정의한 콜백함수*/
callback.OnInitComplete = OnMyInitCompleteCallback; /*전역에서 정의한 콜백함수*/
callback.OnToken = OnMyTokenCallback; /*전역에서 정의한 콜백함수*/
callback.OnUser = OnMyUserInfoCallback; /*전역에서 정의한 콜백함수*/
callback.OnOwnership = OnMyOwnershipCallback; /*전역에서 정의한 콜백함수*/

// 서비스 이용 약관
callback.OnFetchTermsAgreement = OnMyFetchTermsAgreement; /*전역에서 정의한 콜백함수*/
    
// 빌링서비스
OnFetchShopCategories = OnMyFetchShopCategories; /*전역에서 정의한 콜백함수*/
OnFetchProducts = OnMyFetchProducts; /*전역에서 정의한 콜백함수*/
OnStartPurchase = OnMyStartPurchase; /*전역에서 정의한 콜백함수*/
OnConfirmPurchase = OnMyConfirmPurchase; /*전역에서 정의한 콜백함수*/
OnFetchInventory = OnMyFetchInventory; /*전역에서 정의한 콜백함수*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

OnFetchTermsAgreement, OnFetchShopCategories, OnFetchProducts, OnStartPurchase, OnConfirmPurchase, OnFetchInventory 콜백을 반드시 구현할 필요는 없습니다.
게임에서 상점이 필요한 경우만 연결하면 됩니다. 단, 상점 기능을 위해서는 5개의 콜백을 모두 구현하여 연결하여야 합니다.

# 2) IAP 초기화

게임에서 PCSDK 를 사용해서 빌링서비스를 제공하기로 결정하였다면, 스토브에서 발급된 상점키 ShopKey 인자값으로 StovePC_IAPInit 함수로 빌링 초기화를 시도합니다.
빌링초기화 시도시 스토브 플랫폼에 등록된 상품리스트를 자동으로 조회한 후 스토브 PCSDK 내부 캐시에 저장을 합니다.
StovePC_IAPInit을 호출하고 실패하였다면 StovePCResultOnError 콜백으로 에러내용을 전달합니다.

// 입력 파라미터
// char* shopKey : 스토브에서 발급받은 shopKey

StovePCResult result = StovePC_IAPInit(YOUR_SHOP_KEY);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5
6
7
8
ExternalError 설명
500 Internal Server Error
50001 상점이 존재하지 않거나, 점검 중
50002 상품이 존재 하지 않거나 판매 불가능 상품
999999 정의되지 않은 오류

# 3) 게임프로필 설정

StovePC_SetGameProfile 함수로 게임의 월드와 캐릭터 정보를 설정합니다.
이는 상품 구매 주체의 수준을 결정하기 위함입니다. PC SDK는 상품 구매 주체의 우선순위를 아래와 같이 매깁니다.

  • Character No. > Guid > Member No.

StovePC_SetGameProfile 함수를 통해 캐릭터 정보가 설정되면 PC SDK는 상품 구매시 Character No.를 기준으로 구매를 진행합니다.
반면에 StovePC_SetGameProfile 함수를 통해 캐릭터 정보가 설정되지 않은 경우, PC SDK는 Guid 또는 Member No.를 기준으로 구매를 진행합니다.
따라서 상품 구매시 상품 구매 주체가 잘 적용되도록 하려면 PC SDK의 빌링서비스 API를 호출하기 전에 StovePC_SetGameProfile API 호출 여부를 고려해야 합니다.
일반적으로 StovePC_SetGameProfile 함수는 월드/캐릭터 변경시마다 1회만 호출하면 됩니다.

# 4) 서비스 이용 약관 동의 여부 조회

StovePC_FetchTermsAgreement 함수로 해당 게임에 대한 사용자의 서비스 이용 약관 동의 정보를 조회합니다.

StovePCResult result = StovePC_FetchTermsAgreement();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5

StovePC_FetchTermsAgreement 함수가 정상적으로 처리되면 OnFetchTermsAgreement 콜백이 호출됩니다.
콜백에 전달되는 StovePCTermsAgreement 구조체에는 약관 동의에 대한 메타정보가 포함되어 있습니다.

  • StovePCShopCategory.gameId: 게임 아이디
  • StovePCShopCategory.result : 서비스 이용 약관 동의 여부
  • StovePCShopCategory.region: 권역 코드
  • StovePCShopCategory.agreementUrl : 서비스 약관 동의 동의 페이지 Url
void OnFetchTermsAgreement(StovePCTermsAgreement termsAgreement)
{
    printf("OnFetchTermsAgreement");
    wprintf(" - gameId : %s", termsAgreement.gameId);
    printf(" - result : %s", termsAgreement.result ? "true" : "false");
    printf(" - region : %s", termsAgreement.resion);
    printf(" - agreementUrl : %s", termsAgreement.agreementUrl);
    
    if(termsAgreement.result == false)
    {
        // 외부 브라우저 열기
        ShellExecute( NULL, "open", termsAgreement.agreementUrl, NULL, NULL, SW_SHOWNORMAL);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

StovePC_FetchTermsAgreement 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
400 잘못된 요청 정보
500 시스템 에러
70898 유효하지 않은 데이터
70899 파라미터에 유효하지 않은 값이 존재
70800 해당 조건으로 존재하는 약관 없음
70804 GS API 호출에러
70805 GUID API 호출 에러
70806 서비스를 찾을 수 없음
70807 GUID API 에서 정의되지 않은 오류 발생
40103 토큰 만료

# 4) 상점 카테고리 정보 얻기

StovePC_FetchShopCategories 함수로 해당 게임에 대한 상점 카테고리 정보를 조회합니다.
카테고리 정보에는 부모 카테고리에 대한 아이디를 포함하고 있어 계층적 구조로 상점을 구성할 수 있습니다.

StovePCResult result = StovePC_FetchShopCategories();
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5

StovePC_FetchShopCategories 함수가 정상적으로 처리되면 OnFetchShopCategories 콜백이 호출됩니다.
콜백에 전달되는 StovePCShopCategory 구조체에는 상점 카테고리에 대한 메타정보가 포함되어 있습니다.

  • StovePCShopCategory.categoryId : 카테고리 아이디
  • StovePCShopCategory.parentCategoryId : 부모 카테고리 아이디
  • StovePCShopCategory.displayNo : 카테고리 순서
  • StovePCShopCategory.name : 카테고리명
  • StovePCShopCategory.depth : 카테고리 깊이 (최상위 카테고리의 경우 1)
void OnFetchShopCategories(const int size, StovePCShopCategory* categories)
{
    printf("OnFetchShopCategories");
    printf("shopCategory size = %d", size);
    
    for (int i = 0; i < size; i++, categories++)
    {
        printf(" - categories[%d].categoryId : %s", i, categories->categoryId);
        printf(" - categories[%d].parentCategoryId : %s", i, categories->parentCategoryId);
        printf(" - categories[%d].displayNo: %d", i, categories->displayNo);
        wprintf(L" - categories[%d].name: %s", i, categories->name);
        printf(" - categories[%d].depth : %d", i, categories->depth);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

StovePC_FetchShopProducts 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
500 Internal Server Error
999999 정의되지 않은 오류

# 5) 상품 정보 얻기

StovePC_FetchProducts 함수로 해당 게임에 대한 상품 정보를 조회합니다.

// 입력 파라미터
// char* categoryId : 파트너스에서 등록한 카테고리 식별자(빈문자열 전달시 전체 카테고리 조회)
// bool isRefresh : true 인 경우 Web API 조회, false 인 경우 PC SDK 의 Cache 조회
StovePCResult result = StovePC_FetchProducts("CATEGORY_ID", IS_REFRESH);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5
6
7
8

StovePC_FetchProducts 함수가 정상적으로 처리되면 OnFetchProducts 콜백이 호출됩니다.
콜백에 전달되는 StovePCProduct 구조체에는 상품에 대한 메타정보가 포함되어 있습니다.

  • StovePCProduct.productId : 상품 아이디
  • StovePCProduct.gameItemId : 상품 아이디에 매핑되는 게임 내 아이템 아이디
  • StovePCProduct.name : 상품명
  • StovePCProduct.description : 상품 설명
  • StovePCProduct.quantity : 개별 상품 수량
  • StovePCProduct.productTypeCode : 상품 유형 코드 (1: 패키지 게임 상품, 2: 인 게임 상품, 3: 패키지 아이템)
  • StovePCProduct.categoryId : 카테고리 아이디
  • StovePCProduct.currencyCode : 통화 코드
  • StovePCProduct.price : 상품 정가 (표기시에는 currencyCode 가 "KRW" 와 같으면 소수점 이하 생략 표기, 다르면 소수점 둘째자리까지 표기)
  • StovePCProduct.salePrice : 상품 판매가 (표기시에는 currencyCode 가 "KRW" 와 같으면 소수점 이하 생략 표기, 다르면 소수점 둘째자리까지 표기)
  • StovePCProduct.isDiscount : 할인 여부
  • StovePCProduct.discountType : 할인 유형(1: 정률, 2: 정액)
  • StovePCProduct.discountTypeValue : 할인값
  • StovePCProduct.discountBeginDate : 할인 시작 일자(UTC+0)
  • StovePCProduct.discountEndDate : 할인 종료 일자(UTC+0)
  • StovePCProduct.totalQuantity : 상품 총 판매 수량
  • StovePCProduct.memberQuantity : 회원 구매 수량
  • StovePCProduct.guidQuantity : Guid 구매 수량(상품 구매 주체[CharacterNo/Guid/MemberNo]의 구매 수량)
  • StovePCProduct.thumbnailUrl : 대표 상품 이미지
void OnFetchProducts(const int size, StovePCProduct* products)
{
    printf("OnFetchProducts");
    printf("product size = %d", size);
    
    for (int i = 0; i < size; i++, products++)
    {
       printf(" - products[%d].productId: %lld", i, products->productId);
        printf(" - products[%d].gameItemId: %s", i, products->gameItemId);
        wprintf(L" - products[%d].name: %s", i, products->name);
        wprintf(L" - products[%d].description: %s", i, products->description);
        printf(" - products[%d].quantity: %d", i, products->quantity);
        printf(" - products[%d].productTypeCode: %hd", i, products->productTypeCode);
        printf(" - products[%d].categoryId: %s", i, products->categoryId);
        printf(" - products[%d].currencyCode: %s", i, products->currencyCode);
        
        if( strcmp(products->currencyCode, "KRW") == 0)
        {
            printf(" - products[%d].price: %.0lf", i, products->price);
            printf(" - products[%d].salePrice: %.0lf", i, products->salePrice);
        }
        else
        {
             printf(" - products[%d].price: %.2lf", i, products->price);
             printf(" - products[%d].salePrice: %.2lf", i, products->salePrice);
        }
            
        printf(" - products[%d].isDiscount: %s", i, products->isDiscount ? "true" : "false");
        printf(" - products[%d].discountType: %hd", i, products->discountType);
        printf(" - products[%d].discountTypeValue: %d", i, products->discountTypeValue);
        printf(" - products[%d].discountBeginDate: %llu", i, products->discountBeginDate);
        printf(" - products[%d].discountEndDate: %llu", i, products->discountEndDate);
        printf(" - products[%d].totalQuantity: %d", i, products->totalQuantity);
        printf(" - products[%d].memberQuantity: %d", i, products->memberQuantity);
        printf(" - products[%d].thumbnailUrl: %s", i, products->thumbnailUrl);
    }
}
1
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

StovePC_FetchProducts 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
500 Internal Server Error
50001 상점이 존재하지 않거나, 점검 중
50002 상품이 존재 하지 않거나 판매 불가능 상품
999999 정의되지 않은 오류

# 6) 상품 구매 시작

StovePC_StartPurchase 함수로 상품 구매를 시작합니다.

// 입력 파라미터
// StovePCOrderProduct* products : 주문 상품 정보
// Size : 주문상품 갯수 


StovePCResult result = StovePC_StartPurchase(products, size);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5
6
7
8
9
10

StovePC_StartPurchase 함수가 정상적으로 처리되면 OnStartPurchase 콜백이 호출됩니다.
콜백에 전달되는 StovePCPurchase 구조체에는 상품 구매에 대한 메타정보가 포함되어 있습니다.

  • StovePCPurchase.transactionMasterNo : 거래 고유 마스터 번호
  • StovePCPurchase.tempPaymentUrl : 1회용 결제 URL
  • StovePCPurchase.purchaseProgress : 구매 진행 상태
    • 1 : 결제중 (TempPaymentUrl 을 이용하여 외부브라우저 표시 필요)
    • 2 : 구매 완료 (판매가격이 0 인 상품의 구매 진행으로 결제가 완료 상태로써 TempPaymentUrl 을 이용하여 외부브라우저 페이지 표시 불필요)

필요시 게임은 외부브라우저를 통해 1회용 결제 URL을 탐색합니다. 지원브라우저 : Chrome(75이상), Edge(42이상)

void OnStartPurchase(StovePCPurchase purchase)
{
    printf("OnStartPurchase");
    printf(" - transactionMasterNo : %lld", purchase.transactionMasterNo);
    printf(" - tempPaymentUrl : %s", purchase.tempPaymentUrl);
    printf(" - purchaseProgress : %d", purchase.purchaseProgress);
    
    if(purchase.purchaseProgress == 1)
    {
        // 외부 브라우저 열기
        ShellExecute( NULL, "open", purchase.tempPaymentUrl, NULL, NULL, SW_SHOWNORMAL);
    }
    else if(purchase.purchaseProgress == 2)
    {
        // 구매 완료 처리(e.g. 구매 완료 메세지 박스)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

StovePC_StartPurchase 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.
일반적으로 StovePC_StartPurchase 함수 호출에 대해 OnError 콜백이 호출되면 게임은 실패에 대한 메세지를 게임 사용자에게 노출합니다.
아래 표는 게임 사용자에게 표시 할 메세지에 대한 가이드를 함께 제시합니다.

ExternalError 설명 게임 사용자 대상 노출 메시지 확인
500 Internal Server Error 일시적인 현상이거나 네트워크 원인으로 서비스가 원활하지 않습니다.
50001 상점이 존재하지 않거나, 점검 중 서비스 점검 중이거나, 존재하지 않는 서비스 입니다.
50002 상품이 존재 하지 않거나 판매 불가능 상품 상품 상태로 인하여 구매하실 수 없는 상품입니다.
50003 비 전시 상품 현재 판매하고 있지 않은 상품입니다.
50004 판매 기간이 아닌 상품 상품 판매 기간이 아닙니다.
50005 상품 가격이 불일치(상품 가격이 변경 되었을 경우) 상품 가격 정보가 변경되었습니다.
50009 구매 가능 한 회원 별 판매 개수를 초과 1인 당 구매 가능 개수를 초과 하였습니다.
50010 구매 가능 한 총 판매 개수를 초과 준비 된 수량이 모두 판매 완료 되었습니다.
50031 구매 수량이 '0' 구매하실 수량을 1개 이상 입력해 주세요.
999999 정의되지 않은 오류 기타 오류로 서비스가 원활하지 않습니다.

# 7) 상품 구매 상태 확인

StovePC_ConfirmPurchase 함수로 상품 구매 상태를 확인합니다.

// 입력 파라미터
// int64 transactionMasterNo : 거래 고유 마스터 번호(OnStartPurchase 콜백 파라미터 StovePCPurchase.transactionMasterNo를 통해 취득)
StovePCResult result = StovePC_ConfirmPurchase(TRANSACTION_MASTER_NO);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    // 성공 처리
}
1
2
3
4
5
6
7

StovePC_ConfirmPurchase 함수가 정상적으로 처리되면 OnConfirmPurchase 콜백이 호출됩니다.
콜백에 전달되는 StovePCPurchaseProduct 구조체에는 구매된 상품에 대한 메타정보가 포함되어 있고, status 콜백 파라미터는 상품 구매 상태를 전달합니다.

  • StovePCPurchaseProduct.totalQuantity : 상품 총 판매 수량
  • StovePCPurchaseProduct.memberQuantity : 회원 구매 수량
  • StovePCPurchaseProduct.guidQuantity : Guid 구매 수량(상품 구매 주체[CharacterNo/Guid/MemberNo]의 구매 수량)

별도의 게임서버가 없는 게임의 경우 구매 결과가 성공이라면 게임은 아이템을 지급할 수도 있습니다.
게임서버가 있는 게임의 경우 게임서버가 구매에 대한 알림을 받을 수 있고 이때 아이템을 지급할 수도 있습니다.

void OnConfirmPurchase(const int size, StovePCPurchaseProduct* purchaseProducts, bool status, char* shopKey)
{
    printf("OnConfirmPurchase");
    printf(" - status : %s", status ? "true":"false");
    printf(" - shopKey: %s", shopKey);
    
    printf(" - puchaseProduct size = %d", size);
    for (int i = 0; i < size; i++, purchaseProducts++)
  {
        printf(" - purchaseProducts[%d].productId: %lld", i, purchaseProducts->productId);
        printf(" - purchaseProducts[%d].categoryId: %s", i, purchaseProducts->categoryId);
        printf(" - purchaseProducts[%d].totalQuantity: %d", i, purchaseProducts->totalQuantity);
        printf(" - purchaseProducts[%d].memberQuantity: %d", i, purchaseProducts->memberQuantity);
        printf(" - purchaseProducts[%d].guidQuantity: %d", i, purchaseProducts->guidQuantity);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

TIP

위 샘플코드에서 함수에서 string shopKeyStovePC_IAPInit 함수로 호출하는 YOUR_SHOP_KEY와 동일한 값입니다.

shopKey를 입력 파라메터로 YOUR_SHOP_KEY를 보내야 합니다.

StovePC_ConfirmPurchase 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
500 Internal Server Error
999999 정의되지 않은 오류

# 8) 상품 구매 이력 검증

StovePC_VerifyPurchase 함수로 상품 구매 이력를 검증합니다. 1회 이상 구매 이력이 있는 상품의 경우 IsPurchased 필드 값은 true 입니다.
상품 구매 이력 검증은 PC SDK 내의 캐시를 대상으로 수행됩니다. 이때 categoryId 파라미터의 값을 명시적으로 입력하면 해당 카테고리만을 대상으로 검색하고
categoryId 파라미터의 값에 빈문자열("")을 입력하면 전체 카테고리를 대상으로 검색을 진행합니다.
따라서 검색할 카테고리 아이디를 정확히 입력하는 편이 검색 속도면에서 유리할 수 있습니다.

// 입력 파라미터
// char* categoryId : 상품을 검색할 카테고리 아이디
// int64 productId : 상품 아이디
StovePCPurchaseVerification purchaseVerification = StovePC_VerifyPurchase("CATEGORY_ID", PRODUCT_ID);
if (purchaseVerification.result == StovePCResult::STOVE_PC_NO_ERROR)
{
    printf("VerifyPurchase Success");
    printf(" - purchaseVerification.isPurchased : %s", purchaseVerification.isPurchased ? "true" : "false");
}
else
{
    // 실패 처리
}
1
2
3
4
5
6
7
8
9
10
11
12
13

StovePC_VerifyPurchase 함수는 StovePCPurchaseVerification 구조체를 리턴합니다.
리턴되는 StovePCPurchaseVerification 구조체에는 상품 구매 이력 여부가 포함되어 있습니다.
또한, 함수 호출에 대한 에러코드도 포함되어 있습니다.

# 9) 보관함 조회

StovePC_FetchInventory 함수로 보관함을 조회합니다. 보관함에는 구매가 완료된 상품들이 보관되어 있습니다.
보관함의 구매 완료 상품 리스트를 이용하여 상품 지급 처리를 할 수 있습니다.
보통 게임은 StovePC_ConfirmPurchase 함수를 호출하여 상품 구매 상태를 확인 후 즉시 상품을 지급하지만
오류, 게임 재설치 등의 사유로 지급된 상품 정보가 소실 되었을 경우 보관함 정보를 이용하여 복구 작업에 활용이 가능합니다.

StovePCResult result = StovePC_FetchInventory();
if(result == StovePCResult.NoError)
{
    // 성공 처리
}
1
2
3
4
5

StovePC_FetchInventory 함수가 정상적으로 처리되면 OnFetchInventory 콜백이 호출됩니다.
콜백에 전달되는 StovePCInventoryItem 구조체에는 구매된 상품에 대한 메타정보가 포함되어 있습니다.

  • StovePCInventoryItem.transactionMasterNo : 거래 고유 마스터 번호
  • StovePCInventoryItem.transactionDetailNo : 거래 고유 상세 번호
  • StovePCInventoryItem.productId : 상품 아이디
  • StovePCInventoryItem.gameItemId : 상품 아이디에 매핑되는 게임 내 아이템 아이디
  • StovePCInventoryItem.productName : 상품명
  • StovePCInventoryItem.quantity : 개별 상품 수량
  • StovePCInventoryItem.thumbnailUrl : 대표 상품 이미지
void OnFetchInventory(const int size, StovePCInventoryItem* inventoryItems)
{
    printf("OnFetchInventory");
    printf(" - inventoryItem size = %d", size);
    for (int i = 0; i < size; i++, inventoryItems++)
    {
        printf(" - inventoryItems[%d].transactionMasterNo: %lld", i, inventoryItems->transactionMasterNo);
        printf(" - inventoryItems[%d].transactionDetailNo: %lld", i, inventoryItems->transactionDetailNo);
        printf(" - inventoryItems[%d].productId: %lld", i, inventoryItems->productId);
        printf(" - inventoryItems[%d].gameItemId: %s", i, inventoryItems->gameItemId);
        wprintf(" - inventoryItems[%d].productName: %s", i, inventoryItems->productName);
        printf(" - inventoryItems[%d].quantity: %d", i, inventoryItems->quantity);
        printf(" - inventoryItems[%d].thumbnailUrl: %s", i, inventoryItems->thumbnailUrl);
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

StovePC_FetchInventory 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.
StovePCError 구조체의 ExternalError 필드를 통해 외부 오류를 확인할 수 있습니다.

ExternalError 설명
500 Internal Server Error
999999 정의되지 않은 오류

# 부가서비스 연동하기

PC SDK는 부가서비스를 게임에 통합할 수 있도록 API를 제공합니다.
PC SDK가 지원하는 부가서비스로는 사용자정의 이벤트 로그, PC SDK 버전 조회, 과몰입방지 알림, 셧다운 알림, 추적 단서 조회가 있습니다.
게임은 게임내 사용자정의 이벤트(게임 로그)를 스토브 플랫폼으로 전송할 수 있습니다. 또한 게임은 현재 사용중인 PC SDK의 유의적 버전을 조회할 수 있습니다.
PC SDK의 유의적 버전 조회는 콜백이 아닌 리턴값으로 획득이 가능합니다.
과몰입방지 알림은 매시간 게임 과몰입에 대한 경고 문구를 콜백을 통해 전달합니다.
셧다운 알림은 만 18세 미만의 청소년이 부모에 의해 요일별 특정시간에 게임을 이용 할 수 없도록 제한을 하는 시스템으로써 요건이 충족되면 최대 4회에 걸쳐 알림을 콜백을 통해 전달합니다.

# 1) Callback 설정

부가서비스 API를 사용하여 PC SDK와 커뮤니케이션 하기 위하여, 게임에서는 아래 StovePCCallback 구조체의 콜백 포인터에 연결할 콜백함수를 정의해야 합니다.

struct StovePCCallback
{
    void(*OnError)(const StovePCError error);
    void(*OnInitComplete)();
    void(*OnToken)(const StovePCToken token);
    void(*OnUser)(const StovePCUser user);
    void(*OnOwnership)(int size, StovePCOwnership* ownership);
  
    void(*OnAutoPopup)(int size, StovePCAutoPopup* autoPopup, int headerSize, StovePCPopupRequestHeader* header);
    void(*OnManualPopup)(int size, StovePCManualPopup* manualPopup, int headerSize, StovePCPopupRequestHeader* header);
    void(*OnNewsPopup)(StovePCNewsPopup newsPopup, int headerSize, StovePCPopupRequestHeader* header);
    void(*OnCouponPopup)(StovePCCouponPopup couponPopup, int headerSize, StovePCPopupRequestHeader* header);
    void(*OnCommunityPopup)(StovePCCommunityPopup communityPopup, int cookieSize, StovePCPopupRequestCookie* cookie);
 
    // StashCustomEvent 처리가 완료됐을 때 호출되는 콜백
    void(*OnStashCustomEvent)(const StovePCCustomEvent customEvent, int parameterSize, StovePCCustomEventParameter* parameter);

    // ADD 2.6.0 Start
    // 과몰입방지를 위해 매시간 호출되는 콜백
    void(*OnOverImmersion)(const StovePCOverImmersion overImmersion);

    // 셧다운 제한시 호출되는 콜백
    void(*OnShutdown)(const StovePCShutdown shutdown);
    // 2.6.0 End

};
1
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

연동하기 2) Config, Callback 설정에서와 같이 StovePCCallback 구조체의 콜백 포인터에 콜백함수를 연결합니다.

// StovePCCallback 구조체 instance 생성
StovePCCallback callback;
 
// 모든 함수 포인터를 NULL로 초기화
memset(&callback, 0, sizeof(StovePCCallback));
 
// 구현한 함수 포인터를 연결
callback.OnError = OnMyErrorCallback; /*전역에서 정의한 콜백함수*/
callback.OnInitComplete = OnMyInitCompleteCallback; /*전역에서 정의한 콜백함수*/
callback.OnToken = OnMyTokenCallback; /*전역에서 정의한 콜백함수*/
callback.OnUser = OnMyUserInfoCallback; /*전역에서 정의한 콜백함수*/
callback.OnOwnership = OnMyOwnershipCallback; /*전역에서 정의한 콜백함수*/
  
// 팝업
callback.OnAutoPopup = OnMyAutoPopup; /*전역에서 정의한 콜백함수*/
callback.OnManualPopup = OnMyManualPopup; /*전역에서 정의한 콜백함수*/
callback.OnNewsPopup = OnMyNewsPopup; /*전역에서 정의한 콜백함수*/
callback.OnCouponPopup = OnMyCouponPopup; /*전역에서 정의한 콜백함수*/
callback.OnCommunityPopup = OnMyCommunityPopup; /*전역에서 정의한 콜백함수*/
 
// 부가서비스
callback.OnStashCustomEvent = OnMyStashCustomEvent; /*전역에서 정의한 콜백함수*/
// ADD 2.6.0 Start
callback.OnOverImmersion = OnMyOverImmersion; /*전역에서 정의한 콜백함수*/
callback.OnShutdown = OnMyShutdown; /*전역에서 정의한 콜백함수*/
// 2.6.0 End
1
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

OnStashCustomEvent 콜백을 반드시 구현할 필요는 없습니다.게임에서 사용자정의 이벤트 로그 기능을 사용할 경우만 연결하면 됩니다.

경고

OnOverImmersion 콜백은 법률에 의거 게임과몰입/중독 예방조치가 필요한 경우 반드시 구현하여야 합니다.
OnShutdown 콜백은 법률에 의거 선택적 셧다운이 필요한 경우 반드시 구현하여야 합니다.

# 2) 사용자정의 이벤트 로깅

StovePC_StashCustomEvent 함수로 사용자정의 이벤트(게임 로그)를 로깅합니다.

// 입력 파라미터
// const char* name: 이벤트명
// const char* category1 : 1차 카테고리명
// const char* category2 : 2차 카테고리명
// const float simpleValue : 간단한 값
// const StovePCCustomEventParameter* params : 세부적인 파라미터 정보
// const int paramsSize : 세부적인 파라미터 정보 개수
StovePCResult result = StovePC_StashCustomEvent("EVENT_NAME", "CATEGORY1", "CATEGORY2", 1.0f, params, PARAMS_SIZE);
if(result == StovePCResult::STOVE_PC_NO_ERROR)
{
    /* 성공 처리 */
}
1
2
3
4
5
6
7
8
9
10
11
12

StovePC_StashCustomEvent 함수가 정상적으로 처리되면 OnStashCustomEvent 콜백이 호출됩니다.
콜백에 전달되는 StovePCCustomEvent 구조체에는 API 호출시 전달한 이벤트명, 1차 카테고리명, 2차 카테고리명, 간단한 값이 포함되어 있습니다.
콜백에 전달되는 StovePCCustomEventParameter 구조체에는 API 호출시 전달한 파라미터 정보가 포함되어 있습니다.

void OnStashCustomEvent(const StovePCCustomEvent customEvent, int parameterSize, StovePCCustomEventParameter* parameter)
{
    // 모든 사용자정의 이벤트 정보 출력
    printf("OnStashCustomEvent");
    printf(" - customEvent.name : %s", customEvent.name);
    printf(" - customEvent.category1 : %s", customEvent.category1);
    printf(" - customEvent.category2: %s", customEvent.category2);
    printf(" - customEvent.simpleValue: %f", customEvent.simpleValue);
 
    printf(" - parameter size : %d", parameterSize);
 
    for (int i = 0; i < parameterSize; i++, parameter++)
    {
        printf(" - parameter[%d].name : %s", i, parameter->name);
        printf(" - parameter[%d].value : %s", i, parameter->value);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

주의사항

콜백파라미터 StovePCCustomEvent/StovePCCustomEventParameter 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCCustomEvent/StovePCCustomEventParameter 구조체의 정보를 사용하기 위해 저장이 필요한 경우 반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고,
사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

StovePC_StashCustomEvent 함수가 실행중에 오류가 발생하면 OnError 콜백이 호출됩니다.

# 3) PC SDK 유의적 버전 얻기

StovePC_GetSDKVersion 함수로 현재 연동중인 PC SDK의 버전 정보를 조회합니다.

char* version = StovePC_GetSDKVersion();
if(0 != strcmp(version, ""))
{
    /* 성공 처리 */
}
1
2
3
4
5

# 4) 게임 과몰입방지 2.6.0

게임을 시작한 후 매시간마다 OnOverImmersion 콜백이 호출됩니다.
콜백에 전달되는 StovePCOverImmersion 구조체에는 메세지, 게임이용 경과시간, 메세지 최소 노출시간(초)이 포함되어 있습니다.

  • StovePCOverImmersion.message : 과몰입 메세지
  • StovePCOverImmersion.elapsedTimeInHours : 경과 시간
  • StovePCOverImmersion.minExposureTimeInSeconds : 메세지 최소 노출 시간(초단위)

메세지는 PC SDK에 설정된 언어를 기반으로 번역된 메세지가 전달 됩니다.

void OnOverImmersion(const StovePCOverImmersion overImmersion)
{
    // 과몰입방지 정보 출력
    printf("OnOverImmersion");
    wprintf(L" - overImmersion.message : %s", overImmersion.message);
    printf(" - overImmersion.elapsedTimeInHours: %d", overImmersion.elapsedTimeInHours);
    printf(" - overImmersion.minExposureTimeInSeconds: %d", overImmersion.minExposureTimeInSeconds);
}
1
2
3
4
5
6
7
8

주의사항

콜백파라미터 StovePCOverImmersion 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCOverImmersion 구조체의 정보를 사용하기 위해 저장이 필요한 경우
반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

과몰입 메시지 안내

과몰입 메시지 : 게임을 플레이한 지 1 시간이 지났습니다. 과도한 게임이용은 정상적인 일상생활에 지장을 줄 수 있습니다.

# 5) 셧다운 2.6.0

게임을 시작한 후 선택적 셧다운 대상자에 한해 셧다운 시스템에 등록된 타임테이블에 의거하여 OnShutdown 콜백이 호출됩니다.
OnShutdown 콜백은 최대 4회 호출 될 수 있으며 호출되는 시점 및 게임에서 조치해야 하는 사항은 아래와 같습니다.

  • PCSDK 초기화 성공 후 셧다운 이벤트
    • 10분전 셧다운 알림 : 10분뒤 로그아웃 된다는 알림만 표시
    • 5분전 셧다운 알림 : 5분뒤 로그아웃 된다는 알림만 표시
    • 1분전 셧다운 알림 : 1분뒤 로그아웃 된다는 알림만 표시
    • 셧다운 알림 : 로그아웃 된다는 알림을 표시하고 사용자 확인시 즉시 게임 종료

콜백에 전달되는 StovePCShutdown 구조체에는 셧다운까지 남은 시간, 메세지, 메세지 노출시간(초)이 포함되어 있습니다.

  • StovePCShutdown.inadvanceTimeInMinutes : 사용자의 셧다운까지 남은 시간(분)으로써 0 인 경우 즉시 게임 종료
  • StovePCShutdown.message : 셧다운 알림 메세지
  • StovePCShutdown.exposureTimeInSeconds : 메세지 노출 시간(초)
void OnShutdown(const StovePCShutdown shutdown)
{
    // 셧다운 정보 출력
    printf("OnShutdown");
    printf(" - shutdown.inadvanceTimeInMinutes: %d", shutdown.inadvanceTimeInMinutes);
    wprintf(L" - shutdown.message : %s", shutdown.message);
    printf(" - shutdown.exposureTimeInSeconds: %d", shutdown.exposureTimeInSeconds);
}
1
2
3
4
5
6
7
8

주의사항

콜백파라미터 StovePCShutdown 구조체의 유효한 범위는 콜백함수 스코프로 한정됩니다.
PC SDK는 콜백함수 실행이 완료되는 즉시 내부에서 할당한 메모리를 해제합니다.
따라서 콜백함수 스코프 밖에서 StovePCShutdown 구조체의 정보를 사용하기 위해 저장이 필요한 경우
반드시 깊은복사(Deep Copy)를 통해 사본을 생성하고, 사본에 대한 사용이 완료되면 메모리를 해제하여야 합니다.

셧다운 메시지 안내

10분 : 회원님은 게임 시간 선택제 적용 대상으로 10 분 후 게임 이용이 제한됩니다.
5분 : 회원님은 게임 시간 선택제 적용 대상으로 5 분 후 게임 이용이 제한됩니다.
1분 : 회원님은 게임 시간 선택제 적용 대상으로 1 분 후 게임 이용이 제한됩니다.
0분 : 회원님은 게임 시간 선택제 적용 대상으로 게임 이용이 제한되어 게임을 종료합니다.

# 6) 추적 단서 조회 2.6.0

StovePC.GetTraceHint 함수로 스토브 플랫폼 로그를 추적 하기 위한 일련의 단서를 조회합니다.

StovePCTraceHint traceHint = StovePC_GetTraceHint();
if (traceHint.result == StovePCResult::STOVE_PC_NO_ERROR)
{
    printf("GetTraceHint");
    printf(" - traceHint.sessionId : %s", traceHint.sessionId);
    printf(" - traceHint.refSessionId : %s", traceHint.refSessionId);
    printf(" - traceHint.uuid : %s", traceHint.uuid);
    printf(" - traceHint.serviceProtocol : %s", traceHint.serviceProtocol);
    printf(" - traceHint.refResourceType : %s", traceHint.refResourceType);
}
else
{
    /* 실패 처리 */
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

StovePC_GetTraceHint 함수는 StovePCTraceHint 구조체를 리턴합니다.
리턴되는 StovePCTraceHint 구조체에는 세션 아이디 및 레퍼런스 세션 아이디 등이 포함되어 있습니다.
또한, 함수 호출에 대한 에러코드도 포함되어 있습니다.

Last Updated: 2024. 7. 10. 오전 2:07:53