원스토어 결제
This commit is contained in:
parent
97c5381fea
commit
e07d40d684
Binary file not shown.
|
|
@ -51,7 +51,7 @@ public static class AutoBuild
|
|||
[MenuItem("AutoBuild/EmptySymbol")]
|
||||
static void EmptySymbol()
|
||||
{
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, "");
|
||||
PlayerSettings.SetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.Android, "");
|
||||
}
|
||||
[MenuItem("AutoBuild/Set_AndroidKeyStore")]
|
||||
static void Set_AndroidKeyStore()
|
||||
|
|
@ -73,13 +73,24 @@ public static class AutoBuild
|
|||
BuildStart("AndroidData/GoStop_Test_" + Application.version + "_(" + PlayerSettings.Android.bundleVersionCode + ").apk", BuildTarget.Android);
|
||||
PlayerSettings.bundleVersion = curVer;
|
||||
}
|
||||
[MenuItem("AutoBuild/Build OneStore APK")]
|
||||
static void Build_APK_OneStore()
|
||||
{
|
||||
Common(BuildTargetGroup.Android, BuildTarget.Android);
|
||||
//PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel23;
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.Android, "OneStore");
|
||||
EditorUserBuildSettings.buildAppBundle = false;
|
||||
BuildStart("AndroidData/GoStop_Test_" + Application.version + "_(" + PlayerSettings.Android.bundleVersionCode + ").apk", BuildTarget.Android);
|
||||
EmptySymbol();
|
||||
}
|
||||
[MenuItem("AutoBuild/Build Live AAB")]
|
||||
static void Build_AAB()
|
||||
{
|
||||
++PlayerSettings.Android.bundleVersionCode;
|
||||
Common(BuildTargetGroup.Android, BuildTarget.Android);
|
||||
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, "FGB_LIVE");
|
||||
PlayerSettings.SetScriptingDefineSymbols(UnityEditor.Build.NamedBuildTarget.Android, "");
|
||||
EditorUserBuildSettings.buildAppBundle = true;
|
||||
BuildStart("AndroidData/GoStop_Live_" + Application.version + "_(" + PlayerSettings.Android.bundleVersionCode + ").aab", BuildTarget.Android);
|
||||
EmptySymbol();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7ab68dd3fa82e4b4eb8e4795d6fbb273
|
||||
guid: f73007bb22bf455458373bb61c6817cb
|
||||
labels:
|
||||
- gvh
|
||||
- gvh_version-9.5.0
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f962e167eaa8d4a489e63d1db5839efd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e87bd305d2c974f279321dd6dbe03ec6
|
||||
folderAsset: yes
|
||||
timeCreated: 1458317573
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
[InitializeOnLoad]
|
||||
public class AndroidKeystoreLoader
|
||||
{
|
||||
static AndroidKeystoreLoader()
|
||||
{
|
||||
string keystorePass, keyaliasName, keyaliasPass;
|
||||
|
||||
keystorePass = KeystoreHelper.ReadPrefs(KeystoreHelper.KEYSTOREPASS);
|
||||
keyaliasName = KeystoreHelper.ReadPrefs(KeystoreHelper.KEYALIASNAME);
|
||||
keyaliasPass = KeystoreHelper.ReadPrefs(KeystoreHelper.KEYALIASPASS);
|
||||
|
||||
PlayerSettings.Android.keystorePass = keystorePass;
|
||||
PlayerSettings.Android.keyaliasName = keyaliasName;
|
||||
PlayerSettings.Android.keyaliasPass = keyaliasPass;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
|
||||
class KeystoreHelper : EditorWindow {
|
||||
|
||||
public const string KEYSTOREPASS = "AKS_keystorePass_";
|
||||
public const string KEYALIASNAME = "AKS_keyaliasName_";
|
||||
public const string KEYALIASPASS = "AKS_keyaliasPass_";
|
||||
|
||||
private string keystorePass = "";
|
||||
private string keyaliasName = "";
|
||||
private string keyaliasPass = "";
|
||||
|
||||
[MenuItem ("Window/Keystore Helper")]
|
||||
public static void ShowWindow () {
|
||||
EditorWindow.GetWindow(typeof(KeystoreHelper));
|
||||
}
|
||||
|
||||
void OnEnable() {
|
||||
keystorePass = ReadPrefs(KEYSTOREPASS);
|
||||
keyaliasName = ReadPrefs(KEYALIASNAME);
|
||||
keyaliasPass = ReadPrefs(KEYALIASPASS);
|
||||
|
||||
PlayerSettings.Android.keystorePass = keystorePass;
|
||||
PlayerSettings.Android.keyaliasName = keyaliasName;
|
||||
PlayerSettings.Android.keyaliasPass = keyaliasPass;
|
||||
}
|
||||
|
||||
void OnDisable() {
|
||||
WritePrefs(KEYSTOREPASS, keystorePass);
|
||||
WritePrefs(KEYALIASNAME, keyaliasName);
|
||||
WritePrefs(KEYALIASPASS, keyaliasPass);
|
||||
|
||||
PlayerSettings.Android.keystorePass = keystorePass;
|
||||
PlayerSettings.Android.keyaliasName = keyaliasName;
|
||||
PlayerSettings.Android.keyaliasPass = keyaliasPass;
|
||||
}
|
||||
|
||||
public static string ReadPrefs(string _key) {
|
||||
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
string key = _key+Md5Sum(codeBase);
|
||||
return Decode(EditorPrefs.GetString(key, ""));
|
||||
}
|
||||
|
||||
public static void WritePrefs(string _key, string value) {
|
||||
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
|
||||
string key = _key + Md5Sum(codeBase);
|
||||
EditorPrefs.SetString(key, Encode(value));
|
||||
}
|
||||
|
||||
void OnGUI () {
|
||||
GUILayout.Label ("Android Keystore", EditorStyles.boldLabel);
|
||||
keystorePass = EditorGUILayout.PasswordField ("Keystore Password", keystorePass);
|
||||
keyaliasName = EditorGUILayout.TextField ("Key Alias Name", keyaliasName);
|
||||
keyaliasPass = EditorGUILayout.PasswordField ("Key Alias Password", keyaliasPass);
|
||||
}
|
||||
|
||||
private static string Md5Sum(string strToEncrypt)
|
||||
{
|
||||
System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
|
||||
byte[] bytes = ue.GetBytes(strToEncrypt);
|
||||
|
||||
// encrypt bytes
|
||||
System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
|
||||
byte[] hashBytes = md5.ComputeHash(bytes);
|
||||
|
||||
// Convert the encrypted bytes back to a string (base 16)
|
||||
string hashString = "";
|
||||
|
||||
for (int i = 0; i < hashBytes.Length; i++)
|
||||
{
|
||||
hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
|
||||
}
|
||||
|
||||
return hashString.PadLeft(32, '0');
|
||||
}
|
||||
|
||||
private static string Encode(string inputText) {
|
||||
byte[] bytesToEncode = Encoding.UTF8.GetBytes (inputText);
|
||||
return Convert.ToBase64String (bytesToEncode);
|
||||
}
|
||||
|
||||
private static string Decode(string encodedText) {
|
||||
byte[] decodedBytes = Convert.FromBase64String (encodedText);
|
||||
return Encoding.UTF8.GetString (decodedBytes);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -1,8 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4a989aa6f253d4fba9884871e22997d1
|
||||
timeCreated: 1460876014
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -28,6 +28,5 @@
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
데이터 저장, 불러오기 (구글 플레이센터로 변경) - 확인 필요
|
||||
|
||||
원스토어 검수 빌드 후 원스토어 결제 추가
|
||||
원스토어 검수 빌드 후 원스토어 결제 추가
|
||||
한달에 70만원 초과 구매 체크
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a38b4c520db724670b30b04da0be7c01
|
||||
guid: 204651c98036c4d3daa51358c1f71e07
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9b15d8887bf22409089afedfc3215b46
|
||||
guid: c912baa65aed04a0695d7deeb9e26f9f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5e737082478de4f8cb850a38f00c2488
|
||||
guid: 45866b059e1ac4748ac1f5997e7563ac
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<dependencies>
|
||||
<androidPackages>
|
||||
<repositories>
|
||||
<repository>https://repo.onestore.co.kr/repository/onestore-sdk-public</repository>
|
||||
<repository>https://repo.onestore.net/repository/onestore-sdk-public</repository>
|
||||
</repositories>
|
||||
<androidPackage spec="com.onestorecorp.sdk:sdk-licensing:2.1.0" />
|
||||
<androidPackage spec="com.onestorecorp.sdk:sdk-licensing:2.2.1" />
|
||||
</androidPackages>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 22835d64d81424a4a973b971bdf001f7
|
||||
guid: 3a871155c97ce4cb0befa3037f342edc
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5368639f6f8b94a3fa108ae0442ac776
|
||||
guid: e8430a97b91bb4c4986ed7a70c40bfd3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d25a6068257e1484a80f45db0abfa7a2
|
||||
guid: 5ca8f8998e0534e088a4771ae1fc1909
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b0be8215d7b2841d2ba7a2c0920485b1
|
||||
guid: 0c113be81d6ec415a800631bc1b1c9e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 43b9607f255614a8d8bc960e200a6eaf
|
||||
guid: 586e06c7044794af6b82b88f0dcf0b6b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c0c7575908d62447bbbb66c6f846f505
|
||||
guid: 2812dfc9335dd4ca680f70b95551cf18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2272b91e6c0354de4af84ac36237d115
|
||||
guid: 51ff5605005df46c3aeaed3994057a54
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace OneStore.Alc.Internal
|
|||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public const string Version = "2.1.0";
|
||||
public const string Version = "2.2.1";
|
||||
public static readonly TimeSpan AsyncTimeout = TimeSpan.FromMilliseconds(30000);
|
||||
|
||||
public const string AppLicenseChecker = "com.onestore.extern.licensing.AppLicenseCheckerImpl";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ad6e43bd6f5be4ade91f9331f2143270
|
||||
guid: 9b59d64b9c466404faf6ad9e76a2bd69
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c1dd2cc05dab6464e8438052ec61fb93
|
||||
guid: 6a637d767706346c2b6ccc07ce3dc9ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -4,31 +4,38 @@ using System;
|
|||
using OneStore.Common;
|
||||
using OneStore.Alc.Internal;
|
||||
using UnityEngine;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
|
||||
namespace OneStore.Alc
|
||||
{
|
||||
public class OneStoreAppLicenseCheckerImpl
|
||||
{
|
||||
private AndroidJavaObject _appLicenseChecker;
|
||||
private readonly OneStoreLogger _logger;
|
||||
|
||||
private readonly string _licenseKey;
|
||||
|
||||
private LicenseCheckerListener _listener;
|
||||
|
||||
private ILicenseCheckCallback _callback;
|
||||
|
||||
public OneStoreAppLicenseCheckerImpl(string licenseKey) {
|
||||
if (Application.platform != RuntimePlatform.Android) {
|
||||
/// <summary>
|
||||
/// Initializes the ONE store App License Checker with the provided license key.
|
||||
/// Ensures that the platform is Android before proceeding.
|
||||
/// </summary>
|
||||
/// <param name="licenseKey">The license key required for validation.</param>
|
||||
public OneStoreAppLicenseCheckerImpl(string licenseKey)
|
||||
{
|
||||
if (Application.platform != RuntimePlatform.Android)
|
||||
{
|
||||
throw new PlatformNotSupportedException("Operation is not supported on this platform.");
|
||||
}
|
||||
|
||||
_logger = new OneStoreLogger();
|
||||
_licenseKey = licenseKey;
|
||||
}
|
||||
|
||||
// ALC 연결 초기화
|
||||
public void Initialize(ILicenseCheckCallback callback) {
|
||||
/// <summary>
|
||||
/// Initializes the App License Checker (ALC) and establishes a connection.
|
||||
/// </summary>
|
||||
/// <param name="callback">Callback interface for handling license check results.</param>
|
||||
public void Initialize(ILicenseCheckCallback callback)
|
||||
{
|
||||
_callback = callback;
|
||||
_appLicenseChecker = new AndroidJavaObject(Constants.AppLicenseChecker, _licenseKey);
|
||||
|
||||
|
|
@ -38,6 +45,7 @@ namespace OneStore.Alc
|
|||
_listener.Denied += OnDenied;
|
||||
_listener.Error += OnError;
|
||||
|
||||
// Sets up the license checker with the Unity activity context and the listener.
|
||||
_appLicenseChecker.Call(
|
||||
Constants.AppLicenseCheckerSetupMethod,
|
||||
context,
|
||||
|
|
@ -45,37 +53,63 @@ namespace OneStore.Alc
|
|||
);
|
||||
}
|
||||
|
||||
// Cached API 호출
|
||||
// 캐시된 라이센스를 이용할 경우 사용한다.
|
||||
public void QueryLicense() {
|
||||
_logger.Log("do queryLicense");
|
||||
/// <summary>
|
||||
/// Calls the Cached API to query the license.
|
||||
/// Uses cached license information when available.
|
||||
/// </summary>
|
||||
public void QueryLicense()
|
||||
{
|
||||
Logger.Log("do queryLicense");
|
||||
_appLicenseChecker.Call(Constants.AppLicenseCheckerQueryLicenseMethod);
|
||||
}
|
||||
|
||||
// Non-Cached API 호출
|
||||
// 캐시된 라이센스를 이용하지 않고 사용할 경우 사용한다.
|
||||
public void StrictQueryLicense() {
|
||||
_logger.Log("do strictQueryLicense");
|
||||
/// <summary>
|
||||
/// Calls the Non-Cached API to query the license.
|
||||
/// Does not use cached license information and forces a fresh validation.
|
||||
/// </summary>
|
||||
public void StrictQueryLicense()
|
||||
{
|
||||
Logger.Log("do strictQueryLicense");
|
||||
_appLicenseChecker.Call(Constants.AppLicenseCheckerStrickQueryLicenseMethod);
|
||||
}
|
||||
|
||||
// ALC 연결 해제
|
||||
public void Destroy() {
|
||||
_logger.Log("do destroy");
|
||||
/// <summary>
|
||||
/// Disconnects and releases resources related to the App License Checker (ALC).
|
||||
/// </summary>
|
||||
public void Destroy()
|
||||
{
|
||||
Logger.Log("do destroy");
|
||||
_appLicenseChecker.Call(Constants.AppLicenseCheckerDestroy);
|
||||
}
|
||||
private void OnGranted(string license, string signature) {
|
||||
|
||||
/// <summary>
|
||||
/// Callback triggered when the license is successfully granted.
|
||||
/// </summary>
|
||||
/// <param name="license">The granted license key.</param>
|
||||
/// <param name="signature">The license signature for verification.</param>
|
||||
private void OnGranted(string license, string signature)
|
||||
{
|
||||
_callback.OnGranted(license, signature);
|
||||
}
|
||||
|
||||
private void OnDenied() {
|
||||
/// <summary>
|
||||
/// Callback triggered when the license validation is denied.
|
||||
/// </summary>
|
||||
private void OnDenied()
|
||||
{
|
||||
_callback.OnDenied();
|
||||
}
|
||||
|
||||
private void OnError(int code, string message) {
|
||||
/// <summary>
|
||||
/// Callback triggered when an error occurs during license validation.
|
||||
/// </summary>
|
||||
/// <param name="code">The error code returned.</param>
|
||||
/// <param name="message">A message describing the error.</param>
|
||||
private void OnError(int code, string message)
|
||||
{
|
||||
_callback.OnError(code, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b3b4c2e72d54a47089f9924b864c1073
|
||||
guid: 67da1af35e6ff4d7696b6e38fac9e567
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23c72fe8a92df4875bbe0b34fd3baf78
|
||||
guid: 7c7dbd20a57f34f549514b36c28c2464
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 80a4911cfab194fc0bfd87f745cba5de
|
||||
guid: 865f0763c3a514f71952dafdcdd70025
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 88896edd6f04a49948dc1bce81c814ac
|
||||
guid: 5fddbfe50d40c4e42b3ef7bc7b0a4007
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 37cb852ebcdd54283a52d99a5cc86f96
|
||||
guid: 5ea618f5f42c04bb4b0fbe8a4e06bc28
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 59f7259c06ccb4c589db49c97df7a643
|
||||
guid: 4591019618cbc44098c4780faff6edab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 67a438630cf644db58c0badde6a4d803
|
||||
guid: d281333515ded4eb491b21fc3cd2ca4f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,16 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using OneStore.Common;
|
||||
using OneStore.Auth;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
|
||||
namespace OneStore.Auth.Internal
|
||||
{
|
||||
public class AuthHelper
|
||||
public static class AuthHelper
|
||||
{
|
||||
private readonly OneStoreLogger _logger;
|
||||
public AuthHelper(OneStoreLogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the SignIn results returned by Gaa Auth Client.
|
||||
/// </summary>
|
||||
/// <returns> The SignInResult that indicates the outcome of the Java SignInResult. </returns>
|
||||
public SignInResult ParseJavaSignInpResult(AndroidJavaObject javaSignInResult)
|
||||
public static SignInResult ParseJavaSignInpResult(AndroidJavaObject javaSignInResult)
|
||||
{
|
||||
var code = javaSignInResult.Call<int>("getCode");
|
||||
var message = javaSignInResult.Call<string>("getMessage");
|
||||
|
|
@ -29,7 +22,7 @@ namespace OneStore.Auth.Internal
|
|||
/// Parses the SignInResults returned by Gaa SignIn Client.
|
||||
/// </summary>
|
||||
/// <returns>Returns the code value of the SignInResult in ResponseCode.</returns>
|
||||
public ResponseCode GetResponseCodeFromSignInResult(SignInResult signInResult)
|
||||
public static ResponseCode GetResponseCodeFromSignInResult(SignInResult signInResult)
|
||||
{
|
||||
var resultResponseCode = ResponseCode.RESULT_ERROR;
|
||||
try
|
||||
|
|
@ -38,11 +31,11 @@ namespace OneStore.Auth.Internal
|
|||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
_logger.Error("Missing response code, return ResponseCode.RESULT_ERROR.");
|
||||
Logger.Error("Missing response code, return ResponseCode.RESULT_ERROR.");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
_logger.Error("Unknown response code {0}, return ResponseCode.RESULT_ERROR.", signInResult.Code);
|
||||
Logger.Error("Unknown response code {0}, return ResponseCode.RESULT_ERROR.", signInResult.Code);
|
||||
}
|
||||
return resultResponseCode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3f5d217fdb8804701ba32cd03e453cee
|
||||
guid: a1f867c7b662d4b22933c64ffc9ce2e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace OneStore.Auth.Internal
|
|||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public const string Version = "1.1.2";
|
||||
public const string Version = "1.2.1";
|
||||
|
||||
public static readonly TimeSpan AsyncTimeout = TimeSpan.FromMilliseconds(30000);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 027b0062071924b73be50dbe31e00d63
|
||||
guid: 58c615962d2e144dea4a9517a4ad1d80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b51bc302fe47f44ffba8d75820917107
|
||||
guid: 22253330bda434f55a0401ca5944c271
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -5,35 +5,54 @@ using System;
|
|||
using OneStore.Common;
|
||||
using OneStore.Auth.Internal;
|
||||
using UnityEngine;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
|
||||
namespace OneStore.Auth
|
||||
{
|
||||
public class OneStoreAuthClientImpl
|
||||
{
|
||||
private AndroidJavaObject _signInClient;
|
||||
private readonly OneStoreLogger _logger;
|
||||
private readonly AuthHelper _authHelper;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the ONE store authentication client.
|
||||
/// Ensures that the platform is Android before proceeding.
|
||||
/// </summary>
|
||||
public OneStoreAuthClientImpl()
|
||||
{
|
||||
if (Application.platform != RuntimePlatform.Android)
|
||||
{
|
||||
throw new PlatformNotSupportedException("Operation is not supported on this platform.");
|
||||
}
|
||||
|
||||
_logger = new OneStoreLogger();
|
||||
_authHelper = new AuthHelper(_logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to sign in silently using a stored login token.
|
||||
/// This method can only be called in the background.
|
||||
/// </summary>
|
||||
/// <param name="callback">Callback function to handle the sign-in result.</param>
|
||||
public void SilentSignIn(Action<SignInResult> callback)
|
||||
{
|
||||
SignInInternal(true, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to sign in using the stored login token first.
|
||||
/// If silent login fails, a login screen is displayed to prompt the user to log in.
|
||||
/// This method must be called in the foreground.
|
||||
/// </summary>
|
||||
/// <param name="callback">Callback function to handle the sign-in result.</param>
|
||||
public void LaunchSignInFlow(Action<SignInResult> callback)
|
||||
{
|
||||
SignInInternal(false, callback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the sign-in process.
|
||||
/// If `isSilent` is true, a silent login is attempted.
|
||||
/// If `isSilent` is false or the silent login fails, a login screen is displayed.
|
||||
/// </summary>
|
||||
/// <param name="isSilent">Determines whether the sign-in should be silent.</param>
|
||||
/// <param name="callback">Callback function to return the sign-in result.</param>
|
||||
private void SignInInternal(bool isSilent, Action<SignInResult> callback)
|
||||
{
|
||||
var context = JniHelper.GetApplicationContext();
|
||||
|
|
@ -42,11 +61,11 @@ namespace OneStore.Auth
|
|||
|
||||
var authListener = new OnAuthListener();
|
||||
authListener.OnAuthResponse += (javaSignInResult) => {
|
||||
var signInResult = _authHelper.ParseJavaSignInpResult(javaSignInResult);
|
||||
var responseCode = _authHelper.GetResponseCodeFromSignInResult(signInResult);
|
||||
var signInResult = AuthHelper.ParseJavaSignInpResult(javaSignInResult);
|
||||
var responseCode = AuthHelper.GetResponseCodeFromSignInResult(signInResult);
|
||||
if (responseCode != ResponseCode.RESULT_OK)
|
||||
{
|
||||
_logger.Error("Failed to signIn with error code {0} and message: {1}", signInResult.Code, signInResult.Message);
|
||||
Logger.Error("Failed to signIn with error code {0} and message: {1}", signInResult.Code, signInResult.Message);
|
||||
}
|
||||
|
||||
RunOnMainThread(() => callback?.Invoke(signInResult));
|
||||
|
|
@ -95,6 +114,10 @@ namespace OneStore.Auth
|
|||
// );
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// Runs the provided action on the main thread.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on the main thread.</param>
|
||||
private void RunOnMainThread(Action action)
|
||||
{
|
||||
OneStoreDispatcher.RunOnMainThread(() => action());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 280e837976a7c4756b3e0192e35e2f47
|
||||
guid: a9230c0d3e676444fbaf4c6c5a3307e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b25dbdcc8597f45a8a4b91aabb30699b
|
||||
guid: 2dce71f6a2a1f4749b65c5fd1f63d10d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dc2db6a2e4d914f69887793389752e1a
|
||||
guid: 4915e45c611874c7ebd04bbfe73351cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dbbed83b03870418fadb93987e8444e3
|
||||
guid: 1a1f1e2fd32df4b41aebf90b5a83074b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9ecc0d0eb034b4728b627f98121eaf98
|
||||
guid: 84eca2a2ddc984d44a706d98801f3906
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -22,3 +22,7 @@
|
|||
-keep class com.gaa.sdk.base.ResultListener { *; }
|
||||
|
||||
-keep class com.gaa.sdk.base.Utils { *; }
|
||||
|
||||
-keep class com.gaa.sdk.base.StoreEnvironment (
|
||||
public *;
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5bd27940027ea4339a48c16d7397de38
|
||||
guid: 086e6716fd1c140ab8c1900df67960d6
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 20d274d91b62b40aa87642481e9e31b3
|
||||
guid: 0e7f3f62a1d934afa8c5a50871b4e961
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 51b187192c98746c38f9f3fef6d5f77d
|
||||
guid: c890dfc1dbfab44d9b5708963c3ac833
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ccbf429e4c2a44d0a8b32088c56ac6b3
|
||||
guid: 5a270edd7fdb445bdac56df23638c238
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace OneStore.Common.Internal
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public const string Version = "1.2.1";
|
||||
|
||||
public const string SdkLogger = "com.gaa.sdk.base.Logger";
|
||||
public const string SdkLoggerSetLogLevelMethod = "setLogLevel";
|
||||
public const string ResultListener = "com.gaa.sdk.base.ResultListener";
|
||||
public const string StoreEnvironment = "com.gaa.sdk.base.StoreEnvironment";
|
||||
public const string StoreEnvironmentGetStoreTypeMethod = "getStoreType";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9d86995d9257a440c907fae32aa2fa18
|
||||
timeCreated: 1458309246
|
||||
licenseType: Store
|
||||
guid: 26e8301dedd9c4d8cb5c5becbeb6089d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
|
|
@ -7,7 +7,7 @@ namespace OneStore.Common.Internal
|
|||
{
|
||||
public event Action<int, string> OnResponse = delegate { };
|
||||
|
||||
public ResultListener() : base("com.gaa.sdk.base.ResultListener") { }
|
||||
public ResultListener() : base(Constants.ResultListener) { }
|
||||
|
||||
void onResponse(int code, string message)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 12d01ff0c86d5497a9748ae538253a5f
|
||||
guid: 2cf2f0ceed6a040e68e5620fcb8f7b42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using UnityEngine;
|
|||
#if UNITY_ANDROID || !UNITY_EDITOR
|
||||
namespace OneStore.Common
|
||||
{
|
||||
public class JniHelper
|
||||
public static class JniHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the Android activity context of the Unity app.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4e1f0f7aabbc646afa163a77e8d8910f
|
||||
guid: 97c7b848926a1402e8b15c9348a47853
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3492da76c2c644025b0f367f039ed0cd
|
||||
guid: 1d74f11dbf39a4acc97dc280c1e23d1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,25 +1,45 @@
|
|||
using UnityEngine;
|
||||
using OneStore.Common.Internal;
|
||||
using System;
|
||||
|
||||
namespace OneStore.Common
|
||||
{
|
||||
public class OneStoreLogger
|
||||
public static class OneStoreLogger
|
||||
{
|
||||
private const string TAG = "ONE Store: ";
|
||||
|
||||
private readonly ILogger _logger = Debug.unityLogger;
|
||||
private static readonly ILogger _logger = Debug.unityLogger;
|
||||
|
||||
private static int _logLevel = 4; // default: 4 (android.util.Log.INFO)
|
||||
|
||||
/// <summary>
|
||||
/// Logs a formatted message with ILogger.
|
||||
/// Logs a verbose-level message (for detailed debugging).
|
||||
/// This message will only be logged if log level is 2 or higher.
|
||||
/// </summary>
|
||||
public void Log(string format, params object[] args)
|
||||
public static void Verbose(string format, params object[] args)
|
||||
{
|
||||
_logger.LogFormat(LogType.Log, TAG + format, args);
|
||||
if (_logLevel >= 2)
|
||||
{
|
||||
_logger.LogFormat(LogType.Log, TAG + format, args);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a standard log message (informational).
|
||||
/// This message will only be logged if log level is 4 or higher.
|
||||
/// </summary>
|
||||
public static void Log(string format, params object[] args)
|
||||
{
|
||||
if (_logLevel >= 4)
|
||||
{
|
||||
_logger.LogFormat(LogType.Log, TAG + format, args);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a formatted warning message with ILogger.
|
||||
/// </summary>
|
||||
public void Warning(string format, params object[] args)
|
||||
public static void Warning(string format, params object[] args)
|
||||
{
|
||||
_logger.LogFormat(LogType.Warning, TAG + format, args);
|
||||
}
|
||||
|
|
@ -27,11 +47,19 @@ namespace OneStore.Common
|
|||
/// <summary>
|
||||
/// Logs a formatted error message with ILogger.
|
||||
/// </summary>
|
||||
public void Error(string format, params object[] args)
|
||||
public static void Error(string format, params object[] args)
|
||||
{
|
||||
_logger.LogFormat(LogType.Error, TAG + format, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs an exception with full stack trace.
|
||||
/// </summary>
|
||||
public static void Exception(Exception exception)
|
||||
{
|
||||
_logger.LogException(exception);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the log level of the library For the convenience of development.<br/>
|
||||
/// Caution! When deploying an app, you must set the logging level to its default value.<br/>
|
||||
|
|
@ -40,8 +68,18 @@ namespace OneStore.Common
|
|||
/// <param name="level">default: 4 (android.util.Log.INFO)</param>
|
||||
public static void SetLogLevel(int level)
|
||||
{
|
||||
var sdkLogger = new AndroidJavaObject("com.gaa.sdk.base.Logger");
|
||||
sdkLogger.CallStatic("setLogLevel", level);
|
||||
_logLevel = level;
|
||||
var sdkLogger = new AndroidJavaObject(Constants.SdkLogger);
|
||||
sdkLogger.CallStatic(Constants.SdkLoggerSetLogLevelMethod, level);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables detailed debug logging for development purposes.
|
||||
/// When enabled, sets log level to VERBOSE (2); otherwise, sets it to INFO (4).
|
||||
/// </summary>
|
||||
public static void EnableDebugLog(bool enable)
|
||||
{
|
||||
SetLogLevel(enable ? 2 : 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5cc3b668dd9c3455fa9172b1636ccfef
|
||||
guid: 793d3dd6ce8fa47229c0da7e96c453d2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 995455e74dfb14e2b9d0c04ffee2da4b
|
||||
guid: 31f0bcacb83d74c12a02c326642286f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
using UnityEngine;
|
||||
using OneStore.Common.Internal;
|
||||
using System;
|
||||
|
||||
namespace OneStore.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// The StoreEnvironment class is responsible for determining the type of store where the app is installed.
|
||||
/// </summary>
|
||||
public class StoreEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the StoreEnvironment Java class.
|
||||
/// </summary>
|
||||
private static readonly AndroidJavaClass storeEnvironmentClass = new AndroidJavaClass(Constants.StoreEnvironment);
|
||||
|
||||
/// <summary>
|
||||
/// Determines the store type where the app was installed.<br/>
|
||||
/// <br/>
|
||||
/// @return One of the following values: <br/>
|
||||
/// - <see cref="StoreType.ONESTORE"/>: Installed from ONE Store or a trusted store. <br/>
|
||||
/// - <see cref="StoreType.VENDING"/>: Installed from Google Play Store. <br/>
|
||||
/// - <see cref="StoreType.ETC"/>: Installed from other stores. <br/>
|
||||
/// - <see cref="StoreType.UNKNOWN"/>: Store information is unknown. <br/>
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="StoreType"/> value representing the app's installation source.</returns>
|
||||
public static StoreType GetStoreType()
|
||||
{
|
||||
var storeTypeValue = storeEnvironmentClass.CallStatic<int>(
|
||||
Constants.StoreEnvironmentGetStoreTypeMethod,
|
||||
JniHelper.GetApplicationContext()
|
||||
);
|
||||
return Enum.IsDefined(typeof(StoreType), storeTypeValue) ? (StoreType)storeTypeValue : StoreType.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ae0d8bec6856f45db890916bc274a00e
|
||||
timeCreated: 1458310695
|
||||
licenseType: Store
|
||||
guid: 21c8b93fdb49b465fa4a680ebe84c984
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
namespace OneStore.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// It is a constant that represents the type of store where the app is installed.
|
||||
/// </summary>
|
||||
public enum StoreType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unable to determine the store (APK sideloaded, unknown source)
|
||||
/// </summary>
|
||||
UNKNOWN = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Installed from ONE Store (or a trusted store defined in Developer Options)
|
||||
/// </summary>
|
||||
ONESTORE = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Installed from Google Play Store
|
||||
/// </summary>
|
||||
VENDING = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Installed from other stores (Samsung Galaxy Store, Amazon Appstore, etc.)
|
||||
/// </summary>
|
||||
ETC = 3,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3aa30d9ec3feb4512a41a68db5646ecc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 83431c64bc5d94a78aacc7b562db1795
|
||||
guid: 864ad717c4e614bc0a9db4fa2c3aae0e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 541cf0e43641147f394d8a32b3089905
|
||||
guid: 635a0593099484eeb86843341155efba
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 590b8eb656428488cbe0514881515afa
|
||||
guid: c3fabc56fd842463bb99c8e57c758680
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<dependencies>
|
||||
<androidPackages>
|
||||
<repositories>
|
||||
<repository>https://repo.onestore.co.kr/repository/onestore-sdk-public</repository>
|
||||
<repository>https://repo.onestore.net/repository/onestore-sdk-public</repository>
|
||||
</repositories>
|
||||
<androidPackage spec="com.onestorecorp.sdk:sdk-iap:21.01.00" />
|
||||
<androidPackage spec="com.onestorecorp.sdk:sdk-iap:21.02.01" />
|
||||
</androidPackages>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8abdc96158a994b00aa31af2ac0db879
|
||||
guid: ab974bc6d99964828895de1da9e0c67f
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8580b732c1a9046189d398e4d902d356
|
||||
guid: a8be89816d0a4449cafdf9261fa82e9a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d78bc3a00355f497383963c097da7fb1
|
||||
guid: 2045a161414604bdfbb2c575c52b481b
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 453ae0db519424f768b7e47dd4d770de
|
||||
guid: 24f8ee9b2400c4066b0213141214b350
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6579c52c9a84e40b19c6950f8940812e
|
||||
guid: 4a46668187d28471caa65849b3f5d7d0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 44f6c5580605e496790f90e64628d10f
|
||||
guid: 24484c467aa7d4ce181da6d1e4725c3a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 087121c8ffc51413ea4b6cfbcd4da6f1
|
||||
guid: 7059e457b5e6b4063940b27d33e320ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 45a88cb38305847f993f7a92dc762864
|
||||
guid: 9747ed7e096c34dcc8c17ecb12d0319a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0930120a3615c46759a4ba4487fbf6ea
|
||||
guid: a85708d2f7eb44faf95f4134caeeab20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d92232be28e1b42c39e526e00611a8de
|
||||
guid: 8646eff21cc32420c8226a4da4c4ae39
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 75bcc9e21ba7e4b2aa4a48ff1f7f8776
|
||||
guid: a74d8f7ec29824f25b20deb0e8e1c9b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace OneStore.Purchasing.Internal
|
|||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public const string Version = "21.01.00";
|
||||
public const string Version = "21.02.01";
|
||||
|
||||
public static readonly TimeSpan AsyncTimeout = TimeSpan.FromMilliseconds(30000);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8e64f61104c86498aa934fa89bd417f6
|
||||
guid: 1461d8108bf7e4400996432a42335571
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c06b2c2e4a7364c3696ba84e0be1e9a9
|
||||
guid: d46db22ec1a8144ed9dad5701acca54e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -3,25 +3,21 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using OneStore.Common;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
|
||||
namespace OneStore.Purchasing.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of utils methods to process AndroidJavaObject returned by Gaa Purchasing Library.
|
||||
/// </summary>
|
||||
public class IapHelper
|
||||
public static class IapHelper
|
||||
{
|
||||
private readonly OneStoreLogger _logger;
|
||||
public IapHelper(OneStoreLogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the Iap results returned by Gaa Purchasing Client.
|
||||
/// </summary>
|
||||
/// <returns> The IapResult that indicates the outcome of the Java IapResult. </returns>
|
||||
public IapResult ParseJavaIapResult(AndroidJavaObject javaIapResult)
|
||||
public static IapResult ParseJavaIapResult(AndroidJavaObject javaIapResult)
|
||||
{
|
||||
var code = javaIapResult.Call<int>("getResponseCode");
|
||||
var message = javaIapResult.Call<string>("getMessage");
|
||||
|
|
@ -33,7 +29,7 @@ namespace OneStore.Purchasing.Internal
|
|||
/// Parses the IapResults returned by Gaa Purchasing Client.
|
||||
/// </summary>
|
||||
/// <returns>Returns the code value of the IapResult in ResponseCode.</returns>
|
||||
public ResponseCode GetResponseCodeFromIapResult(IapResult iapResult)
|
||||
public static ResponseCode GetResponseCodeFromIapResult(IapResult iapResult)
|
||||
{
|
||||
var resultResponseCode = ResponseCode.RESULT_ERROR;
|
||||
try
|
||||
|
|
@ -42,11 +38,11 @@ namespace OneStore.Purchasing.Internal
|
|||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
_logger.Error("Missing response code, return ResponseCode.RESULT_ERROR.");
|
||||
Logger.Error("Missing response code, return ResponseCode.RESULT_ERROR.");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
_logger.Error("Unknown response code {0}, return ResponseCode.RESULT_ERROR.", iapResult.Code);
|
||||
Logger.Error("Unknown response code {0}, return ResponseCode.RESULT_ERROR.", iapResult.Code);
|
||||
}
|
||||
return resultResponseCode;
|
||||
}
|
||||
|
|
@ -55,12 +51,12 @@ namespace OneStore.Purchasing.Internal
|
|||
/// Parses the ProductDetail list results returned by the Gaa Purchasing Library.
|
||||
/// </summary>
|
||||
/// <returns>An IEnumerable of <cref="SkuDetails"/>. The IEnumerable could be empty.</returns>
|
||||
public IEnumerable<ProductDetail> ParseProductDetailsResult(AndroidJavaObject javaIapResult, AndroidJavaObject productDetailsList)
|
||||
public static IEnumerable<ProductDetail> ParseProductDetailsResult(AndroidJavaObject javaIapResult, AndroidJavaObject productDetailsList)
|
||||
{
|
||||
var iapResult = ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Warning("Failed to retrieve products information! Error code {0}, message: {1}.",
|
||||
Logger.Warning("Failed to retrieve products information! Error code {0}, message: {1}.",
|
||||
iapResult.Code, iapResult.Message);
|
||||
return Enumerable.Empty<ProductDetail>();
|
||||
}
|
||||
|
|
@ -71,6 +67,8 @@ namespace OneStore.Purchasing.Internal
|
|||
{
|
||||
var javaProductDetail = productDetailsList.Call<AndroidJavaObject>("get", i);
|
||||
var originalJson = javaProductDetail.Call<string>(Constants.ProductDetailGetOriginalJson);
|
||||
Logger.Verbose("ParseProductDetailsResult: originalJson: {0}", originalJson);
|
||||
|
||||
ProductDetail productDetail;
|
||||
if (ProductDetail.FromJson(originalJson, out productDetail))
|
||||
{
|
||||
|
|
@ -78,7 +76,7 @@ namespace OneStore.Purchasing.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.Warning("Failed to parse productDetails {0} ", originalJson);
|
||||
Logger.Warning("Failed to parse productDetails {0} ", originalJson);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +87,7 @@ namespace OneStore.Purchasing.Internal
|
|||
/// Parses the Java list of purchaseData list returned by the Gaa Purchasing Library.
|
||||
/// </summary>
|
||||
/// <returns>An IEnumerable of <cref="PurchaseData"/>. The IEnumerable could be empty.</returns>
|
||||
public IEnumerable<PurchaseData> ParseJavaPurchasesList(AndroidJavaObject javaPurchasesList)
|
||||
public static IEnumerable<PurchaseData> ParseJavaPurchasesList(AndroidJavaObject javaPurchasesList)
|
||||
{
|
||||
var parsedPurchasesList = new List<PurchaseData>();
|
||||
var size = javaPurchasesList.Call<int>("size");
|
||||
|
|
@ -98,6 +96,8 @@ namespace OneStore.Purchasing.Internal
|
|||
var javaPurchase = javaPurchasesList.Call<AndroidJavaObject>("get", i);
|
||||
var originalJson = javaPurchase.Call<string>(Constants.PurchaseDataGetOriginalJsonMethod);
|
||||
var signature = javaPurchase.Call<string>(Constants.PurchaseDataGetSignatureMethod);
|
||||
Logger.Verbose("ParseJavaPurchasesList: originalJson: {0}, signature: {1}", originalJson, signature);
|
||||
|
||||
PurchaseData purchaseData;
|
||||
if (PurchaseData.FromJson(originalJson, signature, out purchaseData))
|
||||
{
|
||||
|
|
@ -105,23 +105,22 @@ namespace OneStore.Purchasing.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.Warning("Failed to parse purchase {0} ", originalJson);
|
||||
Logger.Warning("Failed to parse purchase {0} ", originalJson);
|
||||
}
|
||||
}
|
||||
|
||||
return parsedPurchasesList;
|
||||
}
|
||||
|
||||
public PurchaseData ParseJavaPurchaseData(AndroidJavaObject javaPurchaseData)
|
||||
public static PurchaseData ParseJavaPurchaseData(AndroidJavaObject javaPurchaseData)
|
||||
{
|
||||
var originalJson = javaPurchaseData.Call<string>("getOriginalJson");
|
||||
var signature = javaPurchaseData.Call<string>("getSignature");
|
||||
PurchaseData purchaseData;
|
||||
if (PurchaseData.FromJson(originalJson, signature, out purchaseData))
|
||||
var originalJson = javaPurchaseData.Call<string>(Constants.PurchaseDataGetOriginalJsonMethod);
|
||||
var signature = javaPurchaseData.Call<string>(Constants.PurchaseDataGetSignatureMethod);
|
||||
if (PurchaseData.FromJson(originalJson, signature, out PurchaseData purchaseData))
|
||||
{
|
||||
return purchaseData;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +145,7 @@ namespace OneStore.Purchasing.Internal
|
|||
// var responseCode = GetResponseCodeFromIapResult(iapResult);
|
||||
// if (responseCode != ResponseCode.RESULT_OK)
|
||||
// {
|
||||
// _logger.Error("Failed to retrieve purchases information! Error code {0}, message: {1}.",
|
||||
// Logger.Error("Failed to retrieve purchases information! Error code {0}, message: {1}.",
|
||||
// iapResult.Code, iapResult.Message);
|
||||
// return Enumerable.Empty<PurchaseData>();
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9ff3024883f804d08918d7b14baefb97
|
||||
guid: 826c4b35303374ef896b7eb23d2a3c16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ea27d8035db8f4f2c9351525e474d806
|
||||
guid: 7545e6e6d3d4d447788110bef866985c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c4bf13942066d4db495cb8ac556789ae
|
||||
guid: c5efe3bf23765426bbaf92f82f5cbd20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 161f62becd9884402b9930107ce68982
|
||||
guid: 709f0596b6b8c4b6b9b64b5a836c6b79
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fb1ca6ef17e26421e80445ad6a286245
|
||||
guid: ef9e60b8602a8459885a544273a4f4da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 099220b88e8f14b1e8c20a94af76e7a3
|
||||
guid: a46dd76b0654b4ace8018eed3ad0602c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 32cccf6915cf74937be26ca1674b1e4b
|
||||
guid: 107a553b495544bfca51807e3ce88f93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3075a4c0c070a495cb198e9747e9c981
|
||||
guid: fe478ec6c9d4e4a0db2e2cce3ae4d4cf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5eabc8ed8e0e340b79d53d6c47f553e1
|
||||
guid: c214bbaa82deb465c8dc0d33eb013bd1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 74e6007e0cb824d73803296c1ac942a3
|
||||
guid: 7f238cae7b9d94d84adda85b667ecdad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using OneStore.Purchasing.Internal;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
|
||||
namespace OneStore.Purchasing
|
||||
{
|
||||
|
|
@ -41,8 +42,10 @@ namespace OneStore.Purchasing
|
|||
productDetail.JsonProductDetail = jsonProductDetail;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("[ProductDetail]: Failed to parse purchase data: {0}", jsonProductDetail);
|
||||
Logger.Exception(ex);
|
||||
productDetail = null;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4891df32dba4642319f9e2d48e6923a5
|
||||
guid: cc5c07c0c0c584c418d11f3ce55ef7d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 82e8e1ef36f844207ac2a641db1663b2
|
||||
guid: b25bfa4e2b7454b6cbd096e9abf46540
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -7,10 +7,15 @@ using System.Collections.ObjectModel;
|
|||
using System.Linq;
|
||||
using OneStore.Purchasing.Internal;
|
||||
using OneStore.Common;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OneStore.Purchasing
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of the One Store IAP client for Unity.
|
||||
/// This class handles purchase initialization, product queries, purchase flows, and subscription management.
|
||||
/// </summary>
|
||||
public class PurchaseClientImpl : IPurchaseExtensions
|
||||
{
|
||||
private IPurchaseCallback _callback;
|
||||
|
|
@ -19,8 +24,6 @@ namespace OneStore.Purchasing
|
|||
private PurchasesUpdatedListener _purchaseUpdatedListener;
|
||||
|
||||
private readonly OneStorePurchasingInventory _inventory;
|
||||
private readonly OneStoreLogger _logger;
|
||||
private readonly IapHelper _iapHelper;
|
||||
|
||||
private volatile string _productInPurchaseFlow;
|
||||
|
||||
|
|
@ -32,10 +35,16 @@ namespace OneStore.Purchasing
|
|||
|
||||
private volatile ConnectionStatus _connectionStatus = ConnectionStatus.DISCONNECTED;
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing the connection status of the purchase client.
|
||||
/// </summary>
|
||||
private enum ConnectionStatus {
|
||||
DISCONNECTED, CONNECTING, CONNECTED,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to track query purchase status for different product types.
|
||||
/// </summary>
|
||||
private volatile Dictionary<ProductType, AsyncRequestStatus> _queryPurchasesCallStatus =
|
||||
new Dictionary<ProductType, AsyncRequestStatus>
|
||||
{
|
||||
|
|
@ -44,6 +53,9 @@ namespace OneStore.Purchasing
|
|||
{ProductType.AUTO, AsyncRequestStatus.Succeed},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to track query product details status for different product types.
|
||||
/// </summary>
|
||||
private volatile Dictionary<ProductType, AsyncRequestStatus> _queryProductDetailsCallStatus =
|
||||
new Dictionary<ProductType, AsyncRequestStatus>
|
||||
{
|
||||
|
|
@ -53,11 +65,23 @@ namespace OneStore.Purchasing
|
|||
{ProductType.ALL, AsyncRequestStatus.Succeed},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Enum representing the asynchronous request status.
|
||||
/// </summary>
|
||||
private enum AsyncRequestStatus
|
||||
{
|
||||
Pending, Failed, Succeed,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the `PurchaseClientImpl` class with the specified license key.
|
||||
/// </summary>
|
||||
/// <param name="licenseKey">The license key required for authentication with the ONE store IAP SDK.</param>
|
||||
/// <remarks>
|
||||
/// - Checks if the application is running on an Android platform; otherwise, throws a `PlatformNotSupportedException`.
|
||||
/// - Initializes `_inventory` as an instance of `OneStorePurchasingInventory` to manage purchase data.
|
||||
/// - Stores the provided `licenseKey` in `_licenseKey` for later use.
|
||||
/// </remarks>
|
||||
public PurchaseClientImpl(string licenseKey)
|
||||
{
|
||||
if (Application.platform != RuntimePlatform.Android)
|
||||
|
|
@ -66,11 +90,21 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
|
||||
_inventory = new OneStorePurchasingInventory();
|
||||
_logger = new OneStoreLogger();
|
||||
_iapHelper = new IapHelper(_logger);
|
||||
_licenseKey = licenseKey;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the ONE store IAP client and establishes a connection to the service.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback interface to handle purchase-related events.</param>
|
||||
/// <remarks>
|
||||
/// - Assigns the provided `callback` to `_callback`.
|
||||
/// - Creates an instance of `_purchaseClient` using the ONE store IAP SDK.
|
||||
/// - Retrieves the application context using `JniHelper.GetApplicationContext()`.
|
||||
/// - Initializes `_purchaseUpdatedListener` to handle purchase updates and assigns `ProcessPurchaseUpdatedResult` as the callback.
|
||||
/// - Calls `_purchaseClient.Call()` to set up the purchase client with the application context, license key, and purchase listener.
|
||||
/// - Initiates the service connection using `StartConnection()`, and upon successful connection, retrieves the `storeCode`.
|
||||
/// </remarks>
|
||||
public void Initialize(IPurchaseCallback callback)
|
||||
{
|
||||
_callback = callback;
|
||||
|
|
@ -88,16 +122,30 @@ namespace OneStore.Purchasing
|
|||
);
|
||||
|
||||
StartConnection(()=> {
|
||||
_logger.Log("Initialize: Successfully connected to the service.");
|
||||
Logger.Log("Initialize: Successfully connected to the service.");
|
||||
GetStoreCode();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a connection to the ONE store IAP service and processes pending requests.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute once the connection is successfully established.</param>
|
||||
/// <remarks>
|
||||
/// - If the client is already connecting (`ConnectionStatus.CONNECTING`), the action is added to `_requestQueue` and logged.
|
||||
/// - Updates `_connectionStatus` to `CONNECTING` before starting the connection process.
|
||||
/// - Creates a `PurchaseClientStateListener` to handle connection events:
|
||||
/// - `OnServiceDisconnected`: Logs a warning, resets `_productInPurchaseFlow`, and sets `_connectionStatus` to `DISCONNECTED`.
|
||||
/// - `OnSetupFinished`:
|
||||
/// - If successful, updates `_connectionStatus` to `CONNECTED`, executes the provided action, and processes queued requests.
|
||||
/// - If failed, logs an error, clears `_requestQueue`, and triggers `OnSetupFailed` callback with the error result.
|
||||
/// - Calls `_purchaseClient.Call()` to start the connection process.
|
||||
/// </remarks>
|
||||
private void StartConnection(Action action)
|
||||
{
|
||||
if (_connectionStatus == ConnectionStatus.CONNECTING) {
|
||||
_requestQueue.Enqueue(action);
|
||||
_logger.Log("Client is already in the process of connecting to service.");
|
||||
Logger.Log("Client is already in the process of connecting to service.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -106,14 +154,14 @@ namespace OneStore.Purchasing
|
|||
var purchaseClientStateListener = new PurchaseClientStateListener();
|
||||
purchaseClientStateListener.OnServiceDisconnected += () =>
|
||||
{
|
||||
_logger.Warning("Client is disconnected from the service.");
|
||||
Logger.Warning("Client is disconnected from the service.");
|
||||
_productInPurchaseFlow = null;
|
||||
_connectionStatus = ConnectionStatus.DISCONNECTED;
|
||||
};
|
||||
|
||||
purchaseClientStateListener.OnSetupFinished += (javaIapResult) =>
|
||||
{
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (iapResult.IsSuccessful())
|
||||
{
|
||||
_connectionStatus = ConnectionStatus.CONNECTED;
|
||||
|
|
@ -125,7 +173,7 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
else
|
||||
{
|
||||
_logger.Error("Failed to connect to service with error code '{0}' and message: '{1}'.",
|
||||
Logger.Error("Failed to connect to service with error code '{0}' and message: '{1}'.",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
_requestQueue.Clear();
|
||||
|
|
@ -141,6 +189,14 @@ namespace OneStore.Purchasing
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the given action if the IAP service is connected; otherwise, attempts to establish a connection first.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute once the connection is established.</param>
|
||||
/// <remarks>
|
||||
/// - If `_connectionStatus` is `CONNECTED`, the provided action is immediately executed.
|
||||
/// - If not connected, `StartConnection(action)` is called to establish a connection before executing the action.
|
||||
/// </remarks>
|
||||
private void ExecuteService(Action action)
|
||||
{
|
||||
if (_connectionStatus == ConnectionStatus.CONNECTED)
|
||||
|
|
@ -153,6 +209,10 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ends the connection to the One Store purchase service.
|
||||
/// This should be called when the application exits or the purchasing service is no longer needed.
|
||||
/// </summary>
|
||||
public void EndConnection()
|
||||
{
|
||||
_productInPurchaseFlow = null;
|
||||
|
|
@ -161,6 +221,18 @@ namespace OneStore.Purchasing
|
|||
_connectionStatus = ConnectionStatus.DISCONNECTED;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves detailed product information for the given product IDs using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="productIds">A collection of product IDs to query.</param>
|
||||
/// <param name="type">The type of product to query.</param>
|
||||
/// <remarks>
|
||||
/// - If there is an ongoing request for the given product type, the function returns without executing a new request.
|
||||
/// - If product details are already available in the local inventory and match the requested product IDs,
|
||||
/// the details are returned immediately without making a new request.
|
||||
/// - Otherwise, a request is constructed using `ProductDetailsParamBuilder` and sent through `_purchaseClient.Call()`.
|
||||
/// - The result is handled by `ProductDetailsListener`, which triggers the appropriate callback upon response.
|
||||
/// </remarks>
|
||||
public void QueryProductDetails(ReadOnlyCollection<string> productIds, ProductType type)
|
||||
{
|
||||
if (_queryProductDetailsCallStatus[type] == AsyncRequestStatus.Pending)
|
||||
|
|
@ -203,12 +275,22 @@ namespace OneStore.Purchasing
|
|||
return IsPurchasingServiceAvailable() ? _inventory.GetAllProductDetails() : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queries the non-consumed purchase history for managed products using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of product to query. Must not be `ProductType.ALL` or `null`.</param>
|
||||
/// <remarks>
|
||||
/// - If `ProductType.ALL` is passed, an error is logged, and the request is rejected, as querying all product types is not supported.
|
||||
/// - If `type` is `null`, an error is returned indicating an illegal argument.
|
||||
/// - If there is an ongoing query for the given product type, the function returns without executing another request.
|
||||
/// - Otherwise, the function sets the request status to `Pending`, then initiates the query using `_purchaseClient.Call()`.
|
||||
/// </remarks>
|
||||
public void QueryPurchases(ProductType type)
|
||||
{
|
||||
if (ProductType.ALL == type)
|
||||
{
|
||||
var message = "ProductType.ALL is not supported. This is supported only by the QueryProductDetails.";
|
||||
_logger.Error(message);
|
||||
Logger.Error(message);
|
||||
RunOnMainThread(() => _callback.OnPurchaseFailed(new IapResult((int) ResponseCode.ERROR_ILLEGAL_ARGUMENT, message)));
|
||||
return;
|
||||
}
|
||||
|
|
@ -237,12 +319,22 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a purchase request for a product using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="purchaseFlowParams">The parameters required to process the purchase, including product ID, type, quantity, and additional metadata.</param>
|
||||
/// <remarks>
|
||||
/// - If a purchase is already in progress for another product, the request is rejected, and an error is logged.
|
||||
/// - The function constructs a `PurchaseFlowParams` object using the provided parameters.
|
||||
/// - The purchase flow is initiated using the `LaunchPurchaseFlow` method.
|
||||
/// - The request includes additional metadata such as `ProductName`, `GameUserId`, and whether the product is eligible for promotions.
|
||||
/// </remarks>
|
||||
public void Purchase(PurchaseFlowParams purchaseFlowParams)
|
||||
{
|
||||
if (_productInPurchaseFlow != null)
|
||||
{
|
||||
var message = string.Format("A purchase for {0} is already in progress.", _productInPurchaseFlow);
|
||||
_logger.Error(message);
|
||||
Logger.Error(message);
|
||||
RunOnMainThread(() => _callback.OnPurchaseFailed(new IapResult((int) ResponseCode.RESULT_ERROR, message)));
|
||||
return;
|
||||
}
|
||||
|
|
@ -274,12 +366,22 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing subscription product using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="purchaseFlowParams">The parameters required to process the subscription update, including product ID, type, developer payload, and proration mode.</param>
|
||||
/// <remarks>
|
||||
/// - If a subscription update is already in progress, the request is rejected, and an error is logged.
|
||||
/// - The function constructs a `PurchaseFlowParams` object using the provided parameters.
|
||||
/// - A `SubscriptionUpdateParams` object is created to include the proration mode and the old purchase token for the update.
|
||||
/// - The update request is initiated using the `LaunchPurchaseFlow` method.
|
||||
/// </remarks>
|
||||
public void UpdateSubscription(PurchaseFlowParams purchaseFlowParams)
|
||||
{
|
||||
if (_productInPurchaseFlow != null)
|
||||
{
|
||||
var message = string.Format("The update subscription for {0} is already in progress.", _productInPurchaseFlow);
|
||||
_logger.Error(message);
|
||||
Logger.Error(message);
|
||||
RunOnMainThread(() => _callback.OnPurchaseFailed(new IapResult((int) ResponseCode.RESULT_ERROR, message)));
|
||||
return;
|
||||
}
|
||||
|
|
@ -325,6 +427,16 @@ namespace OneStore.Purchasing
|
|||
purchaseFlowParamsBuilder.Call<AndroidJavaObject>(Constants.BuildMethod));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Consumes a purchased managed product using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="purchaseData">The purchase data of the managed product to be consumed.</param>
|
||||
/// <remarks>
|
||||
/// - If `purchaseData` is null, the request is rejected, and an error is logged.
|
||||
/// - The function constructs a `ConsumeParams` object using the provided `purchaseData`.
|
||||
/// - The consumption request is sent using `_purchaseClient.Call()`.
|
||||
/// - The result is handled by `ConsumeListener`, which triggers the appropriate callback upon response.
|
||||
/// </remarks>
|
||||
public void ConsumePurchase(PurchaseData purchaseData)
|
||||
{
|
||||
if (purchaseData == null)
|
||||
|
|
@ -353,6 +465,19 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Acknowledges a purchased non-consumable or subscription product using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="purchaseData">The purchase data of the product to be acknowledged.</param>
|
||||
/// <param name="type">The type of product being acknowledged (must not be `ProductType.ALL` or `null`).</param>
|
||||
/// <remarks>
|
||||
/// - If `purchaseData` is null, the request is rejected, and an error is logged.
|
||||
/// - If `type` is null, the request is rejected, and an error is logged.
|
||||
/// - If `type` is `ProductType.ALL`, the request is rejected, as acknowledging all product types is not supported.
|
||||
/// - The function constructs an `AcknowledgeParams` object using the provided `purchaseData`.
|
||||
/// - The acknowledgment request is sent using `_purchaseClient.Call()`.
|
||||
/// - The result is handled by `AcknowledgeListener`, which triggers the appropriate callback upon response.
|
||||
/// </remarks>
|
||||
public void AcknowledgePurchase(PurchaseData purchaseData, ProductType type)
|
||||
{
|
||||
if (purchaseData == null)
|
||||
|
|
@ -372,7 +497,7 @@ namespace OneStore.Purchasing
|
|||
else if (ProductType.ALL == type)
|
||||
{
|
||||
var message = "ProductType.ALL is not supported. This is supported only by the QueryProductDetails.";
|
||||
_logger.Error(message);
|
||||
Logger.Error(message);
|
||||
RunOnMainThread(() => _callback.OnAcknowledgeFailed(new IapResult((int) ResponseCode.ERROR_ILLEGAL_ARGUMENT, message)));
|
||||
return;
|
||||
}
|
||||
|
|
@ -395,6 +520,19 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages an auto product (auto-renewable subscription) using the ONE store IAP SDK.
|
||||
/// This method is obsolete.
|
||||
/// </summary>
|
||||
/// <param name="purchaseData">The purchase data of the auto product to be managed.</param>
|
||||
/// <param name="action">The recurring action to be performed (e.g., cancel, pause, resume).</param>
|
||||
/// <remarks>
|
||||
/// - If `purchaseData` is null, the request is rejected, and an error is logged.
|
||||
/// - If the product type is not `AUTO`, the request is rejected, as only auto products support this feature.
|
||||
/// - The function constructs a `RecurringProductParams` object using the provided `purchaseData` and `action`.
|
||||
/// - The request is sent using `_purchaseClient.Call()`.
|
||||
/// - The result is handled by `RecurringProductListener`, which triggers the appropriate callback upon response.
|
||||
/// </remarks>
|
||||
[Obsolete]
|
||||
public void ManageRecurringProduct(PurchaseData purchaseData, RecurringAction action)
|
||||
{
|
||||
|
|
@ -433,12 +571,26 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the update or installation flow for the ONE store IAP SDK.
|
||||
/// This ensures that the latest version of the ONE store service is installed or updated if necessary.
|
||||
/// </summary>
|
||||
/// <param name="callback">A callback function that receives the result of the update or installation process.</param>
|
||||
/// <remarks>
|
||||
/// - In-app payments cannot be used if the ONE store service is outdated or not installed.
|
||||
/// - The first API call attempts to connect to the ONE store service.
|
||||
/// - If `RESULT_NEED_UPDATE` occurs, you must call this method to update or install the service.
|
||||
/// - The function creates an `IapResultListener` to handle the response.
|
||||
/// - The result from the Java IAP service is parsed using `IapHelper.ParseJavaIapResult()`.
|
||||
/// - If the update or installation is successful, the provided callback is invoked with the `IapResult`.
|
||||
/// - The process is executed via `_purchaseClient.Call()`, which triggers the update or installation flow.
|
||||
/// </remarks>
|
||||
public void LaunchUpdateOrInstallFlow(Action<IapResult> callback)
|
||||
{
|
||||
var iapResultListener = new IapResultListener();
|
||||
iapResultListener.OnResponse += (javaIapResult) =>
|
||||
{
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
HandleErrorCode(iapResult, () => {
|
||||
RunOnMainThread(() => callback?.Invoke(iapResult));
|
||||
});
|
||||
|
|
@ -451,6 +603,20 @@ namespace OneStore.Purchasing
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the subscription management screen using the ONE store IAP SDK.
|
||||
/// </summary>
|
||||
/// <param name="purchaseData">
|
||||
/// The purchase data of the subscription product to manage.
|
||||
/// If `purchaseData` is provided, the management screen for that specific subscription product is displayed.
|
||||
/// If `purchaseData` is `null`, the user's subscription list screen is launched.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// - The function creates a `SubscriptionParamsBuilder` to set the purchase data if available.
|
||||
/// - If `purchaseData` is provided, the management screen for that specific subscription product is shown.
|
||||
/// - If `purchaseData` is `null`, the general subscription list screen is displayed.
|
||||
/// - The function executes `_purchaseClient.Call()` to open the subscription management screen.
|
||||
/// </remarks>
|
||||
public void LaunchManageSubscription(PurchaseData purchaseData)
|
||||
{
|
||||
using (var subscriptionParamsBuilder = new AndroidJavaObject(Constants.SubscriptionParamsBuilder))
|
||||
|
|
@ -468,6 +634,15 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the market distinction code (storeCode) using the ONE store IAP SDK.
|
||||
/// This code is required for using the S2S API from SDK v19 onward.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// - When the `PurchaseClientImpl` object is initialized, the SDK attempts to connect to the payment module.
|
||||
/// - Upon successful connection, the `storeCode` is automatically obtained and assigned to `PurchaseClientImpl.storeCode`.
|
||||
/// - This function requests the `storeCode` using `_purchaseClient.Call()` and assigns it upon response.
|
||||
/// </remarks>
|
||||
private void GetStoreCode()
|
||||
{
|
||||
var storeCodeListener = new StoreInfoListener();
|
||||
|
|
@ -479,6 +654,14 @@ namespace OneStore.Purchasing
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the purchasing service is available by verifying the connection status.
|
||||
/// </summary>
|
||||
/// <returns>Returns `true` if the service is connected; otherwise, logs a warning and returns `false`.</returns>
|
||||
/// <remarks>
|
||||
/// - If `_connectionStatus` is `CONNECTED`, the function returns `true`, indicating that the purchasing service is available.
|
||||
/// - If not connected, a warning message is logged, and the function returns `false`.
|
||||
/// </remarks>
|
||||
private bool IsPurchasingServiceAvailable()
|
||||
{
|
||||
if (_connectionStatus == ConnectionStatus.CONNECTED)
|
||||
|
|
@ -486,16 +669,29 @@ namespace OneStore.Purchasing
|
|||
return true;
|
||||
}
|
||||
var message = string.Format("Purchasing service unavailable. ConnectionStatus: {0}", _connectionStatus.ToString());
|
||||
_logger.Warning(message);
|
||||
Logger.Warning(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the result of a product details query and updates the inventory accordingly.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of product being queried.</param>
|
||||
/// <param name="javaIapResult">The result of the IAP request from the ONE store SDK.</param>
|
||||
/// <param name="javaProductDetailList">The list of product details retrieved from the query.</param>
|
||||
/// <remarks>
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the query fails, logs a warning with the error details and updates the query status as `Failed`.
|
||||
/// - Handles error cases by invoking `HandleErrorCode(iapResult)`, triggering the `OnProductDetailsFailed` callback.
|
||||
/// - If successful, parses the product details list and updates the inventory using `_inventory.UpdateProductDetailInventory()`.
|
||||
/// - Marks the query status as `Succeed` and invokes the `OnProductDetailsSucceeded` callback with the retrieved product details.
|
||||
/// </remarks>
|
||||
private void ProcessProductDetailsResult(ProductType type, AndroidJavaObject javaIapResult, AndroidJavaObject javaProductDetailList)
|
||||
{
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Warning("Retrieve product failed with error code '{0}' and message: '{1}'",
|
||||
Logger.Warning("Retrieve product failed with error code '{0}' and message: '{1}'",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
_queryProductDetailsCallStatus[type] = AsyncRequestStatus.Failed;
|
||||
|
|
@ -506,19 +702,32 @@ namespace OneStore.Purchasing
|
|||
return;
|
||||
}
|
||||
|
||||
var productDetailList = _iapHelper.ParseProductDetailsResult(javaIapResult, javaProductDetailList);
|
||||
var productDetailList = IapHelper.ParseProductDetailsResult(javaIapResult, javaProductDetailList);
|
||||
_inventory.UpdateProductDetailInventory(productDetailList);
|
||||
_queryProductDetailsCallStatus[type] = AsyncRequestStatus.Succeed;
|
||||
RunOnMainThread(() => _callback.OnProductDetailsSucceeded(productDetailList.ToList()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the result of a purchase update and updates the inventory accordingly.
|
||||
/// </summary>
|
||||
/// <param name="javaIapResult">The result of the IAP request from the ONE store SDK.</param>
|
||||
/// <param name="javaPurchasesList">The list of purchases retrieved from the query.</param>
|
||||
/// <remarks>
|
||||
/// - Resets `_productInPurchaseFlow` to `null` after the purchase process completes.
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the purchase fails, logs a warning with the error details and invokes `OnPurchaseFailed` callback.
|
||||
/// - If the purchase is successful, retrieves the purchase list using `IapHelper.ParseJavaPurchasesList(javaPurchasesList)`.
|
||||
/// - If any purchases exist, updates the inventory using `_inventory.UpdatePurchaseInventory()`.
|
||||
/// - Invokes the `OnPurchaseSucceeded` callback with the retrieved purchase list.
|
||||
/// </remarks>
|
||||
private void ProcessPurchaseUpdatedResult(AndroidJavaObject javaIapResult, AndroidJavaObject javaPurchasesList)
|
||||
{
|
||||
_productInPurchaseFlow = null;
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Warning("Purchase failed with error code '{0}' and message: '{1}'",
|
||||
Logger.Warning("Purchase failed with error code '{0}' and message: '{1}'",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
HandleErrorCode(iapResult, () => {
|
||||
|
|
@ -527,7 +736,7 @@ namespace OneStore.Purchasing
|
|||
return;
|
||||
}
|
||||
|
||||
var purchasesList = _iapHelper.ParseJavaPurchasesList(javaPurchasesList);
|
||||
var purchasesList = IapHelper.ParseJavaPurchasesList(javaPurchasesList);
|
||||
if (purchasesList.Any())
|
||||
{
|
||||
_inventory.UpdatePurchaseInventory(purchasesList);
|
||||
|
|
@ -535,13 +744,28 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the result of a purchase query and updates the inventory accordingly.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of product being queried.</param>
|
||||
/// <param name="javaIapResult">The result of the IAP request from the ONE store SDK.</param>
|
||||
/// <param name="javaPurchasesList">The list of purchases retrieved from the query.</param>
|
||||
/// <remarks>
|
||||
/// - Resets `_productInPurchaseFlow` to `null` after processing the query.
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the query fails, logs a warning, sets the query status to `Failed`, and triggers the `OnPurchaseFailed` callback.
|
||||
/// - If the query is successful, updates `_queryPurchasesCallStatus[type]` to `Succeed`.
|
||||
/// - Retrieves the purchase list using `IapHelper.ParseJavaPurchasesList(javaPurchasesList)`.
|
||||
/// - Updates the inventory with the retrieved purchases using `_inventory.UpdatePurchaseInventory()`.
|
||||
/// - Invokes the `OnPurchaseSucceeded` callback with the purchase list.
|
||||
/// </remarks>
|
||||
private void ProcessQueryPurchasesResult(ProductType type, AndroidJavaObject javaIapResult, AndroidJavaObject javaPurchasesList)
|
||||
{
|
||||
_productInPurchaseFlow = null;
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Warning("Purchase failed with error code '{0}' and message: '{1}'",
|
||||
Logger.Warning("Purchase failed with error code '{0}' and message: '{1}'",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
_queryPurchasesCallStatus[type] = AsyncRequestStatus.Failed;
|
||||
|
|
@ -553,17 +777,29 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
|
||||
_queryPurchasesCallStatus[type] = AsyncRequestStatus.Succeed;
|
||||
var purchasesList = _iapHelper.ParseJavaPurchasesList(javaPurchasesList);
|
||||
var purchasesList = IapHelper.ParseJavaPurchasesList(javaPurchasesList);
|
||||
_inventory.UpdatePurchaseInventory(purchasesList);
|
||||
RunOnMainThread(() => _callback.OnPurchaseSucceeded(purchasesList.ToList()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the result of a consume purchase request and updates the inventory accordingly.
|
||||
/// </summary>
|
||||
/// <param name="javaIapResult">The result of the IAP request from the ONE store SDK.</param>
|
||||
/// <param name="javaPurchaseData">The purchase data of the consumed product.</param>
|
||||
/// <remarks>
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the consumption request fails, logs an error, handles the error code, and triggers the `OnConsumeFailed` callback.
|
||||
/// - If successful, parses the consumed purchase data using `IapHelper.ParseJavaPurchaseData(javaPurchaseData)`.
|
||||
/// - Removes the consumed product from the inventory using `_inventory.RemovePurchase(purchaseData.ProductId)`.
|
||||
/// - Invokes the `OnConsumeSucceeded` callback with the consumed purchase data.
|
||||
/// </remarks>
|
||||
private void ProcessConsumePurchaseResult(AndroidJavaObject javaIapResult, AndroidJavaObject javaPurchaseData)
|
||||
{
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Error("Failed to finish the consume purchase with error code {0} and message: {1}",
|
||||
Logger.Error("Failed to finish the consume purchase with error code {0} and message: {1}",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
HandleErrorCode(iapResult, () => {
|
||||
|
|
@ -572,17 +808,30 @@ namespace OneStore.Purchasing
|
|||
return;
|
||||
}
|
||||
|
||||
var purchaseData = _iapHelper.ParseJavaPurchaseData(javaPurchaseData);
|
||||
var purchaseData = IapHelper.ParseJavaPurchaseData(javaPurchaseData);
|
||||
_inventory.RemovePurchase(purchaseData.ProductId);
|
||||
RunOnMainThread(() => _callback.OnConsumeSucceeded(purchaseData));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the result of an acknowledge purchase request and verifies the updated purchase status.
|
||||
/// </summary>
|
||||
/// <param name="javaIapResult">The result of the IAP request from the ONE store SDK.</param>
|
||||
/// <param name="productId">The product ID of the acknowledged purchase.</param>
|
||||
/// <param name="type">The type of product being acknowledged.</param>
|
||||
/// <remarks>
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the acknowledgment request fails, logs an error, handles the error code, and triggers the `OnAcknowledgeFailed` callback.
|
||||
/// - If successful, calls `QueryPurchasesInternal()` to verify the purchase status.
|
||||
/// - Runs the result on the main thread and invokes `OnAcknowledgeSucceeded` if the query is successful.
|
||||
/// - If the query fails, invokes the `OnAcknowledgeFailed` callback.
|
||||
/// </remarks>
|
||||
private void ProcessAcknowledgePurchaseResult(AndroidJavaObject javaIapResult, string productId, ProductType type)
|
||||
{
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Error("Failed to finish the acknowledge purchase with error code {0} and message: {1}",
|
||||
Logger.Error("Failed to finish the acknowledge purchase with error code {0} and message: {1}",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
HandleErrorCode(iapResult, () => {
|
||||
|
|
@ -605,12 +854,24 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Processes the result of a recurring product management request and verifies the updated purchase status.
|
||||
/// </summary>
|
||||
/// <param name="javaIapResult">The result of the IAP request from the ONE store SDK.</param>
|
||||
/// <param name="productId">The product ID of the recurring product being managed.</param>
|
||||
/// <param name="recurringAction">The recurring action performed (e.g., cancel, pause, resume).</param>
|
||||
/// <remarks>
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the request fails, logs an error, handles the error code, and triggers the `OnManageRecurringProduct` callback with a failure response.
|
||||
/// - If successful, calls `QueryPurchasesInternal()` to verify the updated purchase status.
|
||||
/// - Runs the result on the main thread and invokes `OnManageRecurringProduct` with the retrieved purchase data.
|
||||
/// </remarks>
|
||||
private void ProcessRecurringProductResult(AndroidJavaObject javaIapResult, string productId, string recurringAction)
|
||||
{
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Error("Failed to finish the manage recurring with error code {0} and message: {1}",
|
||||
Logger.Error("Failed to finish the manage recurring with error code {0} and message: {1}",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
HandleErrorCode(iapResult, () => {
|
||||
|
|
@ -624,14 +885,33 @@ namespace OneStore.Purchasing
|
|||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internally queries the latest purchase status after an `AcknowledgePurchase()` or `ManageRecurringProduct()` API call,
|
||||
/// ensuring that the product's state is updated accordingly by refreshing the inventory.
|
||||
/// </summary>
|
||||
/// <param name="productId">The ID of the product to query.</param>
|
||||
/// <param name="type">The type of product being queried.</param>
|
||||
/// <param name="callback">The callback function to return the query result and purchase data.</param>
|
||||
/// <remarks>
|
||||
/// - This function is called internally after an `AcknowledgePurchase()` or `ManageRecurringProduct()` API call
|
||||
/// to refresh the product's state based on the latest purchase information.
|
||||
/// - It executes `queryPurchasesAsync` internally to update the inventory with the latest state values.
|
||||
/// - Creates a `QueryPurchasesListener` instance to listen for purchase query responses.
|
||||
/// - Parses the IAP result using `IapHelper.ParseJavaIapResult(javaIapResult)`.
|
||||
/// - If the query fails, logs a warning, handles the error code, and invokes the callback with a failure response.
|
||||
/// - If the query succeeds, retrieves and parses the purchase list using `IapHelper.ParseJavaPurchasesList(javaPurchasesList)`.
|
||||
/// - Updates `_inventory` with the retrieved purchases to maintain the latest product state.
|
||||
/// - If a purchase matching `productId` exists in `_inventory`, invokes the callback with the corresponding `PurchaseData`.
|
||||
/// - Calls `_purchaseClient.Call()` to execute the purchase query asynchronously for the specified product type.
|
||||
/// </remarks>
|
||||
private void QueryPurchasesInternal(string productId, ProductType type, Action<IapResult, PurchaseData> callback)
|
||||
{
|
||||
var queryPurchasesListener = new QueryPurchasesListener(type);
|
||||
queryPurchasesListener.OnPurchasesResponse += (_, javaIapResult, javaPurchasesList) => {
|
||||
var iapResult = _iapHelper.ParseJavaIapResult(javaIapResult);
|
||||
var iapResult = IapHelper.ParseJavaIapResult(javaIapResult);
|
||||
if (!iapResult.IsSuccessful())
|
||||
{
|
||||
_logger.Warning("QueryPurchasesInternal failed with error code '{0}' and message: '{1}'",
|
||||
Logger.Warning("QueryPurchasesInternal failed with error code '{0}' and message: '{1}'",
|
||||
iapResult.Code, iapResult.Message);
|
||||
|
||||
HandleErrorCode(iapResult, () => {
|
||||
|
|
@ -640,7 +920,7 @@ namespace OneStore.Purchasing
|
|||
return;
|
||||
}
|
||||
|
||||
var purchasesList = _iapHelper.ParseJavaPurchasesList(javaPurchasesList);
|
||||
var purchasesList = IapHelper.ParseJavaPurchasesList(javaPurchasesList);
|
||||
if (purchasesList.Any())
|
||||
{
|
||||
_inventory.UpdatePurchaseInventory(purchasesList);
|
||||
|
|
@ -659,9 +939,21 @@ namespace OneStore.Purchasing
|
|||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles specific IAP error codes and executes the appropriate response.
|
||||
/// </summary>
|
||||
/// <param name="iapResult">The IAP result containing the error code.</param>
|
||||
/// <param name="action">An optional action to execute if the error code does not require a special response.</param>
|
||||
/// <remarks>
|
||||
/// - Retrieves the response code from the IAP result using `IapHelper.GetResponseCodeFromIapResult(iapResult)`.
|
||||
/// - If the response code is `RESULT_NEED_UPDATE`, triggers the `OnNeedUpdate` callback to prompt the user to update the ONE store service.
|
||||
/// - If the response code is `RESULT_NEED_LOGIN`, triggers the `OnNeedLogin` callback to prompt the user to log in.
|
||||
/// - If the response code is `ERROR_SERVICE_DISCONNECTED`, resets `_productInPurchaseFlow` and updates `_connectionStatus` to `DISCONNECTED`.
|
||||
/// - If none of the above cases match, the provided `action` (if any) is executed.
|
||||
/// </remarks>
|
||||
private void HandleErrorCode(IapResult iapResult, Action action = null)
|
||||
{
|
||||
var responseCode = _iapHelper.GetResponseCodeFromIapResult(iapResult);
|
||||
var responseCode = IapHelper.GetResponseCodeFromIapResult(iapResult);
|
||||
switch (responseCode)
|
||||
{
|
||||
case ResponseCode.RESULT_NEED_UPDATE:
|
||||
|
|
@ -680,6 +972,14 @@ namespace OneStore.Purchasing
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the specified action on the main thread using the ONE store dispatcher.
|
||||
/// </summary>
|
||||
/// <param name="action">The action to execute on the main thread.</param>
|
||||
/// <remarks>
|
||||
/// - Calls `OneStoreDispatcher.RunOnMainThread()` to ensure that the provided action runs on the main UI thread.
|
||||
/// - This is useful for updating UI elements or triggering callbacks that require execution on the main thread.
|
||||
/// </remarks>
|
||||
private void RunOnMainThread(Action action)
|
||||
{
|
||||
OneStoreDispatcher.RunOnMainThread(() => action());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 83bea0b014e634756af66f3a340f9ed8
|
||||
guid: a428fd88042f746e8a7b125eea2b255c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using OneStore.Purchasing.Internal;
|
||||
using Logger = OneStore.Common.OneStoreLogger;
|
||||
|
||||
namespace OneStore.Purchasing
|
||||
{
|
||||
|
|
@ -29,6 +30,7 @@ namespace OneStore.Purchasing
|
|||
|
||||
public long PurchaseTime { get { return _purchaseMeta.purchaseTime; } }
|
||||
|
||||
[Obsolete]
|
||||
public string PurchaseId { get { return _purchaseMeta.purchaseId; } }
|
||||
|
||||
public string PurchaseToken { get { return _purchaseMeta.purchaseToken; } }
|
||||
|
|
@ -61,9 +63,11 @@ namespace OneStore.Purchasing
|
|||
purchaseData = new PurchaseData(purchaseMeta, jsonPurchaseData, signature);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Error is logged at the caller side.
|
||||
Logger.Error("[PurchaseData]: Failed to parse purchase data: {0}", jsonPurchaseData);
|
||||
Logger.Exception(ex);
|
||||
|
||||
purchaseData = null;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -71,7 +75,12 @@ namespace OneStore.Purchasing
|
|||
|
||||
public AndroidJavaObject ToJava()
|
||||
{
|
||||
return new AndroidJavaObject(Constants.PurchaseDataClass, _purchaseReceipt.json);
|
||||
return new AndroidJavaObject(
|
||||
Constants.PurchaseDataClass,
|
||||
_purchaseReceipt.json,
|
||||
_purchaseReceipt.signature,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
|
@ -96,12 +105,12 @@ namespace OneStore.Purchasing
|
|||
private class PurchaseReceipt
|
||||
{
|
||||
public string json;
|
||||
public string sigature;
|
||||
public string signature;
|
||||
|
||||
public PurchaseReceipt(string jsonPurchaseData, string signature)
|
||||
{
|
||||
json = jsonPurchaseData;
|
||||
this.sigature = signature;
|
||||
this.signature = signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 32d816303781743ebbef5fd546e63d01
|
||||
guid: c0c9deb7e41a54ff9a7af2666ad1f463
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a28e0eadc8ecc49d1a29b4b0ae1e942a
|
||||
guid: 92dd96d95eedf4f149d2f39a1b4b0748
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fb3ca9121fecd400388c947a7a42b506
|
||||
guid: 8d580cce6b60743eabfc1ecb92344eeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue