유저 인게이지먼트(UE, 딥링크)
Hive 유저 인게이지먼트(User Engagement, UE) 모듈은 프로모션 목적에 따라 링크 클릭만으로 유저를 게임 내 특정 위치 또는 이벤트 페이지로 초대하거나, 보상을 바로 획득할 수 있도록 하는 쿠폰 딥링크 기능을 제공합니다.
Scheme URL을 통해 수행하고자 하는 작업을 Hive에서는 유저 인게이지먼트 액션이라고 합니다. 게임이 주어진 URL에 명시된 동작을 수행할 때, Hive는 유저 인게이지먼트 이벤트의 형태로 게임에 동작 수행 요청을 전달합니다.
유저 인게이지먼트(UE)란?¶
UE는 앱 내/외부에서 전달받은 요청을 수행시키는 서비스로 다음과 같은 기능을 수행합니다.
- 딥링크, 푸시를 통해 앱 외부에서 전달받은 scheme URL을 수행합니다.
- Interwork를 통해 앱 내부에서 전달받은 scheme URL을 수행합니다.
- Hive SDK v4.4.0 이후 버전부터는
- 앱 외부에서 UA를 통해 생성된 링크 혹은 QR Code를 통해 앱에 진입한 이력을 전송하여 보상지급을 요청합니다.
- Offerwall 등의 다른 Hive 기능을 통해 앱에 진입한 이력을 전송하여 보상지급을 요청합니다.(CPI 보상 지급 요청)
- CPI보상 등에 대해 처리하기 위해 게임 클라이언트는 `setEngagementReady()` 메서드를 반드시 호출하여 UE 기능의 실행 가능 시점을 Hive 모듈에 전달해야 합니다.
Hive가 사용하는 Scheme URL 표기법¶
Scheme URL은 유저 인게이지먼트 액션을 표현하는 형식으로, Scheme URL에 정의된 동작과 적용 대상을 명시하고 있습니다. Hive SDK에서 처리되는 Scheme URL은 URI(통합 자원 식별자)라는 표준 표기 방식을 따라 별도의 Hive 표기로 정의하며, 서비스 필드와 공통 필드로 구성됩니다.
- 표준 표기 : {scheme}://{host}/{path}?{query}
- Hive 표기 : {scheme}://{host}/{api}?{parameters}
Note
Hive 표기는 Hive SDK에서 처리되는 이벤트로서 공통 필드를 표준 표기의 /{path}?{query}
대신 /{api}?{parameters}
로 표현합니다. Hive 표기에 사용하는 {api} 목록은 공통 필드에서 확인하세요.
게임의 Scheme URL 사용¶
쿠폰 딥링크 목적 외의 프로모션을 위해 UE를 던전이나 우편함, 상점 등 게임 내 특정 위치로 이동해야 하는 경우 게임에서 {path}를 정의하여 Scheme URL을 제공해야 합니다. 이렇게 생성된 Scheme URL은 콘솔에서 랜딩 URL로 변환하여 유저에게 전달됩니다. 게임의 Scheme URL에 대한 자세한 내용은 Scheme URL의 host 값이 game일 경우 가이드를 참조하세요.
서비스 필드¶
Scheme URL의 서비스 필드는 {scheme}://{host}
부분으로, 딥링크가 Hive SDK에 전달되는 경로를 명시하며 scheme과 host로 구성됩니다.
scheme¶
URL이 앱으로 전달되는 경로는 세 가지가 있습니다.
Push
Scheme URL의 대상이 되는 게임 앱이 실행 중이든 아니든, URL 수신자는 Scheme URL이 내부적으로 포함된 푸시 메시지를 수신하게 됩니다. 수신자가 푸시 메시지를 누르면 Push Scheme URL이 Hive 클라이언트에게 전달되며, Hive 클라이언트가 URL을 처리합니다.
-
- 예: push://{host}/{path}?{query}
Deep Link
앱 바깥의 위치(SMS 메시지, 웹브라우저 등)의 URL을 터치한 경우 이 URL의 scheme 필드가 단말에 설치된 특정 앱의 APPID로 되어 있다면, 해당 앱이 실행되며 Hive SDK에게 URL이 전달된다. 해당 앱이 설치되어 있지 않은 경우에는 설치 페이지로 이동합니다.
-
- 예: com.com2us.example://{host}/{path}?{query}
Deep Link Scheme을 이용하였을 때, 게임의 설치 여부에 따라 유저 플로우가 달라집니다.
Interwork
앱 실행 중 Hive SDK의 Promotion 화면(배너, 공지사항 등)의 특정 링크 URL을 터치한 경우로 해당 URL의 scheme 필드가 "interwork" 라는 문자열로 되어 있다면, URL은 Hive SDK에게 전달됩니다.
-
- 예: interwork://{host}/{path}?{query}
host¶
host는 요청하는 동작의 처리 주체가 누구인지 명시합니다:
-
- game : 게임 클라이언트가 처리해야 하는 동작
- hive : Hive SDK가 처리해야 하는 동작
공통 필드¶
Scheme URL의 공통 필드는 /{api}/{parameters}
부분으로, 수행할 동작이 무엇인지 명시하면서 동작에 필요한 정보를 포함합니다: api는 URL을 통해 수행할 동작이 무엇인지 명시합니다. host에 따라 수행할 수 있는 동작은 다음과 같습니다.
Scheme URL의 host 값이 hive일 경우¶
게임에 적용하는 인증 버전(Auth v4 또는 Auth v1)에 따라 수행할 수 있는 API가 다르니 이 부분 주의하세요.
API | 수행 작업 | Auth v4 | Auth v1 |
authlogin auth/login | Hive 멤버십 로그인(게스트 -> 정식계정) | X | O |
socialinquiry social/inquiry | Hive 1:1 문의 화면 접속 | O | O |
promotionshow promotion/show | 프로모션 커스텀뷰 노출 | O | O |
promotioncoupon promotion/coupon | 프로모션 쿠폰 소모 처리 | O | O |
offerwallshow promotion/offerwall | 오퍼월 화면 노출 | O | O |
iappromote | 아이템 구매 예약 (Hive SDK v4.5.0 이상, Hive IAP v4에서 사용 가능) | O | O |
iappurchase | 스팟 배너에서 아이템 판매 (Hive SDK v4.5.0 이상, Hive IAP v4에서 사용 가능) iappurchase를 수행하면 `setEngagementReady` 메서드가 `false`상태로 자동 변경됩니다. 구매가 완료된 이후 `setEngagementReady()` 메서드를 `true`상태로 변경하세요. | O | O |
social/myinquiry | Hive 내 문의 내역 페이지 접속 | O | O |
social/profile | 프로필 페이지 접속 | O | O |
Hive는 UE 관련 동작을 수행하기 직전과 수행 직후 EngagementListener
를 통해 각각에 대한 통지를 받게 됩니다. 게임에서는 필요에 따라 게임 진행 일시 정지 등의 작업등이 필요할 수 있습니다.
Note
showCustomContents API를 활용하여 게임에서 직접 프로모션 UI를 구성하려면 interwork 동작을 직접 구현해야 합니다. showCustomContents API에 대한 안내는 개발 > HiveHive SDK v4 > 프로모션 > 부가 기능를 참고하세요.
iappromote, iappurchase에 관한 자세한 내용은 다음을 확인하세요.
iappromote
Hive SDK v4.5.0 이상, Hive IAP v4에서 제공하는 기능입니다. 게임을 시작하기 전에 아이템을 예약 구매할 수 있는 기능이며, iOS 11에서 제공하는 Promotional IAP 와 동일하지만 앱스토어에 국한하지 않는 것이 특징입니다. 이벤트 페이지나 푸시, 메시지 등 어디서나 활용할 수 있습니다.
- 앞에 언급한 이벤트 페이지나 푸시, 메시지 같이 앱 외부에서 Scheme URL을 클릭하면 게임을 실행한 후 아이템 구매 정보를 전달 받습니다.
- iappromote scheme을 호출하면
EngagementEventType.IAP_PROMOTE
를 결과값으로 받습니다. 결과값을 받은 후, checkPromotePurchase API를 호출해서 유저가 구매 예약한 마켓 PID를 획득합니다. 획득한 마켓 PID를 참고해서 purchase API를 실행하면 구매를 이어갈 수 있습니다. - iappromote는 iOS, Android 모두 사용 가능합니다.
- Scheme URL 구조: [AppID/push/interwork]://hive/iappromote?marketpid=[marketpid]
- 예시
- interwork://hive/iappromote?marketpid=com.com2us.hivesdk.normal.freefull.apple.global.ios.universal.cs02
- 위 Scheme URL에서 빨간색 부분을 예약 구매할 마켓 PID 값으로 변경해 사용합니다.
iappurchase
Hive SDK v4.5.0이상, Hive IAP v4에서 제공하는 기능입니다. Scheme URL에 iappurchase를 사용하면 스팟 배너에서 상품을 판매할 수 있습니다.
- iappurchase scheme을 호출하면 구매 로직이 진행됩니다. 따라서 scheme을 전달하기 전에 마켓을 초기화하고, 상점 정보를 획득해야 합니다. 다시 말해,
setEngagementReady()
메서드 상태를true
로 변경하기 전에 marketConnect API, getProductInfo API를 호출하도록 합니다. - 구매 이후 로직은 게임에서 처리하기 때문에 Engagement 동작이 일시정지합니다. (
setEngagementReady()
가false
로 자동 변경) - 구매가 완료되면
setEngagementReady()
를true
로 변경해서 Engagement 동작을 이어가세요. - Scheme URL 구조: [AppID/push/interwork]://hive/iappurchase?marketpid=[marketpid]
- 예시
- interwork://hive/iappurchase?marketpid=com.com2us.hivesdk.normal.freefull.apple.global.ios.universal.cs01
- 위 Scheme URL에서 빨간색 부분을 판매할 마켓 PID 값으로 변경해 사용합니다.
Sync iappurchase with Spot Banner
iappurchase를 활용해 상품을 판매하려면 스팟 배너를 이용해야 합니다. 스팟 배너 개발 가이드 바로가기
- 먼저 인게임 내 상품 구매를 유도할 위치나 타이밍에 스팟 배너 ID를 설정합니다.
- 스팟 배너 ID를 호출한 후 유저가 스팟 배너를 선택하면 interwork를 수행하고, 등록된 EngagementListener가 동작 수행 여부를 전달합니다.
- interwork scheme을 호출하면 구매 로직이 진행됩니다. 따라서 scheme을 전달하기 전에 마켓을 초기화하고, 상점 정보를 획득해야 합니다. 다시 말해, 스팟 배너를 호출하기 전에 marketConnect API, getProductInfo API를 호출하도록 합니다.
- interwork를 수행할 때, 구매 이후 로직은 게임에서 처리하기 때문에 Engagement 동작이 일시정지합니다. (
setEngagementReady()
가false
로 자동 변경) - 구매가 완료되면
setEngagementReady()
를true
로 변경해서 Engagement 동작을 이어가세요. - Hive 콘솔 > 프로모션 > 캠페인 설정 > 스팟 배너에 스팟 배너 ID를 입력한 후 내부 링크에 scheme URL을 삽입합니다. 스팟 배너 등록은 사업 PM에 문의하세요.
- 예시
- interwork://hive/iappurchase?marketpid=com.com2us.hivesdk.normal.freefull.apple.global.ios.universal.cs01
- 위 Scheme URL에서 빨간색 부분을 판매할 마켓 PID 값으로 변경해 사용합니다.
- Hive 콘솔에 등록이 완료되면 게임에서 구매 테스트를 진행합니다.
Scheme URL의 host 값이 game일 경우¶
이 경우에는 게임이 요청된 동작을 수행해야 합니다. Hive SDK는 Scheme URL을 처리한 후 EngagementListener를 통해 EngagementEventType.EVENT와 JSONObject 형태로 결과를 전달합니다. 결과값은 scheme
키와 api
키, param
키로 구분되어 있으며 게임은 필요한 시점에 관련 동작을 수행해야 합니다.
- 예시 : 포스트박스 아이템 지급
- URL Scheme : com.com2us.example://game/postboxadditem?item_id=123456&item_title=item01
- Hive SDK로 부터 받게 되는 JSONObject 결과 값
자세한 구현 방법은 구현하기 > 전역 콜백 선언 및 등록의 예제코드를 참조하세요.
프로젝트 설정¶
게임 앱에서 유저 인게이지먼트 기능을 이용하려면, 앱을 빌드하기 OS별로 설정이 필요합니다.
Android 설정¶
AndroidManifest.xml 파일 내 Main Activity 항목의 launchMode
속성 값을 singleTask
혹은 singleTop
으로 설정하세요.
//application
android:hardwareAccelerated="true"
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:isGame="true">
<activity
android:label="@string/app_name"
android:name="com.hive.sample.MainActivity"
android:screenOrientation="sensor"
android:launchMode="singleTask"
iOS 설정¶
- Xcode TARGETS 목록에서 빌드하고자 하는 앱 빌드를 선택하세요.
- Info 탭을 선택하세요.
- URL Types 섹션의 Additional url type properties 항목을 새로 추가하여, Bundle Identifier 필드와 URL Schemes 필드에 앱 ID를 입력하세요.
구현하기¶
전역 콜백 선언 및 등록¶
HiveHive UE를 적용하기 위해서는 전역 콜백을 선언하고 등록해야 하며 그 방법은 Hive SDK 버전에 따라 달라집니다.
Note
- Hive SDK v4.5.0부터 Promotion 클래스의 Handler를 등록하는 API를 통해 전역 콜백 선언 및 등록합니다.
- Hive SDK v4.5.0 이상부터 Engagement Handler 형태 및 enum값이 변경되었습니다.
Promotion 클래스의 Handler등록 API를 이용하여 전역 콜백을 등록해야 합니다. 다음은 예제 코드입니다.
API Reference: hive.Promotion.setEngagementListener
using hive;
Promotion.setEngagementListener((ResultAPI result, EngagementEventType engagementEventType, EngagementEventState engagementEventState, JSONObject param) => {
switch (engagementEventType) {
case EngagementEventType.EVENT_TYPE:
switch (engagementEventState) {
case EngagementEventState.BEGIN:
// All actions of Engagement are performed
break;
case EngagementEventState.FINISH:
// All actions of Engagement are completed
break;
}
break;
case EngagementEventType.AUTH_LOGIN_VIEW:
switch (engagementEventState) {
case EngagementEventState.START:
// Start Hive membership login page exposure request
break;
case EngagementEventState.END:
// Hive membership login completed (delivered after login completed/window closed)
break;
}
break;
case EngagementEventType.SOCIAL_INQUIRY_VIEW:
switch (engagementEventState) {
case EngagementEventState.START:
// Start 1:1 inquiry page exposure request
break;
case EngagementEventState.END:
// 1:1 inquiry page exposure completed (delivered after 1:1 inquiry window is closed)
break;
}
break;
case EngagementEventType.PROMOTION_VIEW:
switch (engagementEventState) {
case EngagementEventState.START:
// Start Promotion View impression request
break;
case EngagementEventState.END:
// Promotion View exposure completed (delivered after the Promotion window is closed)
break;
}
break;
caseEngagementEventType.COUPON:
switch (engagementEventState) {
case EngagementEventState.START:
// Start coupon consumption request
break;
case EngagementEventState.END:
// Complete coupon consumption request and send response
break;
}
break;
case EngagementEventType.OFFERWALL_VIEW:
switch (engagementEventState) {
case EngagementEventState.START:
// Start offer wall page exposure request
break;
case EngagementEventState.END:
// Completed offerwall page exposure (delivered after closing the offerwall window)
break;
}
break;
case EngagementEventType.EVENT:
// If the host is game, send the JSONObject result value
String api = "";
String param = "";
param.GetField(ref api, "api");
param.GetField(ref param, "param");
// Check api and param parsing results by Hive SDK version (differences depending on Hive SDK C# JSONObject version)
// ex) interwork://game/openurl?rurl=https://www.withhive.com
//Under Hive SDK 4.16.2
// When output to api debug console: \/openurl
// ( api.Equals("\\/openurl"); )
// param debug console output: rurl=https:\/\/www.withhive.com
// Hive SDK 4.16.2 or higher
// When output to api debug console: /openurl
// (api.Equals("/openurl"); )
// param debug console output: rurl=https://www.withhive.com
// TODO: Perform the following actions according to the api and param values
break;
case EngagementEventType.IAP_UPDATED:
switch (engagementEventState) {
case EngagementEventState.EVENT_START:
// Signal to accept as purchase history has changed (call Restore() method)
break;
case EngagementEventState.EVENT_END:
// Signal to accept as purchase history has changed (call Restore() method)
String type = "";
param.getField(ref type, "type");
if (type == "subscription") {
// TODO: restore subscription product
IAPV4.restoreSubscription((ResultAPI result, List <hive.IAPV4.IAPV4Receipt> receiptList) => {
if (!result.isSuccess()) {
return;
}
// TODO: Request receipt verification using the received receiptList
});
return;
}
// TODO: restore consumable goods
IAPV4.restore((ResultAPI result, List <hive.IAPV4.IAPV4Receipt> receiptList) => {
if (!result.isSuccess()) {
return;
}
// TODO: Request receipt verification using the received receiptList
});
break;
}
break;
case EngagementEventType.IAP_PROMOTE:
switch (engagementEventState) {
case EngagementEventState.START:
// Convey whether IAP Promote data exists
break;
case EngagementEventState.END:
if (!result.isSuccess()) {
return;
}
// Since IAP Promote data exists, marketPid is received through checkPromote API.
IAPV4.checkPromotePurchase((ResultAPI promoteResult, String marketPid) => {
if (!promoteResult.isSuccess()) {
return;
}
// TODO: Request purchase with the received marketPid item
IAPV4.purchase(marketPid, null, (ResultAPI purchaseResult, hive.IAPV4.IAPV4Receipt receipt) => {
if (!purchaseResult.isSuccess()) {
return;
}
// TODO: Request receipt verification with received receipt
});
});
break;
}
break;
case EngagementEventType.IAP_PURCHASE:
switch (engagementEventState) {
case EngagementEventState.START:
// A pop-up for purchasing items received through the IAPPurchase schema is displayed.
break;
case EngagementEventState.END:
// Whether or not the purchase of the requested item was successful is communicated through the IAPPurchase schema.
if (!result.isSuccess()) {
return;
}
String receipt = "";
param.GetField(ref receipt, "iapV4Receipt");
break;
}
break;
case EngagementEventType.SOCIAL_MY_INQUIRY:
switch (engagementEventState) {
case EngagementEventState.START:
// Start my inquiry page exposure request
break;
case EngagementEventState.END:
// My inquiry page has been exposed (delivered after the My Inquiry window is closed)
break;
}
break;
case EngagementEventType.SOCIAL_PROFILE:
switch (engagementEventState) {
case EngagementEventState.START:
// Initiate profile page exposure request
break;
case EngagementEventState.END:
// Profile page exposure completed (delivered after closing the profile window)
break;
}
break;
}
});
#include "HivePromotion.h"
FHivePromotion::SetEngagementDelegate(FHivePromotionOnEngagementDelegate::CreateLambda([this](const FHiveResultAPI& Result, const EHiveEngagementEventType& EngagementEventType, const EHiveEngagementEventState& EngagementEventState, TSharedPtr<FJsonObject> Param) {
switch (EngagementEventType) {
case EHiveEngagementEventType::EVENT_TYPE:
switch (EngagementEventState) {
case EHiveEngagementEventState::BEGIN:
// Engagement 의 모든 동작 수행됨
break;
case EHiveEngagementEventState::FINISH:
// Engagement 의 모든 동작 수행 완료됨
break;
}
break;
case EHiveEngagementEventType::AUTH_LOGIN_VIEW:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// Hive 멤버십 로그인 페이지 노출 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// Hive 멤버십 로그인 수행 완료 (로그인 완료/창닫음 수행 이후 전달)
break;
}
break;
case EHiveEngagementEventType::SOCIAL_INQUIRY_VIEW:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// 1:1 문의 페이지 노출 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// 1:1 문의 페이지 노출 완료 (1:1 문의 창 닫은 이후 전달)
break;
}
break;
case EHiveEngagementEventType::PROMOTION_VIEW:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// Promotion View 노출 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// Promotion View 노출 완료 (Promotion 창 닫은 이후 전달)
break;
}
break;
case EHiveEngagementEventType::COUPON:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// 쿠폰 소모 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// 쿠폰 소모 요청 완료 및 응답 전달
break;
}
break;
case EHiveEngagementEventType::OFFERWALL_VIEW:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// 오퍼월 페이지 노출 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// 오퍼월 페이지 노출 완료 (오퍼월 창 닫은 이후 전달)
break;
}
break;
case EHiveEngagementEventType::EVENT:
// host가 game인 경우, Param 결과값 전달 (Key: "api", "param")
// TODO: api, param 값에 따라 로직 처리 수행
break;
case EHiveEngagementEventType::IAP_UPDATED:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// 구매 내역이 변경되었으니 받아가라는 신호
break;
case EHiveEngagementEventState::EVENT_END:
// 구매 내역이 변경되었으니 받아가라는 신호
FString TypeValue;
if (Param.IsValid() && Param->TryGetStringField(TEXT("type"), TypeValue)) {
if (TypeValue == TEXT("subscription")) {
// TODO: 구독형 상품 Restore
} else {
// TODO: 소모성 상품 Restore
}
}
break;
}
break;
case EHiveEngagementEventType::IAP_PROMOTE:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// IAP Promote 데이터 존재 여부 전달
break;
case EHiveEngagementEventState::EVENT_END:
if (!Result.IsSuccess()) {
return;
}
// IAP Promote 데이터가 존재하므로 check Promote API를 통해 marketPid를 전달받음
FHiveIAPV4::CheckPromotePurchase(FHiveIAPV4OnCheckPromotePurchaseDelegate::CreateLambda([=](const FHiveResultAPI& PromoteResult, const FString& MarketPid) {
if (!PromoteResult.IsSuccess()) {
return;
}
// TODO: 전달받은 MarketPid로 아이템을 구매 요청
FString IapPayload = TEXT("");
FHiveIAPV4::Purchase(MarketPid, IapPayload, FHiveIAPV4OnPurchaseDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHiveIAPV4Receipt& Receipt) {
// TODO: 전달받은 Receipt 로 영수증 검증을 요청
}));
}));
break;
}
break;
case EHiveEngagementEventType::IAP_PURCHASE:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// IAPPurchase 스키마로 전달받은 아이템 구매 팝업 노출됨
break;
case EHiveEngagementEventState::EVENT_END:
// IAPPurchase 스키마를 통해 구매 요청한 아이템 구매 성공 여부가 전달됨
if (!Result.IsSuccess) {
return;
}
FString ReceiptValue;
if (Param.IsValid() && Param->TryGetStringField(TEXT("iapV4Receipt"), ReceiptValue)) {
// 구매 상품 영수증 전달
// TODO: 영수증 검증 및 아이템 지급처리
}
break;
}
break;
case EHiveEngagementEventType::SOCIAL_MY_INQUIRY:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// 내 문의 페이지 노출 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// 내 문의 페이지 노출 완료 (내 문의 창 닫은 이후 전달)
break;
}
break;
case EHiveEngagementEventType::SOCIAL_PROFILE:
switch (EngagementEventState) {
case EHiveEngagementEventState::EVENT_START:
// 프로필 페이지 노출 요청 시작
break;
case EHiveEngagementEventState::EVENT_END:
// 프로필 페이지 노출 완료 (프로필 창 닫은 이후 전달)
break;
}
break;
}
}));
API Reference: Promotion::setEngagementHandler
#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;
Promotion::setEngagementHandler([ = ](ResultAPI
const & result, EngagementEventType engagementEventType, EngagementEventState engagementEventState, picojson::value
const & param) {
switch (engagementEventType) {
case EngagementEventType::EVENT_TYPE:
switch (engagementEventState) {
case EngagementEventState::BEGIN:
// All actions of Engagement are performed
break;
case EngagementEventState::FINISH:
// All actions of Engagement are completed
break;
}
break;
case EngagementEventType::AUTH_LOGIN_VIEW:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Start Hive membership login page exposure request
break;
case EngagementEventState::EVENT_END:
// Hive membership login completed (delivered after login completed/window closed)
break;
}
break;
case EngagementEventType::SOCIAL_INQUIRY_VIEW:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Start 1:1 inquiry page exposure request
break;
case EngagementEventState::EVENT_END:
// 1:1 inquiry page exposure completed (delivered after 1:1 inquiry window is closed)
break;
}
break;
case EngagementEventType::PROMOTION_VIEW:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Start Promotion View impression request
break;
case EngagementEventState::EVENT_END:
// Promotion View exposure completed (delivered after the Promotion window is closed)
break;
}
break;
case EngagementEventType::COUPON:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Start coupon consumption request
break;
case EngagementEventState::EVENT_END:
// Complete coupon consumption request and send response
break;
}
break;
case EngagementEventType::OFFERWALL_VIEW:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Start offer wall page exposure request
break;
case EngagementEventState::EVENT_END:
// Completed offerwall page exposure (delivered after closing the offerwall window)
break;
}
break;
case EngagementEventType::EVENT:
// If the host is game, send the JSONObject result value
if (param == null) {
return;
}
string api = param.get("api").to_str();
string param = param.get("param").to_str();
// TODO: Perform the following actions according to the api and param values
break;
case EngagementEventType::IAP_UPDATED:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Signal to receive since purchase details have changed
break;
case EngagementEventState::EVENT_END:
// Signal to receive since purchase details have changed
string type = param.get("type").to_str();
if (type != null, type == "subscription") {
// TODO: restore subscription product
IAPV4::restoreSubscription([ = ](ResultApi
const & result, vector < reference_wrapper < IAPV4Receipt >> receiptList) {
if (!result.isSuccess()) {
return;
}
// TODO: Request receipt verification using the received receiptList
});
return;
}
// TODO: restore consumable goods
IAPV4::restore([ = ](ResultAPI
const & result, vector < reference_wrapper < IAPV4Receipt >> receiptList) {
if (!result.isSuccess()) {
return;
}
// TODO: Request receipt verification using the received receiptList
});
break;
}
break;
case EngagementEventType::IAP_PROMOTE:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Convey whether IAP Promote data exists
break;
case EngagementEventState::EVENT_END:
if (!result.isSuccess()) {
return;
}
// Since IAP Promote data exists, marketPid is received through check Promote API.
IAPV4::checkPromotePurchase([ = ](ResultApi
const & promoteResult, string marketPid) {
if (!promoteResult.isSuccess()) {
return;
}
// TODO: Request to purchase the delivered market Pid item
IAPV4::purchase(marketPid, "", [ = ](ResultApi
const & purchaseResult, IAPV4Receipt
const * receipt) {
if (!purchaseResult.isSuccess()) {
return;
}
// TODO: Request receipt verification with received receipt
});
});
break;
}
break;
case EngagementEventType::IAP_PURCHASE:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// A pop-up for purchasing items received through the IAPPurchase schema is displayed.
break;
case hive::EngagementEventState::EVENT_END:
// Whether or not the purchase of the requested item was successful is communicated through the IAPPurchase schema.
if (result.isSucces()) {
return;
}
picojson::value receiptJson = param.get("iapV4Receipt");
shared_ptr receipt = IAPV4Receipt::create(receiptJson);
break;
}
break;
case EngagementEventType::SOCIAL_MY_INQUIRY:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Start my inquiry page exposure request
break;
case EngagementEventState::EVENT_END:
// My inquiry page has been exposed (delivered after the My Inquiry window is closed)
break;
}
break;
case EngagementEventType::SOCIAL_PROFILE:
switch (engagementEventState) {
case EngagementEventState::EVENT_START:
// Initiate profile page exposure request
break;
case EngagementEventState::EVENT_END:
// Profile page exposure completed (delivered after closing the profile window)
break;
}
break;
}
});
API Reference: setEngagementListener
import com.hive.IAPV4
import com.hive.Promotion
import com.hive.ResultAPI
Promotion.setEngagementListener(object: Promotion.EngagementListener {
override fun onEngagement(
result: ResultAPI,
engagementEventType: Promotion.EngagementEventType,
engagementEventState: Promotion.EngagementEventState,
param: JSONObject ?
) {
// Code branched from Hive SDK depending on the type of intervention
when(engagementEventType) {
Promotion.EngagementEventType.EVENT_TYPE -> when(engagementEventState) {
Promotion.EngagementEventState.BEGIN -> {
// All actions of Engagement are performed
}
Promotion.EngagementEventState.FINISH -> {
// All actions of Engagement are completed
}
else -> {}
}
Promotion.EngagementEventType.AUTH_LOGIN_VIEW -> when(engagementEventState) {
Promotion.EngagementEventState.START -> {
// Start Hive membership login page exposure request
}
Promotion.EngagementEventState.END -> {
// Hive membership login completed (delivered after login completed/window closed)
}
else -> {}
}
Promotion.EngagementEventType.SOCIAL_INQUIRY_VIEW -> when(engagementEventState) {
Promotion.EngagementEventState.START -> {
// Start 1:1 inquiry page exposure request
}
Promotion.EngagementEventState.END -> {
// 1:1 inquiry page exposure completed (delivered after 1:1 inquiry window is closed)
}
else -> {}
}
Promotion.EngagementEventType.PROMOTION_VIEW -> when(engagementEventState) {
Promotion.EngagementEventState.START -> {
// Start Promotion View impression request
}
Promotion.EngagementEventState.END -> {
// Promotion View exposure completed (delivered after the Promotion window is closed)
}
else -> {}
}
Promotion.EngagementEventType.COUPON -> when(engagementEventState) {
Promotion.EngagementEventState.START -> {
// Start coupon consumption request
}
Promotion.EngagementEventState.END -> {
// Complete coupon consumption request and send response
}
else -> {}
}
Promotion.EngagementEventType.OFFERWALL_VIEW -> when(engagementEventState) {
Promotion.EngagementEventState.START -> {
// Start offer wall page exposure request
}
Promotion.EngagementEventState.END -> {
// Completed offerwall page exposure (delivered after closing the offerwall window)
}
else -> {}
}
Promotion.EngagementEventType.EVENT -> {
// If the host is game, send the JSONObject result value
if (param == null) {
return
}
val api = param.optString("api")
val param = param.optString("param")
// TODO: Perform the following actions according to the api and param values
}
Promotion.EngagementEventType.IAP_UPDATED -> when (engagementEventState) {
Promotion.EngagementEventState.START -> {
// Signal to accept as purchase history has changed (call Restore() method)
}
Promotion.EngagementEventState.END -> {
// Signal to accept as purchase history has changed (call Restore() method)
val iapUpdateType = param?.optString("type")
if (iapUpdateType == "subscription") {
// TODO: restore subscription product
IAPV4.restoreSubscription(object : IAPV4.IAPV4RestoreListener {
override fun onIAPV4Restore(
result: ResultAPI,
iapv4ReceiptList: ArrayList<IAPV4.IAPV4Receipt>?
) {
if (!result.isSuccess) {
return
}
// TODO: Request receipt verification using the received iapv4ReceiptList
}
})
} else {
IAPV4.restore(object : IAPV4.IAPV4RestoreListener {
override fun onIAPV4Restore(
result: ResultAPI,
iapv4ReceiptList: ArrayList<IAPV4.IAPV4Receipt>?
) {
if (!result.isSuccess) {
return
}
// TODO: Request receipt verification using the received iapv4ReceiptList
}
})
}
}
else -> {}
}
Promotion.EngagementEventType.IAP_PURCHASE -> when (engagementEventState) {
Promotion.EngagementEventState.START -> {
// A pop-up for purchasing items received through the IAPPurchase schema is displayed.
}
Promotion.EngagementEventState.END -> {
// Whether or not the purchase of the requested item was successful is communicated through the IAPPurchase schema.
if (!result.isSuccess) {
return
}
val iapV4Receipt = param?.optJSONObject("iapV4Receipt")
}
else -> {}
}
Promotion.EngagementEventType.SOCIAL_MYINQUIRY_VIEW -> when (engagementEventState) {
Promotion.EngagementEventState.START -> {
// Start my inquiry page exposure request
}
Promotion.EngagementEventState.END -> {
// My inquiry page has been exposed (delivered after the My Inquiry window is closed)
}
else -> {}
}
Promotion.EngagementEventType.SOCIAL_PROFILE_VIEW -> when (engagementEventState) {
Promotion.EngagementEventState.START -> {
// Initiate profile page exposure request
}
Promotion.EngagementEventState.END -> {
// Profile page exposure completed (delivered after closing the profile window)
}
else -> {}
}
else -> {}
}
}
})
API Reference: com.hive.Promotion.setEngagementListener
import com.hive.IAPV4;
import com.hive.Promotion;
import com.hive.ResultAPI;
Promotion.INSTANCE.setEngagementListener((result, engagementEventType, engagementEventState, param) -> {
switch (engagementEventType) {
case EVENT_TYPE:
switch (engagementEventState) {
case BEGIN:
// All actions of Engagement are performed
break;
case FINISH:
// All actions of Engagement are completed
break;
}
break;
case AUTH_LOGIN_VIEW:
switch (engagementEventState) {
case START:
// Start Hive membership login page exposure request
break;
case END:
// Hive membership login completed (delivered after login completed/window closed)
break;
}
break;
case SOCIAL_INQUIRY_VIEW:
switch (engagementEventState) {
case START:
// Start 1:1 inquiry page exposure request
break;
case END:
// 1:1 inquiry page exposure completed (delivered after 1:1 inquiry window is closed)
break;
}
break;
case PROMOTION_VIEW:
switch (engagementEventState) {
case START:
// Start Promotion View impression request
break;
case END:
// Promotion View exposure completed (delivered after the Promotion window is closed)
break;
}
break;
case COUPON:
switch (engagementEventState) {
case START:
// Start coupon consumption request
break;
case END:
// Complete coupon consumption request and send response
break;
}
break;
case OFFERWALL_VIEW:
switch (engagementEventState) {
case START:
// Start offer wall page exposure request
break;
case END:
// Completed offerwall page exposure (delivered after closing the offerwall window)
break;
}
break;
case EVENT:
// If the host is game, send the JSONObject result value
if (param == null)
return;
String api = param.optString("api");
String paramData = param.optString("param");
// TODO: Perform the following actions according to the api and param values
break;
case IAP_UPDATED:
switch (engagementEventState) {
case START:
// Signal to accept as purchase history has changed (call Restore() method)
break;
case END:
// Signal to accept as purchase history has changed (call Restore() method)
if(param == null)
return;
String iapUpdateType = param.optString("type");
if(iapUpdateType == "subscription") {
// TODO: restore subscription product
IAPV4.INSTANCE.restoreSubscription((result1, iapv4ReceiptList) -> {
if (!result1.isSuccess()) {
return;
}
// TODO: Request receipt verification using the received iapv4ReceiptList
});
} else {
IAPV4.INSTANCE.restore((result2, iapv4ReceiptList) -> {
if (!result2.isSuccess()) {
return;
}
// TODO: Request receipt verification using the received iapv4ReceiptList
});
}
break;
}
break;
case IAP_PURCHASE:
switch (engagementEventState) {
case START:
// A pop-up for purchasing items received through the IAPPurchase schema is displayed.
break;
case END:
// Whether or not the purchase of the requested item was successful is communicated through the IAPPurchase schema.
if(!result.isSuccess() || param == null)
return;
JSONObject iapV4Receipt = param.optJSONObject("iapV4Receipt");
break;
}
break;
case SOCIAL_MYINQUIRY_VIEW:
switch (engagementEventState) {
case START:
// Start my inquiry page exposure request
break;
case END:
// My inquiry page has been exposed (delivered after the My Inquiry window is closed)
break;
}
break;
case SOCIAL_PROFILE_VIEW:
switch (engagementEventState) {
case START:
// Initiate profile page exposure request
break;
case END:
// Profile page exposure completed (delivered after closing the profile window)
break;
}
break;
}
});
API Reference: setEngagementHandler(_:)
import HIVEService
PromotionInterface.setEngagementHandler() { result, engagementEventType, engagementState, param in
switchengageEventType {
case.type:
switch engagementState{
case .begin:
// All actions of Engagement are performed
case .finish:
// All actions of Engagement are completed
}
case .authLoginView:
switch engagementState {
case.eventStart:
// Start Hive membership login page exposure request
case .eventEnd:
// Hive membership login completed (delivered after login completed/window closed)
}
case .socialInquiryView:
switch engagementState {
case.eventStart:
// Start 1:1 inquiry page exposure request
case .eventEnd:
// 1:1 inquiry page exposure completed (delivered after 1:1 inquiry window is closed)
}
case .promotionView:
switch engagementState {
case.eventStart:
// Start Promotion View impression request
case .eventEnd:
// Promotion View exposure completed (delivered after the Promotion window is closed)
}
case .coupon:
switch engagementState {
case.eventStart:
// Start coupon consumption request
case .eventEnd:
// Complete coupon consumption request and send response
}
case .offerwallView:
switch engagementState {
case.eventStart:
// Start offer wall page exposure request
case .eventEnd:
// Completed offerwall page exposure (delivered after closing the offerwall window)
}
case.event:
// If the host is game, send the JSONObject result value
let api = param?["api"]
let param = param?["param"]
// Perform requested actions according to api and param values
case.iapPromote:
switch engagementState {
case.eventStart:
// Convey whether IAP Promote data exists
case.eventEnd:
if ! result.isSuccess() {
return
}
// Since IAP Promote data exists, marketPid is received through check Promote API.
IAPV4Interface.checkPromotePurchase() {
promoteResult,
marketPid in
if !promoteResult.isSuccess() {
return
}
// TODO: Request to purchase the delivered market Pid item
IAPV4Interface.purchase(marketPid, additionalInfo: nil) {
purchaseResult,
receipt in
if !purchaseResult.isSuccess() {
return
}
// TODO: Request receipt verification with received receipt
}
}
case.iapUpdated:
switch engagementState {
case.eventStart:
// Signal to receive since purchase details have changed
case.eventEnd:
// Signal to receive since purchase details have changed
if
let type = param ? ["type"],
type == "subscription" {
// TODO: restore subscription product
IAPV4Interface.restoreSubscription() {
(result, receiptList) in
// TODO: Request receipt verification using the received receiptList
}
return
}
// TODO: restore consumable goods
IAPV4Interface.restore() {
(result, receiptList) in
// TODO: Request receipt verification using the received receiptList
}
}
case.iapPurchase:
switch engagementState {
case.eventStart:
// A pop-up for purchasing items received through the IAPPurchase schema is displayed.
case.eventEnd:
// Whether or not the purchase of the requested item was successful is communicated through the IAPPurchase schema.
if result.isSuccess() {
let receipt = param ? ["iapV4Receipt"];
}
}
case.socialMyInquiry:
switch engagementState {
case.eventStart:
// Start my inquiry page exposure request
case.eventEnd:
// My inquiry page has been exposed (delivered after the My Inquiry window is closed)
}
case.socialProfile:
switch engagementState {
case.eventStart:
// Initiate profile page exposure request
case.eventEnd:
// Profile page exposure completed (delivered after closing the profile window)
}
}
}
API Reference: HIVEPromotion setEngagementHandler
#import <HIVEService/HIVEService-Swift.h>
[HIVEPromotion setEngagementHandler: ^(HIVEResultAPI *result, HIVEEngagementEventType engagementEventType, HIVEEngagementEventState engagementState, NSDictionary *param) {
switch (engagementEventType) {
case HIVEEngagementEventTypeType:
switch (engagementState) {
case HIVEEngagementStateBegin:
// All actions of Engagement are performed
break;
case HIVEEngagementStateFinish:
// All actions of Engagement are completed
break;
}
break;
case HIVEEngagementEventTypeAuthLoginView:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Start Hive membership login page exposure request
break;
case HIVEEngagementStateEnd:
// Hive membership login completed (delivered after login completed/window closed)
break;
}
break;
case HIVEEngagementEventTypeSocialInquiryView:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Start 1:1 inquiry page exposure request
break;
case HIVEEngagementStateEnd:
// 1:1 inquiry page exposure completed (delivered after 1:1 inquiry window is closed)
break;
}
break;
case HIVEEngagementEventTypePromotionView:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Start Promotion View impression request
break;
case HIVEEngagementStateEnd:
// Promotion View exposure completed (delivered after the Promotion window is closed)
break;
}
break;
case HIVEEngagementEventTypeCoupon:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Start coupon consumption request
break;
case HIVEEngagementStateEnd:
// Complete coupon consumption request and send response
break;
}
break;
case HIVEEngagementEventTypeOfferwallView:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Start offer wall page exposure request
break;
case HIVEEngagementStateEnd:
// Completed offerwall page exposure (delivered after closing the offerwall window)
break;
}
break;
case HIVEEngagementEventTypeEvent:
// If the host is game, send the JSONObject result value
if (param == nil) {
return;
}
NSString * api = [param objectForKey: @ "api"];
NSSString * param = [param objectForKey: @ "param"];
// TODO: Perform requested action according to api and param values
break;
case HIVEEngagementEventTypeIapPromote:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Convey whether IAP Promote data exists
break;
case HIVEEngagementStateEventEnd:
if (![result isSuccess]) {
return;
}
// Since IAP Promote data exists, marketPid is received through check Promote API.
[HIVEIAPV4 checkPromotePurchase: ^ (HIVEResultAPI * promoteResult, NSString * marketPid) {
if (![promoteResult isSuccess]) {
return;
}
// TODO: Request to purchase an item using the received market Pid
[HIVEIAPV4 purchase: marketPid additionalInfo: nil handler: ^ (HIVEResultAPI * purchaseResult, HIVEIAPV4Receipt * receipt) {
if (![purchaseResult isSuccess]) {
return;
}
// TODO: Request verification of receipt with received receipt
}];
}];
break;
}
break;
case HIVEEngagementEventTypeIapUpdated:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Signal to receive since purchase details have changed
break;
case HIVEEngagementStateEventEnd:
// Signal to receive since purchase details have changed
NSString * type = [param objectForKey: @ "type"];
if (type != nil && [type isEqualToString: @ "subscription"]) {
// TODO: restore subscription product
[HIVEIAPV4 restoreSubscription: ^ (HIVEResultAPI * result, NSArray < HIVEIAPV4Receipt * > * receiptList) {
// TODO: Request receipt verification using the received receiptList
}];
return;
}
// TODO: restore consumable goods
[HIVEIAPV4 restore: ^ (HIVEResultAPI * result, NSArray < HIVEIAPV4Receipt * > * receiptList) {
// TODO: Request receipt verification using the received receiptList
}];
break;
}
case HIVEEngagementEventTypeIapPurchase:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// A pop-up for purchasing items received through the IAPPurchase schema is displayed.
break;
case HIVEEngagementStateEventEnd:
// Whether or not the purchase of the requested item was successful is communicated through the IAPPurchase
schema.
if(![result isSuccess]) {
return;
}
HIVEIAPV4Receipt * receipt = [param objectForKey: @ "iapV4Receipt"];
break;
}
break;
case HIVEEngagementEventTypeSocialMyInquiry:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Start my inquiry page exposure request
break;
case HIVEEngagementStateEnd:
// My inquiry page has been exposed (delivered after the My Inquiry window is closed)
break;
}
break;
case HIVEEngagementEventTypeSocialProfile:
switch (engagementState) {
case HIVEEngagementStateEventStart:
// Initiate profile page exposure request
break;
case HIVEEngagementStateEnd:
// Profile page exposure completed (delivered after closing the profile window)
break;
}
break;
}
}];
UE 이벤트 처리 가능 여부 설정¶
Hive SDK는 전달받은 요청를 처리를 Hive 로그인이 완료된 이후 시점이라면 수행될 수 있는 것이 일반적이지만, 최초 실행 등의 경우 로그인 이후라 하더라도 게임 서버 DB 생성 이전 시점이라면 보상 지급 등의 처리가 불가능하기에, 게임으로부터 처리 가능 여부에 대해 입력받을 필요가 있습니다.
- 이벤트 처리 가능 여부의 기본값은 `false`입니다.
- 이벤트 처리 가능 여부가 `true`로 설정되면 기존의 대기중인 이벤트들이 즉시 처리되며, 이후 입력되는 이벤트들은 즉시 처리가 됩니다.
- 이벤트 처리 가능 여부가 `false`로 설정되면 입력되는 이벤트들은 다시 `true`로 설정되기 전까지 대기 상태로 쌓이게 됩니다.
- 처리 가능 여부를 `true`로 설정하는 것은 반드시 로그인 이후 시점에 호출되어야 하며, `false`로 설정하는 것은 호출 시점에 제약이 없습니다.
- (Hive SDK v4.4.0 이후) CPI 보상 지급을 위해 모든 Hive SDK 를 적용한 게임은 해당 API를 필수로 호출해야 합니다.
- UA에서 생성된 초대 링크 혹은 QR 코드를 통해 앱에 진입한 경우, 혹은 오퍼월 페이지를 통해 앱에 진입한 경우에도 해당 API를 호출하여 변경된 상태에 따라 진입 이력 전송 및 보상 지급 요청이 수행됩니다.
- 반드시 UE의 기능을 수행할 수 있는 시점에 해당 API를 호출하여야합니다.
Note
setEngagementReady()
메서드를 호출하기 전 Promotion 클래스의setAdditionalInfo()
메서드를 이용하여 현재 유저의 게임 정보를 전달할 수 있습니다. 해당 정보는 쿠폰 기능이나, 유저 애퀴지션(UA)를 사용하는 경우 전달되어 게임에서 사용할 수 있습니다.- Hive SDK 버전에 따라
setEngagementReady()
메서드의 클래스가 다릅니다. 적용한 SDK 버전 별로 내용을 확인하세요.
Hive SDK v4.5.0 이상 사용 시¶
Hive SDK v4.5.0 이상에서 UE 이벤트 처리 가능 여부를 설정하기 위해서는 Promotion 클래스의 setEngagementReady()
메서드를 사용합니다. 다음은 UE 이벤트 처리 가능 여부를 true
로 설정하는 예제 코드입니다.
API Reference: hive.Promotion.setEngagementReady
API Reference: Promotion::setEngagementReady
API Reference: Promotion.setEngagementReady
API Reference: com.hive.Promotion.setEngagementReady
API Reference: PromotionInterface .setEngagementReady
API Reference: HIVEPromotion:setEngagementReady
쿠폰 사용 요청에 대한 결과 코드¶
쿠폰 이벤트 처리중, 쿠폰 번호에 문제가 있는 등 문제가 발생한 경우, UE 모듈에서 Hive 가 정의한 에러 코드에 따라 유저에게 팝업으로 상태를 안내합니다.
쿠폰에 대한 Scheme URL의 host값은 항상 hive
입니다.
Code | 설명 | Code | 설명 |
---|---|---|---|
200 | 잘못된 파라미터로 접근 | 305 | 사용 개수가 만료된 고유 쿠폰 |
201 | 잘못된 hash 값으로 전달 | 306 | 사용 기간이 만료된 쿠폰 |
202 | 해당 계정 사용 한도 초과 | 307 | 신규/기존 유저를 구분하는 이벤트지만 필요 정보가 없거나 AU (Active User) 시스템 오류 |
203 | 쿠폰 그룹의 사용 제한 초과 | 308 | 기존 유저 대상 이벤트지만 유저가 기존 유저가 아님 |
204 | 발급된 쿠폰과 넘어온 AppID가 다름 | 309 | 신규 유저 대상 이벤트지만 유저가 신규 유저가 아님 |
300 | 쿠폰 번호 자리수가 잘못됨 | 310 | 신규/기존 이벤트인데 해당 게임에서 입력하지 않음 |
301 | 전달 받은 프로모션 정보에 해당 쿠폰 정보 없음 | 400 | 아이템 전송 전부 실패 |
302 | 쿠폰 번호 조회 실패 | 401 | 아이템 전송 일부 실패 |
303 | 사용 중인 쿠폰 | 500 | DB 에러 |
304 | 사용 완료된 쿠폰 | 501 | 통신 실패 |