콘텐츠로 이동

앱 개발

Hive SDK를 사용해 앱을 개발하는 순서를 안내합니다. Hive SDK는 인증, 결제, 푸시 알림, 광고 배너, 고객 데이터 분석 등 다양한 기능을 제공하는데, 이 가이드에서는 이중에서 가장 기본적인 기능인 인증결제 기능을 구현 예시로 안내합니다.

Note

Hive SDK는 다양한 개발 엔진(Android Native, iOS Native, Unity, Unreal Engine 등)을 지원합니다. 이 가이드는 여러분이 각 개발 엔진으로 앱 개발, 빌드, 출시하는 방법을 이미 알고 있다는 가정하에 Hive SDK 사용법을 안내합니다. 개발 엔진별로 앱을 개발, 빌드, 출시하는 방법은 각 개발 엔진 개발자 센터와 개발자 문서를 참고하세요.


앱 개발 시 Hive SDK를 사용하는 전체 과정을 요약하면 아래와 같습니다.

  1. Hive SDK 초기화 구현
  2. 인증 구현
  3. 결제 구현


인증 구현은 다음을 포함합니다.

  • 로그인 구현
  • 로그인 토큰 검증 구현


결제 구현은 다음을 포함합니다.

  • 결제 초기화 구현
  • 상품 목록 조회 구현
  • 상품 구매 구현
  • 구매 영수증 검증 구현


Hive SDK 구현 순서

Hive SDK로 앱 기능을 구현하는 일반적인 순서는 다음과 같습니다.

Hive SDK 초기화 구현

Hive SDK가 동작하려면 가장 먼저 Hive SDK를 초기화해야 합니다. Hive SDK를 초기화하면 사전에 입력한 Hive SDK 설정 값이 할당되는 등 다양한 준비 작업이 진행됩니다. Hive SDK를 초기화하려면 AuthV4.setup을 호출합니다. 호출에 성공하면 결과로 다음 정보를 전달받으며, 이를 앱에 저장하여 적절한 시점에 사용할 수 있습니다.

Hive 초기화 수행 결과 정보

필드명 설명 예제
isAutoSignIn 자동 로그인 가능 여부 true
did 앱 설치 시 생성되는 식별자 123456789
providerTypeList 현재 앱에서 제공 가능한 IdP 인증 목록 ProviderType.HIVEProviderType.GOOGLE


다음은 setup 메서드 구현 예제 입니다.

API Reference: hive.AuthV4.setup

    // Hive SDK 초기화 요청
    AuthV4.setup ((ResultAPI result, Boolean isAutoSignIn, String did, List providerTypeList) => {
        if (result.isSuccess()) {
            // 초기화 성공. 자동 로그인 가능 여부에 따라 로그인을 처리하세요.
        } else if (result.needExit()) {
            // TODO: 앱 종료 기능을 구현하세요
            // 예) Application.Quit();
        } else {
            // 초기화 실패
        }
    });

API Reference: AuthV4::setup

// Hive SDK 초기화 요청
AuthV4::setup([=](ResultAPI const & result, bool isAutoSignIn, std::string did, std::vector<ProviderType> const & providerTypeList) {

    if (result.isSuccess()) {
        // 초기화 성공. 자동 로그인 가능 여부에 따라 로그인을 처리하세요.
    } else if (result.needExit()) {
        // TODO: 앱 종료 기능을 구현하세요
        // Cocos2d-x 엔진 사용자
        // 예) exit(0);
        // Unreal 엔진 사용자
        // 예) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);    
    } else {
        // 초기화 실패
    }

});

API Reference: com.hive.AuthV4.setup

// Hive SDK 초기화 요청    
    AuthV4.setup(object: AuthV4.AuthV4SetupListener{    
        override fun onAuthV4Setup(result: ResultAPI, isAutoSignIn: Boolean, did: String?, providerTypeList: ArrayList<AuthV4.ProviderType>?) {    
            if (result.isSuccess) {    
                // 초기화 성공. 자동 로그인 가능 여부에 따라 로그인을 처리하세요.    
            } else if (result.needExit()) {    
                // TODO: 앱 종료 기능을 구현하세요    
                // 예) exitProcess(0)    
            } else {    
                // 초기화 실패    
            }    
        }    
})

API Reference: com.hive.AuthV4.setup

// Hive SDK 초기화 요청    
    AuthV4.setup(new AuthV4.AuthV4SetupListener() {    
        @Override    
        public void onAuthV4Setup(ResultAPI result, boolean isAutoSignIn, String did, ArrayList<AuthV4.ProviderType> providerTypeList) {    

                if (result.isSuccess()) {    
                // 초기화 성공. 자동 로그인 가능 여부에 따라 로그인을 처리하세요.    
            } else if (result.needExit()) {    
                // TODO: 앱 종료 기능을 구현하세요    
                // 예) System.exit(0);    
            } else {    
                // 초기화 실패    
            }    
        }        
});

API Reference: HIVEAuthV4:setup

AuthV4Interface.setup { (result, isAutoSignIn, did, providerTypeList) in    
        if result.isSuccess() {    
            // 초기화 성공. 자동 로그인 가능 여부에 따라 로그인을 처리하세요.    
        } else if result.needExit() {    
            // TODO: 앱 종료 기능을 구현하세요    
            // 예) exit(0)    
        } else {    
            // 초기화 실패    
        }    
}

API Reference: HIVEAuthV4:setup

// Hive SDK 초기화 요청    
    [HIVEAuthV4 setup:^(HIVEResultAPI *result, BOOL isAutoSignIn, NSString *did, NSArray<NSNumber *> *providerTypeList) {    
        if (result.isSuccess) {    
            // 초기화 성공. 자동 로그인 가능 여부에 따라 로그인을 처리하세요.    
        } else if (result.needExit) {    
            // TODO: 앱 종료 기능을 구현하세요    
            // 예) exit(0);    
        } else {    
            // 초기화 실패    
        }    
}];
Info

자세한 내용은 Hive 초기화 가이드를 참고하세요.

인증 구현

앱 이용자는 Hive 멤버십 계정뿐만 아니라 구글, 페이스북과 같은 다양한 ID 제공업체(ID Provider, 이하 IdP) 계정으로 앱에 로그인할 수 있습니다. 로그인 구현 시, 이용자는 원하는 IdP 계정을 선택하여 앱에 로그인하고 앱 계정과 IdP 계정을 서로 연동할 수 있습니다. 제공하는 IdP 종류는 앱에 따라 다르게 설정할 수 있으며, Hive 플랫폼은 접속한 이용자의 국가 정보에 따라 이용자에게 적절한 IdP를 노출합니다.

먼저, Hive 콘솔에서 IdP 설정을 진행합니다.

  1. IdP에서 제공하는 키 값 저장
  2. 앱 센터 > 앱 목록 > 앱 검색 후 클릭 > AppID 탭 클릭 > 앱 AppID 클릭 > 로그인에서 IdP 사용 설정
Info

자세한 내용은 Hive 콘솔 인증 가이드를 확인하세요.

로그인 구현

콘솔 설정을 완료했다면, Hive SDK로 로그인 UI를 구현합니다. 아래는 SDK에서 제공하는 UI를 사용하여 구현하는 경우 예시입니다.

API Reference: hive.AuthV4.showSignIn

// Hive SDK AuthV4 인증 UI 요청    
    AuthV4.showSignIn((ResultAPI result, AuthV4.PlayerInfo playerInfo)=>{    
    if (result.isSuccess()) {    
        // 인증 성공    
        // playerInfo : 인증된 사용자 정보    
        // 이메일 정보 조회 예시    
        foreach (KeyValuePair<AuthV4.ProviderType, AuthV4.ProviderInfo> entry in playerInfo.providerInfoData) {    

            AuthV4.ProviderInfo providerInfo = entry.Value;    
            if(providerInfo.providerEmail != null && providerInfo.providerEmail != "") {    
                string email = providerInfo.providerEmail;    
                break;    
            }    
        }    
    }    
    else if (result.needExit()) {    
        // TODO: 앱 종료 기능을 구현하세요    
        // 예) Application.Quit();    
    }    
});

API Reference: AuthV4::showSignIn

// Hive SDK AuthV4 인증 UI 요청    
    AuthV4::showSignIn([=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
    if (result.isSuccess()) {    
        // 인증 성공    
        // playerInfo: 인증된 사용자 정보    

        // 이메일 정보 조회 예시    
        for(auto it = playerInfo.providerInfoData.begin(); it != playerInfo.providerInfoData.end(); ++it) {    
            hive::ProviderInfo providerInfo = it->second;    
            if(!providerInfo.providerEmail.empty()) {    
                std::string email = providerInfo.providerEmail;    
                break;    
            }    
        }    
    }    
    else if (result.needExit()) {    
        // TODO: 앱 종료 기능을 구현하세요    
        // Cocos2d-x 엔진 사용자    
        // 예) exit(0);    
        // Unreal 엔진 사용자    
        // 예) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);    
    }    
});

API Reference: com.hive.AuthV4.showSignIn

// Hive SDK AuthV4 인증 UI 요청    
    AuthV4.showSignIn(object : AuthV4.AuthV4SignInListener {    
    override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
        if (result.isSuccess) {    
            // 인증 성공    
            // playerInfo: 인증된 사용자 정보    
            // 이메일 정보 조회 예시    
            playerInfo?.let {    
                for ((key, value) in it.providerInfoData) {    
                    var providerInfo: AuthV4.ProviderInfo = value    
                    if(providerInfo.providerEmail.isNotEmpty()) {    
                        val email = providerInfo.providerEmail    
                        break    
                    }    
                }    
            }    
        } else if (result.needExit()) {    
            // TODO: 앱 종료 기능을 구현하세요    
            // 예) exitProcess(0)    
        }    
    }    
})

API Reference: com.hive.AuthV4.showSignIn

// Hive SDK AuthV4 인증 UI 요청    
    AuthV4.showSignIn(new AuthV4.AuthV4SignInListener() {    
    @Override    
    public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) {    

        if (result.isSuccess()) {    
            // 인증 성공    
            // playerInfo: 인증된 사용자 정보    
            // 이메일 정보 조회 예시    
            if(playerInfo != null) {    
                for (Map.Entry<AuthV4.ProviderType, AuthV4.ProviderInfo> entry : playerInfo.getProviderInfoData().entrySet()) {    
                    AuthV4.ProviderInfo providerInfo = entry.getValue();    
                    if (providerInfo.getProviderEmail() != "") {    
                        String email = providerInfo.getProviderEmail();    
                        break;    
                    }    
                }    
            }    
        }    
        else if (result.needExit()) {    
            // TODO: 앱 종료 기능을 구현하세요    
            // 예) System.exit(0);    
        }    
    }    
});

API Reference: HIVEAuthV4:showSignIn

var email = String()    
    // Hive SDK AuthV4 인증 UI 요청    
    AuthV4Interface.showSignIn { (result, playerInfo) in    

    if result.isSuccess() {    
        // 인증 성공    
        // playerInfo: 인증된 사용자 정보    
        // 이메일 정보 조회 예시    
        if let playerInfo = playerInfo {    
            // providerEmail이 존재하는 providerInfo 탐색 (현재 로그인 진행된 provider)    
            for key in playerInfo.providerInfoData.keys {    
                if let providerInfo = playerInfo.providerInfoData[key],    
                    providerInfo.providerEmail.count > 0 {    
                    // providerEmail != ""    
                    email = providerInfo.providerEmail    
                    break    
                }    
            }    
        }    
    } else if result.needExit() {    
        // TODO: 앱 종료 기능을 구현하세요    
        // 예) exit(0)    
    }    
}

API Reference: HIVEAuthV4:showSignIn

__block NSString* email = @"";    
    // Hive SDK AuthV4 인증 UI 요청    
    [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {    
    if([result isSuccess]){    
        // 인증 성공    
        // playerInfo: 인증된 사용자 정보    
        // 이메일 정보 조회 예시    
        if(playerInfo != nil) {    
            // providerEmail이 존재하는 providerInfo 탐색 (현재 로그인 진행된 provider)    
            for (NSString* key in playerInfo.providerInfoData.allKeys) {    
                HIVEProviderInfo* providerInfo = playerInfo.providerInfoData[key];    
                if (providerInfo != nil && providerInfo.providerEmail.length > 0) {    
                    // providerEmail != ""    
                    email = providerInfo.providerEmail;    
                    break;    
                }    
            }    
        }    
    } else if ([result needExit]) {    
        // TODO: 앱 종료 기능을 구현하세요    
        // 예) exit(0);    
    }    
}];


