GS2-SerialKey SDK for Game Engine API 레퍼런스
모델
EzSerialKey
시리얼 코드
발급된 시리얼 코드는 한 번만 사용할 수 있습니다.
시리얼 코드는 “RPCLP-FP7N-NCDMJ-FLVA-IRI4"와 같은 형식으로 발급되며 데이터 길이는 변경할 수 없습니다.
시리얼 코드 내에는 캠페인 종류에 대한 정보도 포함되어 있으며, 시리얼 코드를 사용할 때는 네임스페이스만 지정하면 사용할 수 있습니다.
| 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| campaignModelName | string | ✓ | ~ 128자 | 캠페인 이름 이 시리얼 코드가 속한 캠페인 모델의 이름입니다. 캠페인 정보는 시리얼 코드 자체에 포함되어 있으므로 코드를 사용할 때는 네임스페이스만 지정하면 됩니다. | ||||||||||
| metadata | string | ~ 2048자 | 메타데이터 메타데이터에는 임의의 값을 설정할 수 있습니다. 이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. | |||||||||||
| code | string | ✓ | ~ 48자 | 시리얼 코드 “XXXXX-XXXX-XXXXX-XXXX-XXXX” 형식의 시리얼 코드 문자열입니다. 각 코드는 고유하며 캠페인 식별 정보를 포함합니다. 코드의 형식과 데이터 길이는 고정되어 있어 변경할 수 없습니다. | ||||||||||
| status | 문자열 열거형 enum { “ACTIVE”, “USED”, “INACTIVE” } | “ACTIVE” | 상태 이 시리얼 코드의 현재 사용 상태입니다. 사용자가 소비하면 ACTIVE에서 USED로 전환됩니다. 이중 사용을 방지하기 위해 낙관적 잠금(optimistic locking)으로 보호됩니다. INACTIVE 상태의 코드는 사용할 수 없습니다.
|
EzCampaignModel
캠페인 모델
캠페인 모델은 캠페인을 정의하고 시리얼 코드와 연결하여 관리하는 데 사용됩니다.
| 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 | |
|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128자 | 캠페인 모델 이름 | ||
| metadata | string | ~ 2048자 | 메타데이터 메타데이터에는 임의의 값을 설정할 수 있습니다. 이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다. | |||
| enableCampaignCode | bool | false | 캠페인 코드에 의한 교환을 허용할지 여부 활성화하면 개별 시리얼 코드가 아닌 공통 캠페인 코드(캠페인 이름)를 사용하여 보상을 교환할 수 있게 됩니다. 이를 통해 하나의 코드를 여러 사용자가 사용할 수 있습니다. |
메서드
getCampaignModel
특정 시리얼 코드 캠페인의 상세 정보 조회
캠페인 이름을 지정하여 설정을 포함한 상세 정보를 조회합니다.
캠페인 모델은 동일한 목적과 설정을 공유하는 시리얼 코드의 그룹을 정의합니다.
예를 들어 “출시 기념 코드”, “잡지 프로모션 코드”, “이벤트 배포 코드” 등을 각각 별도의 캠페인으로 관리할 수 있습니다.
응답에는 다음이 포함됩니다:
- 캠페인 이름과 메타데이터
- 캠페인이 현재 활성화되어 코드 교환을 허용하고 있는지 여부
코드 입력 화면을 표시하기 전에 캠페인의 상세 정보를 확인할 때 사용합니다. 예를 들어 플레이어에게 시리얼 코드를 입력하게 하기 전에 캠페인이 활성화되어 있는지 확인할 수 있습니다.
Request
| 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128자 | 네임스페이스 이름 네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. | ||
| campaignModelName | string | ✓ | ~ 128자 | 캠페인 모델 이름 |
Result
| 타입 | 설명 | |
|---|---|---|
| item | EzCampaignModel | 캠페인 모델 |
구현 예제
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "campaign-0001"
);
var item = await domain.ModelAsync(); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "campaign-0001"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->CampaignModel(
"campaign-0001" // campaignModelName
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}var domain = ez.serial_key.namespace_(
"namespace-0001"
).campaign_model(
"campaign-0001"
)
var async_result = await domain.model()
if async_result.error != null:
push_error(str(async_result.error))
return
var result = async_result.result값 변경 이벤트 핸들링
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "campaign-0001"
);
// 이벤트 핸들링 시작
var callbackId = domain.Subscribe(
value => {
// 값이 변화했을 때 호출됨
// value에는 변경 후의 값이 전달됨
}
);
// 이벤트 핸들링 정지
domain.Unsubscribe(callbackId); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).CampaignModel(
campaignModelName: "campaign-0001"
);
// 이벤트 핸들링 시작
var callbackId = domain.Subscribe(
value => {
// 값이 변화했을 때 호출됨
// value에는 변경 후의 값이 전달됨
}
);
// 이벤트 핸들링 정지
domain.Unsubscribe(callbackId); const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->CampaignModel(
"campaign-0001" // campaignModelName
);
// 이벤트 핸들링 시작
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::SerialKey::Model::FCampaignModel> value) {
// 값이 변화했을 때 호출됨
// value에는 변경 후의 값이 전달됨
}
);
// 이벤트 핸들링 정지
Domain->Unsubscribe(CallbackId);var domain = ez.serial_key.namespace_(
"namespace-0001"
).campaign_model(
"campaign-0001"
)
# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
# 값이 변화했을 때 호출됨
# value에는 변경 후의 값이 전달됩니다
pass
)
# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.
로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.
따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.
get
시리얼 코드의 상태 확인
특정 시리얼 코드의 상세 정보를 조회합니다. 사용 여부, 어떤 캠페인에 속하는지 등의 정보가 포함됩니다.
코드를 교환하기 전후에 상태를 확인할 때 사용합니다. 예를 들어:
- 플레이어가 이미 사용된 코드를 입력했을 때 “이 코드는 이미 사용되었습니다"라고 표시
- 플레이어가 교환을 확정하기 전에 캠페인 정보(코드로 얻을 수 있는 보상)를 표시
- 고객 지원 목적으로 코드를 조회
코드는 “XXXXX-XXXX-XXXXX-XXXX-XXXXX"와 같은 형식입니다.
응답에는 시리얼 코드의 상세 정보와 관련된 캠페인 모델이 포함됩니다.
Request
| 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128자 | 네임스페이스 이름 네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. | ||
| code | string | ✓ | ~ 48자 | 시리얼 코드 “XXXXX-XXXX-XXXXX-XXXX-XXXX” 형식의 시리얼 코드 문자열입니다. 각 코드는 고유하며 캠페인 식별 정보를 포함합니다. 코드의 형식과 데이터 길이는 고정되어 있어 변경할 수 없습니다. |
Result
| 타입 | 설명 | |
|---|---|---|
| item | EzSerialKey | 시리얼 코드 |
| campaignModel | EzCampaignModel | 캠페인 모델 |
구현 예제
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
var item = await domain.ModelAsync(); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
var future = domain.ModelFuture();
yield return future;
var item = future.Result; const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->User(
"user-0001" // userId
)->SerialKey(
"code-0001" // serialKeyCode
);
const auto Future = Domain->Model();
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
return false;
}var domain = ez.serial_key.namespace_(
"namespace-0001"
).user(
"user-0001"
).serial_key(
"code-0001"
)
var async_result = await domain.model()
if async_result.error != null:
push_error(str(async_result.error))
return
var result = async_result.result값 변경 이벤트 핸들링
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
// 이벤트 핸들링 시작
var callbackId = domain.Subscribe(
value => {
// 값이 변화했을 때 호출됨
// value에는 변경 후의 값이 전달됨
}
);
// 이벤트 핸들링 정지
domain.Unsubscribe(callbackId); var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).User(
userId: "user-0001"
).SerialKey(
serialKeyCode: "code-0001"
);
// 이벤트 핸들링 시작
var callbackId = domain.Subscribe(
value => {
// 값이 변화했을 때 호출됨
// value에는 변경 후의 값이 전달됨
}
);
// 이벤트 핸들링 정지
domain.Unsubscribe(callbackId); const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->User(
"user-0001" // userId
)->SerialKey(
"code-0001" // serialKeyCode
);
// 이벤트 핸들링 시작
const auto CallbackId = Domain->Subscribe(
[](TSharedPtr<Gs2::SerialKey::Model::FSerialKey> value) {
// 값이 변화했을 때 호출됨
// value에는 변경 후의 값이 전달됨
}
);
// 이벤트 핸들링 정지
Domain->Unsubscribe(CallbackId);var domain = ez.serial_key.namespace_(
"namespace-0001"
).user(
"user-0001"
).serial_key(
"code-0001"
)
# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
# 값이 변화했을 때 호출됨
# value에는 변경 후의 값이 전달됩니다
pass
)
# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.
로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.
따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.
useSerialCode
시리얼 코드 교환
시리얼 코드를 사용(소비)하여 현재 플레이어가 교환한 것으로 표시합니다.
한 번 사용된 코드는 누구도 다시 사용할 수 없습니다.
게임 내 “시리얼 코드 입력” 기능에서 사용하는 메인 API입니다. 일반적인 흐름은 다음과 같습니다:
- 플레이어가 게임 내 “코드 교환” 화면을 연다
- 플레이어가 시리얼 코드를 입력한다(프로모션 카드, 이메일, 웹사이트 등에서 얻은 것)
- 게임이 입력된 코드로 UseSerialCode를 호출한다
- 성공하면 코드가 사용됨 상태가 된다 — 보상 지급 시스템과 조합하여 플레이어에게 보상을 지급한다
- 코드가 이미 사용된 경우 “사용됨” 오류가 반환된다
- 코드가 존재하지 않는 경우 “코드를 찾을 수 없음” 오류가 반환된다
주요 사용 사례:
- 상품이나 잡지에 동봉되는 프로모션 코드
- 이벤트나 SNS를 통해 배포되는 기프트 코드
- 사전 등록 특전 코드
- 콜라보레이션 캠페인 코드
Request
| 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128자 | 네임스페이스 이름 네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. | ||
| gameSession | GameSession | ✓ | GameSession | |||
| code | string | ✓ | ~ 48자 | 시리얼 코드 “XXXXX-XXXX-XXXXX-XXXX-XXXX” 형식의 시리얼 코드 문자열입니다. 각 코드는 고유하며 캠페인 식별 정보를 포함합니다. 코드의 형식과 데이터 길이는 고정되어 있어 변경할 수 없습니다. |
Result
| 타입 | 설명 | |
|---|---|---|
| item | EzSerialKey | 시리얼 코드 |
| campaignModel | EzCampaignModel | 캠페인 모델 |
Error
이 API에는 특별한 예외가 정의되어 있습니다.
GS2-SDK for Game Engine에서는 게임 내에서 핸들링이 필요할 것으로 예상되는 에러를, 일반적인 예외에서 파생된 특수화된 예외로 제공하여 다루기 쉽게 하고 있습니다.
일반적인 에러의 종류와 핸들링 방법은 여기 문서를 참고해 주세요.
| 타입 | 베이스 클래스 | 설명 |
|---|---|---|
| AlreadyUsedException | BadRequestException | 지정된 시리얼 코드는 이미 사용되었습니다 |
| CodeNotFoundException | NotFoundException | 지정된 시리얼 코드는 존재하지 않습니다 |
구현 예제
try {
var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).SerialKey(
serialKeyCode: "code-0001"
);
var result = await domain.UseSerialCodeAsync(
code: "code-0001"
);
var item = await result.ModelAsync();
} catch(Gs2.Gs2SerialKey.Exception.AlreadyUsedException e) {
// The specified serial code has already been used.
} catch(Gs2.Gs2SerialKey.Exception.CodeNotFoundException e) {
// The specified serial code does not exist.
} var domain = gs2.SerialKey.Namespace(
namespaceName: "namespace-0001"
).Me(
gameSession: GameSession
).SerialKey(
serialKeyCode: "code-0001"
);
var future = domain.UseSerialCodeFuture(
code: "code-0001"
);
yield return future;
if (future.Error != null)
{
if (future.Error is Gs2.Gs2SerialKey.Exception.AlreadyUsedException)
{
// The specified serial code has already been used.
}
if (future.Error is Gs2.Gs2SerialKey.Exception.CodeNotFoundException)
{
// The specified serial code does not exist.
}
onError.Invoke(future.Error, null);
yield break;
}
var future2 = future.Result.ModelFuture();
yield return future2;
if (future2.Error != null)
{
onError.Invoke(future2.Error, null);
yield break;
}
var result = future2.Result; const auto Domain = Gs2->SerialKey->Namespace(
"namespace-0001" // namespaceName
)->Me(
GameSession
)->SerialKey(
"code-0001" // serialKeyCode
);
const auto Future = Domain->UseSerialCode(
"code-0001" // code
);
Future->StartSynchronousTask();
if (Future->GetTask().IsError())
{
auto e = Future->GetTask().Error();
if (e->IsChildOf(Gs2::SerialKey::Error::FAlreadyUsedError::Class))
{
// The specified serial code has already been used.
}
if (e->IsChildOf(Gs2::SerialKey::Error::FCodeNotFoundError::Class))
{
// The specified serial code does not exist.
}
return false;
}
// 변경된 값 / 결과 값을 취득
const auto Future2 = Future->GetTask().Result()->Model();
Future2->StartSynchronousTask();
if (Future2->GetTask().IsError())
{
return Future2->GetTask().Error();
}
const auto Result = Future2->GetTask().Result();var domain = ez.serial_key.namespace_(
"namespace-0001"
).me(game_session).serial_key(
"code-0001"
)
var async_result = await domain.use_serial_code(
"code-0001" # code
)
if async_result.error != null:
if async_result.error is Gs2SerialKeyAlreadyUsedException:
# 지정된 시리얼 코드는 이미 사용되었습니다
pass
if async_result.error is Gs2SerialKeyCodeNotFoundException:
# 지정된 시리얼 코드는 존재하지 않습니다
pass
push_error(str(async_result.error))
return
var result = async_result.result