ALC(Application License Checker) V2 적용
개요
ALC V2(Application License Checker V2)는 원스토어에서 제공하는 앱 라이선스 검증 서비스의 최신 버전으로, 유료 앱 및 인앱 구매 콘텐츠의 무단 사용을 방지하고, 정품 사용자만 앱을 이용할 수 있도록 보장하는 기능을 제공합니다.
프로젝트 설정
레파지토리 및 종속 항목 추가
프로젝트 최상위 gradle 파일에 원스토어 maven 주소를 등록합니다.
repositories {
    maven { url 'https://repo.onestore.net/repository/onestore-sdk-public' }
}앱의 build.gradle 파일에 원스토어 결제 라이브러리 종속 항목을 추가합니다.
dependencies {
    implementation "com.onestorecorp.sdk:sdk-licensing:2.2.1"
}<queries> 태그 설정
AndroidManifest.xml 파일에 <queries>를 설정 해야합니다. 자세한 내용은 공지사항을 참조하세요.
<queries> 태그를 설정하지 않으면 SDK에서 원스토어 서비스를 찾을 수 없습니다.
<manifest>
    <!-- 
        if your binary use ONE store's In-app SDK,
        Please make sure to declare the following query on Androidmanifest.xml. 
        Refer to the notice for more information.
        https://dev.onestore.net/devpoc/support/news/noticeView.omp?noticeId=32968
     -->
    <queries>
        <intent>
            <action android:name="com.onestore.extern.licensing.LicensingService.ACTION" />
        </intent>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data android:scheme="onestore" />
        </intent>
    </queries>
    ...
    <application>
        ...
    </application>
</manifest>스토어 선택을 위한 개발자 옵션 설정
v2.2.0 업데이트 - 글로벌 스토어 선택 기능 추가
 ALC SDK 2.2.0 부터 아래와 같이 onestore:dev_option의 android:value 값을 설정하면, SDK와 연동되는 스토어 앱을 지정 할 수 있습니다.
<manifest>
    <application>
        <meta-data android:name="onestore:dev_option" android:value="onestore_01" />
    </application>
</manifest>onestore_00
대한민국 (South Korea) (기본값)
onestore_01
싱가포르, 타이완 (Singapore, Taiwan)
onestore_02
미국 – Digital Turbine (United States)
주의: 배포 버전의 바이너리에서는 이 옵션을 반드시 제거해주세요.
ALC 라이브러리 적용하기
로그 레벨 설정
개발 단계에서 로그 레벨을 설정하여 SDK의 데이터의 흐름을 좀 더 자세히 노출할 수 있습니다. android.util.Log에 정의된 값을 기반으로 동작합니다.
/**
 * Set the log level.<br/>
 * {@link Log#VERBOSE}, {@link Log#DEBUG}, {@link Log#INFO},
 * {@link Log#WARN}, {@link Log#ERROR}
 * @param level int
 */
com.gaa.sdk.base.Logger.setLogLevel(2)VERBOSE
2
DEBUG
3
INFO (default)
4
WARN
5
ERROR
6
배포 빌드 버전에서는 보안에 취약할 수 있으니 이 옵션을 삭제해야 합니다.
원스토어 로그인 하기
GaaSignInClient 초기화
GaaSignInClient 초기화GaaSignInClient는 원스토어 로그인을 하기 위한 라이브러리입니다. getClient() 통해 인스턴스를 생성합니다.
val signInClient = GaaSignInClient.getClient(activity)GaaSignInClient signInClient = GaaSignInClient.getClient(activity);백그라운드에서 로그인하기
silentSignIn() 통해 백그라운도 로그인을 호출합니다.
사용자가 이미 원스토어 계정에 로그인 되어있을 경우 이후 부터는 백그라운드에서 토큰로그인을 시도합니다. 성공 또는 실패에 대한 결과값으로 SignInResult 객체로 응답을 받습니다.
signInClient.silentSignIn { signInResult ->
  
}signInClient.silentSignIn(new OnAuthListener() {
    @Override
    public void onResponse(@NonNull SignInResult signInResult) {
        
    }
});포그라운드에서 로그인하기
slientSignIn()과 달리 해당 함수는 UiThread 에서만 호출해야 합니다.
기본적으로 먼저 백그라운드 로그인을 시도하지만 실패에 대한 처리를 SDK에서 전담하여 처리합니다. 이 후, 로그인 화면을 띄워 사용자에게 로그인을 유도합니다.
signInClient.launchSignInFlow(activity) { signInResult ->
  
}signInClient.launchSignInFlow(activity, new OnAuthListener() {
    @Override
    public void onResponse(@NonNull SignInResult signInResult) {
        
    }
});AppLicenseChecker 초기화
AppLicenseChecker란?
AppLicenseChecker는 개발사가 유료 앱을 판매할 때 라이선스 무단 사용을 방지하고 정품 사용자만 앱을 이용할 수 있도록 보호하는 기능을 제공합니다. 이를 통해 앱이 불법적으로 배포되거나 무단으로 사용되는 것을 차단할 수 있습니다.
초기화 방법
유효한 라이선스를 확인하려면 AppLicenseChecker의 인스턴스를 생성해야 합니다.
초기화 과정에서는 개발자 센터에서 발급받은 라이선스 키를 전달해야 하며, 라이선스 검증 결과는 LicenseCheckerListener를 통해 확인할 수 있습니다. 따라서, AppLicenseChecker 초기화 시 리스너 객체도 함께 설정해야 합니다.
override fun onCreate(savedInstanceState: Bundle?) {
	super.onCreate(savedInstanceState)
	val appLicenseChecker = AppLicenseChecker.get(this@MainActivity, getString(R.string.public_key, new AppLicenseListener())
}
...
inner class AppLicenseListener : LicenseCheckerListener {
	override fun granted(license: String, signature: String) {}
	override fun denied() {}  
	
	override fun error(code: Int, message: String) {}
} @Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	...
	appLicenseChecker = AppLicenseChecker.get(MainActivity.this, getString(R.string.publick_key, new AppLicenseListener());
}
...
private class AppLicenseListener implements LicenseCheckerListener {
	@Override
	public void granted(String license, String signature) {}
 	@Override
	public void denied() {}  
	
	@Override
	public void error(int code, String message) {}
} 라이선스 키 발급
라이선스 키는 개발자 센터에서 앱을 등록할 때 자동으로 발급됩니다.
보안 강화를 위해 라이선스 키를 앱 코드에 직접 포함하지 않고, 서버를 통해 안전하게 전달받아 사용하는 것을 권장합니다.
LicenseCheckerListener 설정
LicenseCheckerListener 등록
LicenseCheckerListener 등록AppLicenseChecker를 초기화할 때, 반드시 LicenseCheckerListener를 등록해야 합니다.
이 리스너는 라이선스 검증 결과를 처리하는 인터페이스로, 검증이 완료되면 반드시 해당 인터페이스의 메서드 중 하나가 호출됩니다.
LicenseCheckerListener 메서드
LicenseCheckerListener 메서드LicenseCheckerListener는 다음 세 가지 메서드를 제공합니다.
granted()
라이선스가 정상적으로 확인된 경우 호출됩니다.
denied()
라이선스가 유효하지 않거나 인증에 실패한 경우 호출됩니다.
error(int errorCode,String errorMessage)
라이선스 검증 중 오류가 발생한 경우 호출되며, 에러 코드와 메시지를 함께 제공합니다.
에러 코드 참고
error() 메서드에서 제공하는 에러 코드 및 응답 메시지에 대한 상세 내용은 아래 응답 코드 표를 참고하세요.
class AppLicenseListener : LicenseCheckerListener {
    override fun granted(license: String, signature: String) {
        // License check successful
    }
    override fun denied() {
        // License check denied
    }  
    
    override fun error(code: Int, message: String) {
        // License check error occurred
    }
}public class AppLicenseListener implements LicenseCheckerListener {
    @Override
    public void granted(String license, String signature) {
        // License check successful
    }
    @Override
    public void denied() {
        // License check denied
    }
    @Override
    public void error(int code, String message) {
        // License check error occurred
    }
}라이선스 검증 요청하기
앱에서 라이선스 검증을 요청하면, 원스토어 서버와 통신하여 사용자의 구매 라이선스를 확인합니다. 그러나 네트워크 장애, 비행기 모드 등의 이유로 서버에 접근할 수 없는 경우 앱 실행이 차단될 수 있습니다.
이를 방지하기 위해, 일반적으로 캐시 정책을 사용하여 로컬에 저장된 라이선스를 기반으로 앱을 실행할 수 있도록 보장합니다.
만약 캐시된 라이선스를 사용하지 않고 실시간 검증을 원할 경우, strictQueryLicense API를 사용하면 항상 원스토어 서버에서 최신 라이선스를 조회할 수 있습니다.
QueryLicense API (Cached API) 호출
캐시 정책을 적용하여 동작하는 라이선스 검증 API입니다.
- 기본적으로 원스토어 서버와 통신하여 사용자의 구매 라이선스를 확인합니다. 
- 그러나 네트워크 장애, 비행기 모드 등으로 서버에 접근할 수 없는 경우, 로컬에 저장된 라이선스를 이용하여 앱 실행을 보장합니다. 
- 로컬 캐시에 저장된 라이선스는 유효 기간 내에서만 사용 가능하며, 만료되면 서버와 다시 통신해야 합니다. 
이 방식은 사용자 경험을 개선하고, 일시적인 네트워크 문제로 인해 앱 실행이 차단되는 것을 방지하는 데 유용합니다.
appLicenseChecker.queryLicense()appLicenseChecker.queryLicense();StrictQueryLicense API (Non-Cached API) 호출
StrictQueryLicense API는 캐시된 라이선스를 사용하지 않고, 항상 원스토어 서버에서 최신 라이선스를 조회하는 방식입니다.
- 캐시를 사용하지 않기 때문에, 항상 최신 라이선스 정보를 기반으로 검증이 이루어집니다. 
- 그러나 네트워크 장애, 비행기 모드 등의 상황에서는 원스토어 서버에 접근할 수 없기 때문에, 라이선스 검증이 실패하면 앱을 사용할 수 없습니다. 
- 보안이 중요한 경우 유용할 수 있지만, 네트워크 문제로 인해 앱 사용이 제한될 수 있으므로 사용 목적에 맞게 신중히 선택해야 합니다. 
appLicenseChecker.strictQueryLicense()appLicenseChecker.strictQueryLicense();연결 해제
원스토어 서비스와의 불필요한 연결을 방지하고 리소스를 적절히 해제하기 위해, 더 이상 라이선스 검증이 필요하지 않을 경우 AppLicenseChecker의 destroy() 메서드를 호출하여 연결을 해제하는 것을 권장합니다.
이렇게 하면 메모리 누수를 방지하고, 불필요한 서비스 호출을 차단하여 앱의 성능을 최적화할 수 있습니다.
appLicenseChecker.destroy()appLicenseChecker.destroy();StoreEnvironment API 기능 추가
StoreEnvironment.getStoreType() API는 SDK가 탑재된 애플리케이션이 원스토어를 통해 설치되었는지를 판단하는 기능을 제공합니다.
Store Type 정의
해당 API는 StoreType을 반환하며, 아래 네 가지 값 중 하나를 가집니다.
StoreType.UNKNOWN
0
앱 설치 스토어 정보를 알 수 없음 (APK 직접 설치, 출처 불명 등)
StoreType.ONESTORE
1
ONE Store에서 설치됨 (또는 개발자 옵션이 활성화된 경우)
StoreType.VENDING
2
Google Play Store에서 설치됨
StoreType.ETC
3
기타 스토어에서 설치됨
API 사용 방법
해당 API는 StoreEnvironment.getStoreType()을 호출하여 사용할 수 있습니다.
import com.gaa.sdk.base.StoreEnvironment
val storeType = StoreEnvironment.getStoreType()
when (storeType) {
    StoreType.ONESTORE -> println("ONE Store에서 설치된 앱입니다.")
    StoreType.VENDING -> println("Google Play Store에서 설치된 앱입니다.")
    StoreType.ETC -> println("기타 스토어에서 설치된 앱입니다.")
    StoreType.UNKNOWN -> println("스토어 정보를 알 수 없습니다.")
}import com.gaa.sdk.base.StoreEnvironment;
int storeType = StoreEnvironment.getStoreType();
switch (storeType) {
    case StoreType.ONESTORE:
        System.out.println("ONE Store에서 설치된 앱입니다.");
        break;
    case StoreType.VENDING:
        System.out.println("Google Play Store에서 설치된 앱입니다.");
        break;
    case StoreType.ETC:
        System.out.println("기타 스토어에서 설치된 앱입니다.");
        break;
    case StoreType.UNKNOWN:
    default:
        System.out.println("스토어 정보를 알 수 없습니다.");
        break;
}스토어 판단 기준
이 API는 세 가지 방법을 통해 설치된 스토어를 판별합니다.
- 원스토어 마켓 서명을 통해 배포된 경우 - 원스토어의 마켓 서명을 통한 배포 여부를 확인하여, 원스토어에서 설치된 앱인지 확인합니다. 
 
- Installer Package Name을 기반으로 판별 - 원스토어의 마켓 서명을 통해 배포되지 않은 경우, PackageManager.getInstallerPackageName() API를 이용하여 앱 설치 시 사용된 스토어 정보를 확인합니다. 
 
- 개발자 옵션( - onestore:dev_option)이 활성화된 경우- onestore:dev_option 이 설정 되어있으면 무조건 StoreType.ONESTORE로 응답합니다. 
 
활용 예시
스토어별 UI 차별화 적용
원스토어와 다른 앱 마켓에서 제공하는 결제 시스템이 다를 경우, UI를 다르게 설정할 수 있습니다.
if (StoreEnvironment.getStoreType() == StoreType.ONESTORE) {
    showOneStorePaymentUI()
} else {
    showDefaultPaymentUI()
}스토어별 기능 차단
특정 기능을 원스토어에서만 사용하도록 설정할 수 있습니다.
if (StoreEnvironment.getStoreType() != StoreType.ONESTORE) {
    println("이 기능은 ONE Store에서만 사용할 수 있습니다.")
    return
}
enableOneStoreExclusiveFeature()응답 코드
다음 표는 원스토어 ALC 라이브러리에서 앱으로 전달되는 에러 응답 코드 및 메시지입니다.
라이브러리를 사용하는 앱에서는 각 응답 코드에 대해 적절한 처리를 수행해야 합니다.
RESULT_OK
0
성공
Success
ERROR_CLIENT_NOT_ENABLED
1010
원스토어에 연결할 수 없습니다. 원스토어 앱 실행이 필요합니다.
Unable to connect to the store. ONE store app execution is required.
ERROR_SERVICE_UNAVAILABLE
2000
서비스를 이용할 수 없는 상태입니다.
The service is unavailable.
원스토어에 문의해주세요.
ERROR_DATA_PARSING
2001
파라메터가 유효하지 않습니다.
Parameter is invalid.
원스토어에 문의해주세요.
ERROR_SIGNATURE_VERIFICATION
2002
라이선스 키가 맞지 않거나 구매 내역이 없는 유저 입니다.
The license key is not matched, or the user does not have a purchase history.
원스토어 개발자 센터에서 라이선스 키를 확인해주세요.
ERROR_SERVICE_TIMEOUT
2100
서비스 응답이 없습니다.
There is no response.
네트워크 상태를 체크해주세요.
ERROR_USER_LOGIN_CANCELD
2101
사용자가 로그인을 취소하였습니다.
User canceled login.
원스토어 로그인을 해주세요.
ERROR_INSTALL_USER_CANCELED
2103
원스토어 서비스 설치를 취소하였습니다.
ONE store install has been canceled. Do you want to ONE store installation?
원스토어를 설치해주세요.
ERROR_NOT_FOREGROUND
2104
백그라운드 서비스에서는 진행할 수 없습니다.
Can not run the context is not instance of Activity.
RESULT_UNKNOWN
-1
알 수 없는 오류가 발생하였습니다.
An unknown error occurred.
원스토어에 문의해주세요.
RESULT_USER_CANCELED
1
사용자가 로그인을 취소하였습니다.
User canceled login.
원스토어 로그인을 해주세요.
RESULT_SERVICE_UNAVAILABLE
2
단말 또는 서버 네트워크 오류가 발생하였습니다.
A device or server network error has occurred.
네트워크 상태를 체크해주세요.
RESULT_ALC_UNAVAILABLE
3
ALC api 버전 정보가 낮습니다. 해당 라이브러리를 업데이트 해주세요.
The ALC api has the lower version. Please update the corresponding library.
ALC 라이브러리를 최신버전으로 업데이트 해주세요.
RESULT_DEVELOPER_ERROR
5
파라메터가 유효하지 않습니다.
The parameter is invalid.
원스토어에 문의해주세요.
RESULT_ERROR
6
정의되지 않은 기타 오류가 발생하였습니다.
An unknown error occurred.
원스토어에 문의해주세요.
Last updated