기존에 로그인 했던 인증 토큰 키가 있다면 이용자가 자동으로 앱에 로그인하도록 할 수 있습니다. Hive SDK 초기화 응답값으로 받은 isAutoSignIntrue라면 위와 같이 로그인 UI를 사용할 필요없이 바로 자동으로 이용자를 로그인 시킬 수 있습니다. 아래는 자동 로그인을 호출하는 예제입니다.

API Reference: hive.AuthV4.Helper.signIn

// Hive SDK 로그인(signIn) 시도    
    AuthV4.Helper.signIn (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {    

    if (result.isSuccess()) {    
        // 로그인 성공    
    } else if (result.needExit()) {    
        // TODO: 앱 종료 기능을 구현하세요    
        // 예) Application.Quit();    
    } else {    
        switch (result.code) {    
            case ResultAPI.Code.AuthV4ConflictPlayer:    
                // 계정 충돌    
                break;    
            case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:    
                // 묵시적 로그인에 실패                   
                // ex) AuthV4.showSignIn(...);    
                break;    
            default:    
                // 기타 예외 상황    
                break;    
        }    
    }    
});

API Reference: Auth4::signIn

// Hive SDK 로그인(signIn) 시도    
    AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared_ptr playerInfo) {    

    if (result.isSuccess()) {    
        // 로그인 성공    
    } else if (result.needExit()) {    
        // TODO: 앱 종료 기능을 구현하세요              
        // Cocos2d-x 엔진 사용자    
        // 예) exit(0);    
        // Unreal 엔진 사용자    
        // 예) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);    
    } else {    
        switch (result.code) {    
            case ResultAPI::AuthV4ConflictPlayer:    
                // 계정 충돌    
                break;    
            case ResultAPI::AuthV4HelperImplifiedLoginFail:    
                // 묵시적 로그인에 실패    
                // ex) AuthV4.showSignIn(...);    
                break;    
            default:    
                break;    
        }    
    }    
});

API Reference: com.hive.Auth4.Helper.signIn

// Hive SDK 로그인(signIn) 시도
AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener {
override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
    if (result.isSuccess) {
        // 로그인 성공
    } else if (result.needExit()) {
        // TODO: 앱 종료 기능을 구현하세요
        // 예) exitProcess(0)
    } else {
        when (result.code) {
            ResultAPI.Code.AuthV4ConflictPlayer -> {
                // 계정 충돌
            }
            ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> {
                // 묵시적 로그인에 실패
                // ex) AuthV4.showSignIn(...);
            }
            else -> {
                // 기타 예외 상황
            }
        }
    }
}
})

API Reference: Auth4::signIn

// Hive SDK 로그인(signIn) 시도
AuthV4.Helper.signIn(new AuthV4.Helper.AuthV4HelperListener() {
@Override
public void onAuthV4Helper(ResultAPI result, AuthV4.PlayerInfo playerInfo) {

    if (result.isSuccess()) {
        // 로그인 성공
    } else if (result.needExit()) {
        // TODO: 앱 종료 기능을 구현하세요
        // 예) System.exit(0);
    } else {
            switch (result.code) {
            case AuthV4ConflictPlayer:
                // 계정 충돌
                break;
            case AuthV4HelperImplifiedLoginFail:
                // 묵시적 로그인에 실패               
                // ex) AuthV4.showSignIn(...);
                break;
            default:
                // 기타 예외 상황
                break;
        }
    }
}  
});

API Reference: HIVEAuth4:signIn

    // Hive SDK 로그인(signIn) 시도
AuthV4Interface.helper().signIn() { (result, playerInfo) in

if result.isSuccess() {
    // 로그인 성공 
}
else if result.needExit() {
    // TODO: 앱 종료 기능을 구현하세요
    // 예) exit(0)
}
else {
    switch result.getCode() {
    case .authV4ConflictPlayer:
        // 계정 충돌   
    case .authV4HelperImplifiedLoginFail:
        // 묵시적 로그인에 실패
        // ex) AuthV4Interface.showSignIn() { (result, playerInfo)
        // // do something...
        // }
    default:
        // 기타 예외 상황
        break   
    }
}
}

API Reference: HIVEAuth4:signIn

    // Hive SDK 로그인(signIn) 시도
