API Reference of GS2-Money2 SDK for Game Engine

Specifications of models and API references for GS2-SDK for Game Engine

Model

EzWallet

Wallet

Currency in the wallet is managed separately for currency purchased for a fee and currency obtained for free. Currency purchased for a fee is further managed by the unit price at the time of purchase, allowing for refunds in the event of service termination, or to determine if the balance is sufficient to meet the requirements of the Funds Settlement Act.

The wallet has slots and each slot has a different balance. If balances cannot be shared across platforms, they can be managed separately by using different slots for each platform. Currency acquired for free can also be shared across all platforms.

TypeRequireDefaultLimitationDescription
slotint~ 100000000Slot Number
summaryEzWalletSummaryWallet Status
sharedFreeCurrencyboolShare Free Currency
updatedAtlongNowDatetime of last update (Unix time unit:milliseconds)

EzWalletSummary

Wallet Status

TypeRequireDefaultLimitationDescription
paidint0~ 2147483646Count of Paid
freeint0~ 2147483646Count of Free
totalint0~ 2147483646Count of Total

EzDepositTransaction

Deposit Transaction

TypeRequireDefaultLimitationDescription
pricedouble~ 100000000.0Purchase Price
currencystring{price} > 0~ 8 charsCurrency Code
countint~ 2147483646Count

EzSubscribeTransaction

Subscription purchase information

TypeRequireDefaultLimitationDescription
contentNamestring~ 128 charsSubscription Store Content Model Name
storeenum {
    “AppleAppStore”,
    “GooglePlay”,
    “fake”
}
~ 128 charsStore
transactionIdstring~ 1024 charsTransaction ID
statusDetailenum {
    “active@active”,
    “active@converted_from_trial”,
    “active@in_trial”,
    “active@in_intro_offer”,
    “grace@canceled”,
    “grace@grace_period”,
    “grace@on_hold”,
    “inactive@expired”,
    “inactive@revoked”
}
~ 128 charsStatus
expiresAtlongExpiration date (Unix time unit:milliseconds)

Enumeration type definition to specify as store

Enumerator String DefinitionDescription
AppleAppStoreApple App Store
GooglePlayGoogle Play
fakeFake

Enumeration type definition to specify as statusDetail

Enumerator String DefinitionDescription
active@activeActive
active@converted_from_trialConverted from free trial to paid plan
active@in_trialIn free trial
active@in_intro_offerIn introductory offer
grace@canceledUser has manually canceled
grace@grace_periodUser has canceled, but still in grace period
grace@on_holdUser has canceled, but still in grace period
inactive@expiredSubscription has expired
inactive@revokedSubscription has been revoked

EzSubscriptionStatus

Subscription status

TypeRequireDefaultLimitationDescription
contentNamestring~ 128 charsSubscription Store Content Model Name
userIdstring~ 128 charsUser Id
statusenum {
    “active”,
    “inactive”
}
~ 128 charsStatus
expiresAtlongExpiration date (Unix time unit:milliseconds)
detailList<EzSubscribeTransaction>[]~ 100 itemsSubscription status details

Enumeration type definition to specify as status

Enumerator String DefinitionDescription
activeActive
inactiveInactive

Methods

get

Get Wallet

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token
slotint~ 100000000Slot Number

Result

TypeDescription
itemEzWalletWallet

Implementation Example

