Hive SDK v1.19.1부터 IAP v2의 지원을 종료합니다. Hive SDK v1.19.1 이상의 환경에서는 Hive IAP v4를 적용하시기 바랍니다.
본 가이드는 Hive IAP v2에 대해 안내하며, Hive SDK v1.19.0 이하 v1.9.0 이상에서 적용하실 수 있습니다.
C2SModuleHiveIAP_Info
C2SModuleHiveIAP_Info() 메소드는 Hive 콘솔에 설정된 Hive IAP v2 상점 구성을 위한 상품 정보, 러비 잔액 등의 정보를 요청한다. 유저가 상품 리스트를 볼 때, 항상 정확한 정보 및 최신 정보를 볼 수 있도록 상점에 들어갈 때마다 C2SModuleHiveIAP_Info()를 호출하며 구매 및 구매 복구를 요청하기 전에 반드시 serverId / gameLanguage 식별자를 세팅해주어야 한다.
Request
argument name | type | description | platform | 비고 |
---|---|---|---|---|
상점 구성을 위한 아이템의 정보를 요청 할 때 | ||||
type | string | “shopInfo” | all | |
locationCode | string | 상점 구분 코드, “DEFAULT” | all | |
worldName | string | 게임 서버 구분 값 (Hive 아이템 등록 시 사용한 게임 서버 구분 값) 서버 지역 코드값은 ‘ISO 3166 alpha-2’ 코드를 기준으로 하며Hive 연동 가이드라인 게임서버 ID 항목을 참고한다. |
all | 1.12.0+ 삭제 |
gameLanguage | string | 게임내 언어 구분값. gameLanguage에 따라 상점에 노출되는 언어가 결정된다. ex. “ko”, “en” 게임 언어 코드값은 ‘ISO 639 alpha-2′(ISO 639-1) 코드를 기준으로 하며 Hive 연동 가이드라인 언어 항목을 참고한다. gameLanguage를 입력하지 않거나 유효하지 않은 값을 입력하였을 경우 백오피스에 등록된 default 언어를 사용한다. |
all | 1.12.0+ 삭제 |
상점 구성을 위한 러비 잔액 정보를 요청 할 때 | ||||
type | string | “balance” | android |
Response
locationCode = “DEFAULT” 를 사용한다면 비고에 * 표시가 되어 있는 값은 사용하지 않는다.
argument name | type | description | platform | 비고 |
---|---|---|---|---|
상점 정보 요청에 대한 콜백 데이터 | ||||
type | string | “shopInfo” | all | |
locationCode | string | 상점 구분 코드 “DEFAULT,” |
all | |
balance | string | 러비 잔액 | all | |
products | array | 상품 정보들 | all | |
isBadgeExist | bool | true or false 뱃지 정보 존재 유무 |
all | * |
badgeImageUrl | string | 뱃지 이미지 url | all | * |
shopType | string | 상점 구분 코드 | all | 1.10.3+ * |
러비 잔액 정보 요청에 대한 콜백 데이터 | ||||
type | string | “balance” | android | |
balance | int | 러비 잔액 | android |
array type for products
(locationCode = “DEFAULT” 를 사용한다면 비고에 * 표시가 되어 있는 값은 사용하지 않는다.)
argument name | type | description | platform | 비고 |
---|---|---|---|---|
pid | string | 게임에서 사용하는 상품 pid | all | |
marketPid | string | 마켓에 등록된 상품 pid | all | |
price | double | 상품 가격 | all | |
displayPrice | string | 상품 가격 문자열(ex. ₩1,000) | all | |
currency | string | 통화 코드 | all | |
title | string | 상품 타이틀 | all | * |
description | string | 상품 설명 | all | * |
badgeImageUrl | string | 뱃지 이미지 url | all | * |
productImageUrl | string | 상품 이미지 url | all | * |
titleLandscapeImageUrl | string | 상품 타이틀 이미지 (가로) | all | * |
titlePortraitImageUrl | string | 상품 타이틀 이미지 (세로) | all | * |
descLandscapeImageUrl | string | 상품 설명 이미지 (가로) | all | * |
descPortraitImageUrl | string | 상품 설명 이미지 (세로) | all | * |
productType | string | 상품 타입 일반 상품 : general / 시리즈 상품 : series |
all | 1.11.2+ * |
salesStartUTC | long | 상품 판매 시작 시간 -1일 경우 무제한 |
all | 1.11.2+ * |
salesExpireUTC | long | 상품 판매 만료 시간 -1일 경우 무제한 |
all | 1.11.2+ * |
seriesInfo | dictionary | 시리즈 상품 정보 (productType = general일 땐 필드 없음) |
all | 1.11.2+ * |
dictionary type for seriesInfo
(locationCode = “DEFAULT” 를 사용한다면 비고에 * 표시가 되어 있는 값은 사용하지 않는다.)
argument name | type | description | platform | 비고 |
---|---|---|---|---|
seriesPurchaseStatus | int | 구매 상태 구매전 : 1 / 구매 완료 : 2 |
all | 1.11.2+ * |
seriesSeq | int | 시리즈 상품 순번 | all | 1.11.2+ * |
seriesTotalCount | int | 시리즈 상품 수 | all | 1.11.2+ * |
샘플코드
API Reference: C2SModule.HiveIAP.Info
- public static bool C2SModule.HiveIAP.Info(C2SModule.Parameter arg, out C2SModule.Error error);
- public static bool C2SModule.HiveIAP.Info(C2SModule.Parameter arg, out C2SModule.Error error,
C2SModule.CompletionHandler completionHandler);
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
//상점 정보 public void hiveIAPShopInfo(string locationCode,string worldCode,string gameLanguage,Action<hiveiapitem[],c2serror> completionHandler){ C2SError error; C2SParameter arg = new C2SParameter (); arg ["type"] = "shopInfo"; // 상점 정보 요청 부분 arg ["locationCode"] = locationCode; // 상점 구분 코드 C2SModule.HiveIAP.Info(arg,out error,(C2SParameter resultArg,C2SError resultError) => { //restore process HiveIAPItem[] itemList = null; if(resultError == null) { List< object > products = resultArg["products"] as List< object >; itemList = new HiveIAPItem[products.Count]; for(int i=0;i<products.count;++i) { itemList[i] = new HiveIAPItem(); Dictionary< string,object > product = products[i] as Dictionary< string,object >; itemList[i].pid = product["pid"] as string; itemList[i].currency = product["currency"] as string; itemList[i].price = product["price"].ToString(); itemList[i].title = product["title"] as string; itemList[i].description = product["description"] as string; if(product.ContainsKey("productImageUrl")) { itemList[i].productionImgUrl = product["productImageUrl"].ToString(); } if(product.ContainsKey("badgeImageUrl")) { itemList[i].badgeImgUrl = product["badgeImageUrl"].ToString();; } } } completionHandler(itemList,resultError); }); LocalErrorProcessor (error); } //BadgeInfo API call example public void getHiveIAPBadge(string locationCode,string worldCode,string gameLanguage,Action< HiveIAPBadge,C2SError > completionHandler) { C2SError error; C2SParameter arg = new C2SParameter (); arg ["type"] = "badge"; // 뱃지 정보 요청 부분 arg ["locationCode"] = locationCode; // 상점 구분 코드 C2SModule.HiveIAP.Info(arg,out error,(C2SParameter resultArg,C2SError resultError) => { HiveIAPBadge badge = null; if(resultError == null) { badge = new HiveIAPBadge(); if(resultArg.ContainsKey("badgeImageUrl")) badge.BadgeURL = resultArg["badgeImageUrl"].ToString(); badge.isBadgeExist = (bool)resultArg["isBadgeExist"]; } completionHandler(badge,resultError); }); } //Balance API call example public void getHiveIAPBalance(Action< HiveIAPBadge,C2SError > completionHandler) { C2SError error; C2SParameter arg = new C2SParameter (); arg ["type"] = "balance"; C2SModule.HiveIAP.Info(arg,out error,(C2SParameter resultArg,C2SError resultError) => { // balance 처리. }); } |
API Reference: HiveSDKUEHiveIAP_Info
- void HiveSDKUEHiveIAP_Info(FString fstrJson);
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
//ShopInfo API Call example TSharedPtr arg = MakeShareable(new FJsonObject); arg->SetStringField(TEXT(C2SModuleArgKey_TYPE), TEXT("shopInfo")); // 상정정보 요청 부분 arg->SetStringField(TEXT("locationCode"), locationCode); // 상점 구분 코드 ( ex: "MAIN" ) FString OutputString; TSharedRef< TJsonWriter<TCHAR, TCondensedJsonPrintPolicy< TCHAR >> > Writer = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy< TCHAR >>::Create(&OutputString); FJsonSerializer::Serialize(arg.ToSharedRef(), Writer); FHiveSDKModule::Get().HiveSDKUEHiveIAP_Info(OutputString); //BadgeInfo API Call example TSharedPtr arg = MakeShareable(new FJsonObject); arg->SetStringField(TEXT(C2SModuleArgKey_TYPE), TEXT("badge")); // 뱃지정보 요청 부분 arg->SetStringField(TEXT("locationCode"), locationCode); // 상점 구분 코드 ( ex: "MAIN" ) FString OutputString; TSharedRef< TJsonWriter<TCHAR, TCondensedJsonPrintPolicy< TCHAR >> > Writer = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy< TCHAR >>::Create(&OutputString); FJsonSerializer::Serialize(arg.ToSharedRef(), Writer); FHiveSDKModule::Get().HiveSDKUEHiveIAP_Info(OutputString); //Balance API call example TSharedPtr arg = MakeShareable(new FJsonObject); arg->SetStringField(TEXT(C2SModuleArgKey_TYPE), TEXT("balance")); // 러비 잔액 요청 부분 FString OutputString; TSharedRef< TJsonWriter<TCHAR, TCondensedJsonPrintPolicy< TCHAR >> > Writer = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy< TCHAR >>::Create(&OutputString); FJsonSerializer::Serialize(arg.ToSharedRef(), Writer); FHiveSDKModule::Get().HiveSDKUEHiveIAP_Info(OutputString); *Result Delegate example #if PLATFORM_IOS || PLATFORM_ANDROID void MYGAMECLASS::ResultDelegate(C2SModuleApi api, const char* json, C2SModuleErrorCode code, const char* message) { //... switch(api) { case C2SModuleApi_HiveIAPInfo: { if( arg->HasField(TEXT("type"))) { FString type = arg->GetStringField(TEXT("type")); if(!type.IsEmpty() && type.Compare("shopInfo") == 0) { // badgeImageUrl // isBadgeExist // products TArray productList; productList = arg->GetArrayField(TEXT("products")); UE_LOG(LogTemp, Warning, TEXT( "====>>>> (HiveIAP) Number of productList Array %d"),productList.Num()); TArray hiveIAPgameProductArray; for (int32 loopIDX = 0; loopIDX < productList.Num(); loopIDX++) { FHiveGameProductInfo productInfo; productInfo.localizedTitle = productList[loopIDX]->AsObject()->GetStringField(TEXT("title")); productInfo.localizedDescription = productList[loopIDX]->AsObject()->GetStringField(TEXT("description")); productInfo.formattedString = productList[loopIDX]->AsObject()->GetStringField(TEXT("displayPrice")); productInfo.productID = productList[loopIDX]->AsObject()->GetStringField(TEXT("pid")); productInfo.currencyCode = productList[loopIDX]->AsObject()->GetStringField(TEXT("currency")); double productPrice = productList[loopIDX]->AsObject()->GetNumberField(TEXT("price")); productInfo.amountMicros = FString::SanitizeFloat(productPrice); productInfo.marketPID = productList[loopIDX]->AsObject()->GetStringField(TEXT("marketPid")); productInfo.badgeImageUrl = productList[loopIDX]->AsObject()->GetStringField(TEXT("badgeImageUrl")); productInfo.productImageUrl = productList[loopIDX]->AsObject()->GetStringField(TEXT("productImageUrl")); productInfo.titleLandscapeImageUrl = productList[loopIDX]->AsObject()->GetStringField(TEXT("titleLandscapeImageUrl")); productInfo.titlePortraitImageUrl = productList[loopIDX]->AsObject()->GetStringField(TEXT("titlePortraitImageUrl")); productInfo.descLandscapeImageUrl = productList[loopIDX]->AsObject()->GetStringField(TEXT("descLandscapeImageUrl")); productInfo.descPortraitImageUrl = productList[loopIDX]->AsObject()->GetStringField(TEXT("descPortraitImageUrl")); hiveIAPgameProductArray.Add(productInfo); } //use hiveIAPgameProductArray } else if(!type.IsEmpty() && type.Compare("badge") == 0) { bool isBadgeExist = arg->GetBoolField(TEXT("isBadgeExist")); if(isBadgeExist) { FString bagdeImageUrl = arg->GetStringField(TEXT("badgeImageUrl")); } } else if(!type.IsEmpty() && type.Compare("balance") == 0) { if(arg->HasField(TEXT("balance"))) { } } } break; } } //... } #endif USTRUCT(BlueprintType) struct FHiveGameProductInfo { GENERATED_BODY() public: UPROPERTY(EditAnywhere, BlueprintReadWrite) FString localizedDescription; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString amountMicros; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString productID; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString currencyCode; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString localizedTitle; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString formattedString; //HiveSDK 1.10.0 HiveIAP reuse , additional member. //productID = marketPID //amountMircros = price //formattedString = displayPrice //localizedTitle = title //localizedDescription = description //currencyCode = currency UPROPERTY(EditAnywhere, BlueprintReadWrite) FString marketPID; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString badgeImageUrl; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString productImageUrl; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString titleLandscapeImageUrl; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString titlePortraitImageUrl; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString descLandscapeImageUrl; UPROPERTY(EditAnywhere, BlueprintReadWrite) FString descPortraitImageUrl; }; |
API Reference: C2SModuleHiveIAP_Info
- bool C2SModuleHiveIAP_Info(const char* pstrJson, C2SModule_Cocos2dx::C2SModuleError* pkError,
C2SModule_Cocos2dx::C2SModuleCompletionHandler* completionHandler = NULL);
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
//ShopInfo API Call example void SampleProject::menuHiveIAPShopInfoCallback(cocos2d::Ref* pSender) { Json::Value arg; arg ["type"] = "shopInfo"; // 상정정보 요청 부분 arg ["locationCode"] = "MAIN"; // 상점 구분 코드 Json::StyledWriter writer; std::string strJSON = writer.write(arg); C2SModule_Cocos2dx::C2SModuleError error; if( C2SModuleHiveIAP_Info( strJSON.c_str(), &error ) == false ) { CCLog( "====>>>> C2SModuleHiveIAP_Info shopInfo error (%s)", error.get()->GetMessage() ); } } //BadgeInfo API Call example void SampleProject::menuHiveIAPBadgeInfoCallback(cocos2d::Ref* pSender) { Json::Value arg; arg ["type"] = "badge"; // 뱃지정보 요청 부분 arg ["locationCode"] = "MAIN"; // 상점 구분 코드 Json::StyledWriter writer; std::string strJSON = writer.write(arg); C2SModule_Cocos2dx::C2SModuleError error; if( C2SModuleHiveIAP_Info( strJSON.c_str(), &error ) == false ) { CCLog( "====>>>> C2SModuleHiveIAP_Info badgeInfo error (%s)", error.get()->GetMessage() ); } } //Balance API call example void SampleProject::menuHiveIAPBalanceInfoCallback(cocos2d::Ref* pSender) { Json::Value arg; arg ["type"] = "balance"; // 러비 잔액 요청 부분 Json::StyledWriter writer; std::string strJSON = writer.write(arg); C2SModule_Cocos2dx::C2SModuleError error; if( C2SModuleHiveIAP_Info( strJSON.c_str(), &error ) == false ) { CCLog( "====>>>> C2SModuleHiveIAP_Info balance error (%s)", error.get()->GetMessage() ); } } void SampleProject::ResultDelegate(C2SModuleApi api, const char* json, C2SModuleErrorCode code, const char* message) { case C2SModuleApi_HiveIAPInfo: { Json::Value arg; Json::Reader reader; if( reader.parse(json, arg) == false ) { CCLog( "====>>>> C2SModuleApi_HiveIAPInfo parse failed : (%s)", json ); return; } std::string type = arg.get("type", "").asString(); if(!type.empty() && type.compare("shopInfo") == 0) { int count = arg["products"].size(); for(int i = 0; i < count; i++) { std::string pid = arg["products"][i]["pid"].asString(); // 나머지 데이터 파싱 생략.. } } else if(!type.empty() && type.compare("badge") == 0) { bool isBadgeExist = arg["isBadgeExist"].asBool(); std::string bagdeImageUrl = arg["bagdeImageUrl"].asString(); } else if(!type.empty() && type.compare("balance") == 0) { if(arg.isMember("balance")) { int balance = arg["balance"].asInt(); } } } break; } |
API Reference: C2SModuleHiveIAP Info
- +(BOOL)Info:(id)arg error:(NSError**)error;
- +(BOOL)Info:(id)arg error:(NSError**)error completionHandler:(void(^)(NSDictionary *, NSError*))
completionHandler;
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 42 43 44 45 46 47 48 49 50 51 52 |
-(void)getHiveIAP_infoItem { NSError* error; NSString* type = @"shopInfo"; // 상정 정보 요청 부분 NSString* locationCode = @"MAIN"; // 상점 구분 코드 NSMutableDictionary* arg = [[NSMutableDictionary alloc] init]; [arg setObject:type forKey:@"type"]; [arg setObject:locationCode forKey:@"locationCode"]; [C2SModuleHiveIAP Info:arg error:&error completionHandler:^(NSDictionary *resultArg, NSError *resultError){ if(resultError == nil){ //success NSMutableArray* itemList = [[NSMutableArray alloc]init]; NSMutableArray* productsList = [resultArg objectForKey : @"products"]; for(NSDictionary* product in productsList) { HiveIAPInfoItem* data = [[HiveIAPInfoItem alloc]init]; data.pid = product[@"pid"]; data.marketPid = product[@"marketPid"]; data.currency = product[@"currency"]; data.price = [product[@"price"] doubleValue]; data.title = product[@"title"]; data.descript = product[@"description"]; if ( [product objectForKey : @"productImageUrl"]!=nil) data.productImageUrl = product[@"productImageUrl"]; if ( [product objectForKey : @"badgeImageUrl"]!=nil) data.badgeImageUrl = product[@"badgeImageUrl"]; // 나머지 데이터 파싱 생략 [itemList addObject : data]; } } }]; } '-(void)getHiveIAP_infoBadge { NSError* error; NSString* type = @"badge"; // 뱃지 정보 요청 부분 NSString* locationCode = @"MAIN"; // 상점 구분 코드 NSMutableDictionary* arg = [[NSMutableDictionary alloc] init]; [arg setObject:type forKey:@"type"]; [arg setObject:locationCode forKey:@"locationCode"]; [C2SModuleHiveIAP Info:arg error:&error completionHandler:^(NSDictionary *resultArg, NSError *resultError) { HiveIAPInfoBadge* badge = [[HiveIAPInfoBadge alloc]init]; if(resultError == nil){ //success if ( [resultArg objectForKey : @"badgeImageUrl"]!=nil) badge.badgeURL = [resultArg objectForKey : @"badgeImageUrl"]; badge.isBadgeExist= [resultArg[@"isBadgeExist"] boolValue]; } }]; } |