[[HIVEAuthV4 helper] signIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {

if (result.isSuccess) {
    // 로그인 성공 
}
else if (result.needExit) {
    // TODO: 앱 종료 기능을 구현하세요
    // 예) exit(0);
}
else {
    switch (result.code) {
        case kAuthV4ConflictPlayer:
            // 계정 충돌
            break;    
        case kAuthV4HelperImplifiedLoginFail:
            // 묵시적 로그인에 실패
            // ex) [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
            // // do something...
            // }];
            break;
        default:
            // 기타 예외 상황
            break;   
    }
}
}];


이 외에도, 이용자가 로그인하는 화면을 구현 시 Hive UI를 사용하지 않고 앱에서 자체적으로 로그인 UI를 구현하는 커스터마이징 기능이나, 이용자가 IdP를 선택하지 않고 게스트 계정 상태로 앱을 이용하도록 하는 게스트 로그인 기능도 지원합니다.

Info

자세한 내용은 로그인·로그아웃하기를 참고하세요.

로그인 토큰 검증 구현

앱 계정 도용, 해킹 등 보안 사고를 막으려면 이용자가 로그인한 후 로그인 토큰 검증을 수행해야 합니다. 로그인 성공 후 반환된 토큰, PlayerID, DID를 이용하여 여러분의 앱 서버에서는 로그인한 이용자의 토큰 키가 유효한지 검증할 수 있습니다. 로그인 토큰 검증Hive 서버 API > 인증 v4 토큰 검증하기 API를 호출하여 수행합니다.

Hive SDK는 기본적으로 앱 계정의 중복 로그인을 허용합니다. 따라서, 여러 기기에서 1개 계정으로 로그인하면, 로그인할 때 발생한 세션키를 모든 기기에서 모두 유지합니다. 만약, 앱에서 중복 로그인을 허용하지 않으려면, 하나의 PlayerId에 하나의 세션키만 매칭되게끔(=하나의 기기만 앱 서버와 연결되게끔) 앱에서 구현해야합니다.

Info

자세한 내용은 인증 토큰 키 유효성 검증을 참고하세요.

결제 구현

Hive SDK에서 앱 내 아이템 판매와 결제 기능은 Hive SDK 빌링 모듈인 Hive IAP v4를 사용해 구현합니다. Hive IAP v4는 간단하게 결제를 구현할 수 있도록 아이템 구매 영수증 검증, 아이템 중복 지급 체크, 결제 로그 전송 등 개발 시간을 줄이고 마켓 변화에 빠르게 대응할 수 있는 결제 기능을 제공합니다.

Info

자세한 내용은 다음을 참고하세요.


Hive SDK의 결제 기능을 이용하려면, 먼저 앱 마켓(Google Play) 콘솔과 Hive 콘솔에 판매할 앱 아이템 상품 정보를 등록해야 합니다.

Info

자세한 내용은 각 앱 마켓 문서Hive 콘솔 가이드 빌링을 확인하세요.

결제 초기화 구현

앱 마켓 콘솔과 Hive 콘솔에 상품 정보를 등록했다면, 앱을 실행한 후 시점에서 Hive IAP v4 초기화 코드를 실행해야 Hive IAP v4를 사용할 수 있습니다. Hive IAP v4 초기화를 요청하면 앱 클라이언트에서 이용 가능한 마켓 정보를 결과값으로 반환합니다. 다음은 Hive IAP v4를 초기화하는 예제 코드입니다.

API Reference: hive.IAPV4.marketConnect

using hive;

IAPV4.marketConnect((ResultAPI result, List marketIdList) => {
    if (result.isSuccess()) {
        // 호출 성공
    }
});

API Reference: IAPV4::marketConnect

#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;

IAPV4::marketConnect([=](ResultAPI const & result, vector const & marketIdList) {
    if (result.isSuccess()) {
        // 호출 성공
    }
});

API Reference: IAPV4.marketConnect

import com.hive.IAPV4
import com.hive.ResultAPI

IAPV4.marketConnect(object : IAPV4.IAPV4MarketInfoListener {
    override fun onIAPV4MarketInfo(result: ResultAPI, iapV4TypeList: ArrayList<IAPV4.IAPV4Type>?) {
        if (result.isSuccess) {
            // 호출 성공
        }
    }
})

API Reference: com.hive.IAPV4.marketConnect

import com.hive.IAPV4;
import com.hive.ResultAPI;

IAPV4.INSTANCE.marketConnect((result, iapV4TypeList) -> {
    if (result.isSuccess()) {
        // 호출 성공
    }
});

API Reference: IAPV4Interface.marketConnect

import HIVEService

IAPV4Interface.marketConnect() { result, marketIdList in
    if result.isSuccess() {
        // 호출 성공    
    }
}

API Reference: HIVEIAPV4::marketConnect

#import <HIVEService/HIVEService-Swift.h>

[HIVEIAPV4 marketConnect: ^(HIVEResultAPI *result, NSArray<NSNumber *> *marketIdList) {
    if ([result isSuccess]) {
        // 호출 성공
    } 
}];
Info

자세한 내용은 IAP 초기화를 참고하세요.

상품 목록 조회 구현

이용자가 앱 내 아이템 상점에 진입하면 판매하는 아이템 목록을 표시해야 하며, 이를 위해 상품 목록 조회를 구현합니다. 다음은 상품 목록 조회를 요청하는 예제 코드입니다.

API Reference: hive.IAPV4.getProductInfo

using hive;

IAPV4.getProductInfo((ResultAPI result, List<IAPV4Product> productInfoList, int balance) => {    
    if (result.isSuccess()) {    
        // 호출 성공    
    }    
});

API Reference: IAPV4::getProductInfo

#include <HIVE_SDK_Plugin/HIVE_CPP.h>

using namespace std;    
using namespace hive;

IAPV4::getProductInfo([=](ResultAPI const & result, vector<IAPV4Product> const & productInfoList, unsigned int balance) {    
    if (result.isSuccess()) {    
        // 호출 성공    
    }    
});

API Reference: IAPV4.getProductInfo

import com.hive.IAPV4    
import com.hive.ResultAPI

IAPV4.getProductInfo(object : IAPV4.IAPV4ProductInfoListener {    
    override fun onIAPV4ProductInfo(result: ResultAPI, iapV4ProductList: ArrayList<IAPV4.IAPV4Product>?, balance: Int) {    
        if (result.isSuccess) {    
            // 호출 성공    
        }    
    }    
})

API Reference: com.hive.IAPV4.getProductInfo

import com.hive.IAPV4    
import com.hive.ResultAPI

IAPV4.INSTANCE.getProductInfo((result, iapV4ProductList, balance) -> {    
    if (result.isSuccess()) {    
        // 호출 성공    
    }    
});

API Reference: IAPV4Interface.getProductInfo

import HIVEService

IAPV4Interface.getProductInfo() { result, productInfoList, balance in     
    if result.isSuccess() {    
        // 호출 성공    
    }    
}

API Reference: HIVEIAPV4::getProductInfo

#import <HIVEService/HIVEService-Swift.h>

[HIVEIAPV4 getProductInfo: ^(HIVEResultAPI *result, NSArray<HIVEIAPV4Product *> *productInfoList, NSUInteger balance) {    
    if ([result isSuccess]) {    
        // 호출 성공    
    }    
}];


상품 목록 조회를 수행하면 결과값 반환 시 IAPV4Product 클래스에 상품 목록 정보를 포함하여 반환합니다. 상품 정보에는 아이템 구매 요청 시 사용하는 marketPid와 통화 기호와 가격을 조합한 형태(예: $0.99)인 displayPrice 등이 있습니다.

Info

자세한 내용은 상품 목록 조회를 확인하세요.

상품 구매 구현

이용자가 앱 상점에 진입해 판매 아이템 목록을 확인한 후, 특정 아이템 구매를 누르면, 상품 ID에 해당하는 marketPid를 매개변수로 IAPV4 클래스의 purchase 매서드를 호출해 앱 마켓에 아이템 구매를 요청해야합니다. 다음은 상품 구매를 요청하는 예제 코드입니다.

API Reference: hive.IAPV4.purchase

using hive;

String marketPid = "{YOUR_PRODUCT_MARKET_PID}";    
String iapPayload = "{YOUR_CUSTOM_PAYLOAD}"    

IAPV4.purchase(marketPid, iapPayload, (ResultAPI result, IAPV4Receipt receipt) => {    
    if (result.isSuccess()) {    
        // TODO: 전달받은 receipt로 영수증 검증 요청    
    }    
});