var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).Wallet( slot: 0 ); var item = await domain.ModelAsync();
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).Wallet( slot: 0 ); var future = domain.ModelFuture(); yield return future; var item = future.Result;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession )->Wallet( 0 // slot ); const auto Future = Domain->Model(); Future->StartSynchronousTask(); if (Future->GetTask().IsError()) { return false; }
Value change event handling
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).Wallet( slot: 0 ); // Start event handling var callbackId = domain.Subscribe( value => { // Called when the value changes // The "value" is passed the value after the change. } ); // Stop event handling domain.Unsubscribe(callbackId);
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).Wallet( slot: 0 ); var future = domain.ModelFuture(); yield return future; var item = future.Result;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession )->Wallet( 0 // slot ); // Start event handling const auto CallbackId = Domain->Subscribe( [](TSharedPtr<Gs2::Money2::Model::FWallet> value) { // Called when the value changes // The "value" is passed the value after the change. } ); // Stop event handling Domain->Unsubscribe(CallbackId);

list

Get list of wallets

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token

Result

TypeDescription
itemsList<EzWallet>List of Wallets
nextPageTokenstringPage token to retrieve the rest of the listing

Implementation Example

var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var items = await domain.WalletsAsync( ).ToListAsync();
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var it = domain.Wallets( ); List<EzWallet> items = new List<EzWallet>(); while (it.HasNext()) { yield return it.Next(); if (it.Error != null) { onError.Invoke(it.Error, null); break; } if (it.Current != null) { items.Add(it.Current); } else { break; } }
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession ); const auto It = Domain->Wallets( ); TArray<Gs2::UE5::Money2::Model::FEzWalletPtr> Result; for (auto Item : *It) { if (Item.IsError()) { return false; } Result.Add(Item.Current()); }
Value change event handling
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); // Start event handling var callbackId = domain.SubscribeWallets( () => { // Called when an element of the list changes. } ); // Stop event handling domain.UnsubscribeWallets(callbackId);
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var it = domain.Wallets( ); List<EzWallet> items = new List<EzWallet>(); while (it.HasNext()) { yield return it.Next(); if (it.Error != null) { onError.Invoke(it.Error, null); break; } if (it.Current != null) { items.Add(it.Current); } else { break; } }
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession ); // Start event handling const auto CallbackId = Domain->SubscribeWallets( []() { // Called when an element of the list changes. } ); // Stop event handling Domain->UnsubscribeWallets(CallbackId);

withdraw

Consume the balance from the wallet

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token
slotint~ 100000000Slot Number
withdrawCountint1 ~ 2147483646Quantity of billable currency to be consumed
paidOnlyboolfalseOnly for paid currency

Result

TypeDescription
itemEzWalletPost-withdraw Wallet
withdrawTransactionsList<EzDepositTransaction>List of consumed deposit transactions

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
ConflictExceptionConflictExceptionThe wallet operation process conflicted. Retry required.
InsufficientExceptionBadRequestExceptionWallet balance is insufficient.

Implementation Example

try { var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).Wallet( slot: 0 ); var result = await domain.WithdrawAsync( withdrawCount: 50, paidOnly: null ); var item = await result.ModelAsync(); var withdrawTransactions = result.WithdrawTransactions; } catch(Gs2.Gs2Money2.Exception.Conflict e) { // The wallet operation process conflicted. Retry required. } catch(Gs2.Gs2Money2.Exception.Insufficient e) { // Wallet balance is insufficient. }
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).Wallet( slot: 0 ); var future = domain.WithdrawFuture( withdrawCount: 50, paidOnly: null ); yield return future; if (future.Error != null) { if (future.Error is Gs2.Gs2Money2.Exception.ConflictException) { // The wallet operation process conflicted. Retry required. } if (future.Error is Gs2.Gs2Money2.Exception.InsufficientException) { // Wallet balance is insufficient. } onError.Invoke(future.Error, null); yield break; } var future2 = future.Result.ModelFuture(); yield return future2; if (future2.Error != null) { onError.Invoke(future2.Error, null); yield break; } var result = future2.Result; var withdrawTransactions = future.Result.WithdrawTransactions;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession )->Wallet( 0 // slot ); const auto Future = Domain->Withdraw( 50 // withdrawCount // paidOnly ); Future->StartSynchronousTask(); if (Future->GetTask().IsError()) { auto e = Future->GetTask().Error(); if (e->IsChildOf(Gs2::Money2::Error::FConflictError::Class)) { // The wallet operation process conflicted. Retry required. } if (e->IsChildOf(Gs2::Money2::Error::FInsufficientError::Class)) { // Wallet balance is insufficient. } return false; } // obtain changed values / result values const auto Future2 = Future->GetTask().Result()->Model(); Future2->StartSynchronousTask(); if (Future2->GetTask().IsError()) { return Future2->GetTask().Error(); } const auto Result = Future2->GetTask().Result(); const auto WithdrawTransactions = Result->WithdrawTransactions;

allocateSubscriptionStatus

Allocate subscription status from receipt

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token
receiptstring~ 1024 charsReceipt

Result

TypeDescription
itemEzSubscriptionStatusSubscription status

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
AlreadyUsedExceptionBadRequestExceptionThe subscription contract for that period has already been used by another user.

Implementation Example

try { var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var result = await domain.AllocateSubscriptionStatusAsync( receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" ); var item = await result.ModelAsync(); } catch(Gs2.Gs2Money2.Exception.AlreadyUsed e) { // The subscription contract for that period has already been used by another user. }
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var future = domain.AllocateSubscriptionStatusFuture( receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" ); yield return future; if (future.Error != null) { if (future.Error is Gs2.Gs2Money2.Exception.AlreadyUsedException) { // The subscription contract for that period has already been used by another user. } onError.Invoke(future.Error, null); yield break; } var future2 = future.Result.ModelFuture(); yield return future2; if (future2.Error != null) { onError.Invoke(future2.Error, null); yield break; } var result = future2.Result;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession ); const auto Future = Domain->AllocateSubscriptionStatus( "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" // receipt ); Future->StartSynchronousTask(); if (Future->GetTask().IsError()) { auto e = Future->GetTask().Error(); if (e->IsChildOf(Gs2::Money2::Error::FAlreadyUsedError::Class)) { // The subscription contract for that period has already been used by another user. } return false; } // obtain changed values / result values const auto Future2 = Future->GetTask().Result()->Model(); Future2->StartSynchronousTask(); if (Future2->GetTask().IsError()) { return Future2->GetTask().Error(); } const auto Result = Future2->GetTask().Result();

getSubscriptionStatus

Get Subscription status

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token
contentNamestring~ 128 charsSubscription Store Content Model Name

Result

TypeDescription
itemEzSubscriptionStatusSubscription status

Implementation Example

var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).SubscriptionStatus( contentName: "content-0001" ); var item = await domain.ModelAsync();
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).SubscriptionStatus( contentName: "content-0001" ); var future = domain.ModelFuture(); yield return future; var item = future.Result;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession )->SubscriptionStatus( "content-0001" // contentName ); const auto Future = Domain->Model(); Future->StartSynchronousTask(); if (Future->GetTask().IsError()) { return false; }
Value change event handling
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).SubscriptionStatus( contentName: "content-0001" ); // Start event handling var callbackId = domain.Subscribe( value => { // Called when the value changes // The "value" is passed the value after the change. } ); // Stop event handling domain.Unsubscribe(callbackId);
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ).SubscriptionStatus( contentName: "content-0001" ); var future = domain.ModelFuture(); yield return future; var item = future.Result;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession )->SubscriptionStatus( "content-0001" // contentName ); // Start event handling const auto CallbackId = Domain->Subscribe( [](TSharedPtr<Gs2::Money2::Model::FSubscriptionStatus> value) { // Called when the value changes // The "value" is passed the value after the change. } ); // Stop event handling Domain->Unsubscribe(CallbackId);

listSubscriptionStatuses

Get list of subscription statuses

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token

Result

TypeDescription
itemsList<EzSubscriptionStatus>List of Subscription statuses

Implementation Example

var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var items = await domain.SubscriptionStatusesAsync( ).ToListAsync();
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var it = domain.SubscriptionStatuses( ); List<EzSubscriptionStatus> items = new List<EzSubscriptionStatus>(); while (it.HasNext()) { yield return it.Next(); if (it.Error != null) { onError.Invoke(it.Error, null); break; } if (it.Current != null) { items.Add(it.Current); } else { break; } }
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession ); const auto It = Domain->SubscriptionStatuses( ); TArray<Gs2::UE5::Money2::Model::FEzSubscriptionStatusPtr> Result; for (auto Item : *It) { if (Item.IsError()) { return false; } Result.Add(Item.Current()); }
Value change event handling
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); // Start event handling var callbackId = domain.SubscribeSubscriptionStatuses( () => { // Called when an element of the list changes. } ); // Stop event handling domain.UnsubscribeSubscriptionStatuses(callbackId);
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var it = domain.SubscriptionStatuses( ); List<EzSubscriptionStatus> items = new List<EzSubscriptionStatus>(); while (it.HasNext()) { yield return it.Next(); if (it.Error != null) { onError.Invoke(it.Error, null); break; } if (it.Current != null) { items.Add(it.Current); } else { break; } }
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession ); // Start event handling const auto CallbackId = Domain->SubscribeSubscriptionStatuses( []() { // Called when an element of the list changes. } ); // Stop event handling Domain->UnsubscribeSubscriptionStatuses(CallbackId);