API Reference: IAPV4::purchase

#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;    
using namespace hive;

string marketPid = "{YOUR_PRODUCT_MARKET_PID}";    
string iapPayload = "{YOUR_CUSTOM_PAYLOAD}";

IAPV4::purchase(marketPid, iapPayload, [=](ResultAPI const & result, IAPV4Receipt const & receipt) {    
    if (result.isSuccess()) {    
        // TODO: 전달받은 receipt로 영수증 검증 요청    
    }    
});

API Reference: com.hive.IAPV4.purchase

import com.hive.IAPV4    
import com.hive.ResultAPI

val marketPid = "{YOUR_PRODUCT_MARKET_PID}"    
val iapPayload = "{YOUR_CUSTOM_PAYLOAD}"

IAPV4.purchase(marketPid, iapPayload, object : IAPV4.IAPV4PurchaseListener {    
    override fun onIAPV4Purchase(result: ResultAPI, iapV4Receipt: IAPV4.IAPV4Receipt?) {    
        if (result.isSuccess) {    
            // 호출 성공    
        }    
    }    
})

API Reference: com.hive.IAPV4.purchase

import com.hive.IAPV4;    
import com.hive.ResultAPI;

String marketPid = "{YOUR_PRODUCT_MARKET_PID}";    
String iapPayload = "{YOUR_CUSTOM_PAYLOAD}";

IAPV4.INSTANCE.purchase(marketPid, iapPayload, (result, iapV4Receipt) -> {    
    if (result.isSuccess()) {    
        // 호출 성공    
    }    
});

API Reference: HIVEIAPV4::purchase:additionalInfo:handler:

import HIVEService

let marketPid = "{YOUR_PRODUCT_MARKET_PID}"    
let iapPayload = "{YOUR_CUSTOM_PAYLOAD}"    

HIVEIAPV4.purchase(marketPid, iapPayload: iapPayload) { result, receipt in    
    if result.isSuccess() {    
        // TODO: 전달받은 receipt로 영수증 검증 요청    
    }    
}

API Reference: HIVEIAPV4::purchase:additionalInfo:handler:

#import <HIVEService/HIVEService-Swift.h>

NSString *marketPid = @"{YOUR_PRODUCT_MARKET_PID}";    
NSString *iapPayload = @"{YOUR_CUSTOM_PAYLOAD}";    

[HIVEIAPV4 purchase: marketPid iapPayload: iapPayload handler: ^(HIVEResultAPI *result, HIVEIAPV4Receipt *receipt) {    
    if ([result isSuccess]) {    
        // TODO: 전달받은 receipt로 영수증 검증 요청    
    }    
}];


상품 구매 기능을 구현하기 전에, 미리 구매 메타데이터(iapPayload)를 정의할 수 있습니다. iapPayload는 앱 개발사가 원하는 형식으로 정의한 정보입니다. 이를 사용하면, 결제 시스템을 악용하는 이용자 정보를 분석하거나, 구매 시 에러가 발생해 결제는 되었지만 아이템은 지급하지 못한 상황을 해결할 수 있습니다.

Info

상품 구매에 관한 자세한 내용은 다음을 확인하세요. 구독형 아이템 구매에 관한 자세한 내용은 다음을 참고하세요.

구매 영수증 검증 구현

상품 구매를 요청하는 코드가 실행된 후, 이용자가 앱 마켓에서 결제를 완료하면 Hive SDK는 구매 영수증을 앱 클라이언트에 전달합니다. 여러분의 앱 서버는 앱 클라이언트로부터 이 영수증을 받고, 영수증이 유효한지 Hive 서버 API로 영수증을 검증해야 합니다. 영수증 검증까지 마친 후에, 앱 서버는 이용자에게 아이템을 직접 지급해야 합니다.

영수증 검증 API는 인앱 구매한 상품 영수증을 검증한 후 영수증의 정상 여부를 응답값으로 반환합니다. 응답값의 hiveiap\_transaction\_id는 영수증별로 유니크하게 발급되는 ID이기 때문에 이 값을 앱 서버에 저장하고 중복 영수증인지 체크한 후 아이템을 지급합니다.

Info

자세한 내용은 영수증 검증을 참고하세요.