takeOverSubscriptionStatus

Take over the subscription status of a subscription that is already assigned to another user

Request

TypeRequireDefaultLimitationDescription
namespaceNamestring~ 128 charsNamespace Name
accessTokenstring~ 128 charsAccess token
receiptstring~ 1024 charsReceipt

Result

TypeDescription
itemEzSubscriptionStatusSubscription status

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
LockPeriodNotElapsedExceptionBadRequestExceptionThe lock period has not elapsed since the last user change.

Implementation Example

try { var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var result = await domain.TakeOverSubscriptionStatusAsync( receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" ); var item = await result.ModelAsync(); } catch(Gs2.Gs2Money2.Exception.LockPeriodNotElapsed e) { // The lock period has not elapsed since the last user change. }
var domain = gs2.Money2.Namespace( namespaceName: "namespace-0001" ).Me( gameSession: GameSession ); var future = domain.TakeOverSubscriptionStatusFuture( receipt: "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" ); yield return future; if (future.Error != null) { if (future.Error is Gs2.Gs2Money2.Exception.LockPeriodNotElapsedException) { // The lock period has not elapsed since the last user change. } onError.Invoke(future.Error, null); yield break; } var future2 = future.Result.ModelFuture(); yield return future2; if (future2.Error != null) { onError.Invoke(future2.Error, null); yield break; } var result = future2.Result;
const auto Domain = Gs2->Money2->Namespace( "namespace-0001" // namespaceName )->Me( GameSession ); const auto Future = Domain->TakeOverSubscriptionStatus( "{\"Store\": \"AppleAppStore\", \"TransactionID\": \"transaction-0001\", \"Payload\": \"payload\"}" // receipt ); Future->StartSynchronousTask(); if (Future->GetTask().IsError()) { auto e = Future->GetTask().Error(); if (e->IsChildOf(Gs2::Money2::Error::FLockPeriodNotElapsedError::Class)) { // The lock period has not elapsed since the last user change. } return false; } // obtain changed values / result values const auto Future2 = Future->GetTask().Result()->Model(); Future2->StartSynchronousTask(); if (Future2->GetTask().IsError()) { return Future2->GetTask().Error(); } const auto Result = Future2->GetTask().Result();

Event Handler

OnChangeSubscriptionStatus

Notification when the subscription status of the period changes

NameTypeDescription
namespaceNamestringNamespace Name
userIdstringUser Id
contentNamestringSubscription Store Content Model Name

Implementation Example

gs2.Money2.OnChangeSubscriptionStatus += notification => { var namespaceName = notification.NamespaceName; var userId = notification.UserId; var contentName = notification.ContentName; };
gs2.Money2.OnChangeSubscriptionStatus += notification => { var namespaceName = notification.NamespaceName; var userId = notification.UserId; var contentName = notification.ContentName; };
Gs2->Money2->OnChangeSubscriptionStatus().AddLambda([](const auto Notification) { const auto NamespaceName = Notification->NamespaceNameValue; const auto UserId = Notification->UserIdValue; const auto ContentName = Notification->ContentNameValue; });