Skip to main content

Manage third-party subscriptions

Last updated on October 15, 2024

Overview

AccelByte Gaming Services (AGS) can be integrated with Apple and Google Play to manage player subscriptions. This integration enables you to synchronize subscription data for players who log into your game using their Apple or Google Play accounts.

This article walks you through how to:

  • Integrate Apple and Google Play to manage player subscriptions
  • Manage player subscriptions in the AGS Admin Portal
  • Retrieve player subscription data via API
note

This integration is different from the Subscription item type that is supported in the AGS Store. For more information, see the create store items page.

Prerequisites

  • In-App Purchase (IAP) Configuration: Ensure that Google Play and Apple IAP have been configured in your namespace. For more information, see Third-party store integrations.
  • Apple or Google Play login methods: Ensure that the Apple or Google Play login method is enabled for your game. For more information, refer to the integration guide for Apple or Google.
  • Admin Permissions: Ensure you have the required admin permissions to access the Lookup Subscribers feature in the Admin Portal.
  • Unreal Engine SDK Implementation:
    • Unreal Engine: Players must be logged in to the AGS OSS and the Apple or GooglePlay OSS.
  • Unity SDK Implementation:

Integrate Apple and Google Play

Unreal Engine

const IOnlineSubsystem* OnlineSubsystemABPtr = IOnlineSubsystem::Get("ACCELBYTE");
if (OnlineSubsystemABPtr == nullptr)
{
Result.ExecuteIfBound("AB subsystem nullptr");
return;
}

check(OnlineSubsystemABPtr->GetIdentityInterface())
auto UniqueNetId = (OnlineSubsystemABPtr->GetIdentityInterface()->GetUniquePlayerId(LocalUserNum).Get());
auto ABIdentityInterface = StaticCastSharedPtr<FOnlineIdentityAccelByte>(OnlineSubsystemABPtr->GetIdentityInterface());


// OPTIONAL
// For Apple: Find the configuration on your developer Apple dashboard, the URL shows subscription group ID
// For Google: Find the configuration on your developer GooglePlay dashboard, use the ProductId from your Products>Subscriptions
FString SubscriptionGroupId = "21544099";

// For Apple: Find the configuration on your developer Apple dashboard
// For Google: Find the configuration on your developer GooglePlay dashboard, use the base plan name from your Products>Subscriptions
FString SubscriptionProductId = ProductID;

// If true, it excludes the expired subscription
bool bIsActiveOnly = true;

FOnlineQuerySubscriptionRequestAccelByte QueryRequest;
QueryRequest.ActiveOnly = bIsActiveOnly;
QueryRequest.ProductId = SubscriptionProductId;
QueryRequest.GroupId = SubscriptionGroupId;
QueryRequest.QueryPaging = FPagedQuery(0, 20); // The default paging start from index 0 and the amount is 20


// OnQueryEachEntitlement is an example of delegate

auto ResponseOnSuccess = FOnQueryPlatformSubscriptionCompleteDelegate::CreateLambda([&, OnQueryEachEntitlement](int32 _LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const TArray<FAccelByteModelsThirdPartySubscriptionTransactionInfo>& QueryResult, const FOnlineError& Error)
{
if (QueryResult.Num() == 0)
{
OnQueryEachEntitlement.ExecuteIfBound(false, "EMPTY ARRAY");
}
else
{
FString SerializedResult = "EMPTY Data";
FJsonObjectConverter::UStructToJsonObjectString(QueryResult[0], SerializedResult);
OnQueryEachEntitlement.ExecuteIfBound(true, SerializedResult);
}
});
ABEntitlementInterfacePtr->AddOnQueryPlatformSubscriptionCompleteDelegate_Handle(LocalUserNum, ResponseOnSuccess);
ABEntitlementInterfacePtr->QueryPlatformSubscription(LocalUserNum, QueryRequest);

Unity

  1. Sign in with Google Play Games. For more information about this sign-in method, refer to the our Unity SDK guide for Apple.

  2. Create a MonoBehavior class implementing IDetailedStoreListener. Unity IAP will handle the purchase and trigger callbacks using this interface. Then, prepare the following variables.

    IStoreController storeController;

    public Button BuySeasonPassButton;

    private string seasonPassProductId = "item_season_pass"; // Assume that the registered subscription product ID is named item_season_pass
    private ProductType seasonPassProductType = ProductType.Subscription;
  3. Prepare a script button to login and trigger the purchasing event. Using Unity Editor's inspector, attach those buttons into public Button BuySeasonPassButton;.

  4. Initialize Purchasing.

    void Start()
    {
    InitializePurchasing();
    }

    void InitializePurchasing()
    {
    var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

    // Add the purchasable products and indicate their types
    builder.AddProduct(seasonPassProductId, seasonPassProductType);

    // Assign its ApplicationUsername
    if (!string.IsNullOrEmpty(AccelByteSDK.GetClientRegistry().GetApi().GetUser().Session.UserId))
    {
    var uid = System.Guid.Parse(AccelByteSDK.GetClientRegistry().GetApi().GetUser().Session.UserId);
    appleExtensions.SetApplicationUsername(uid.ToString());
    }
    else
    {
    Debug.LogError($"Player is not logged in. Several features may not work properly");
    }
    }

    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
    Debug.Log("In-App Purchasing successfully initialized");
    storeController = controller;
    appleExtensions = extensions.GetExtension<IAppleExtensions>();
    }
  5. Prepare a function that will trigger the purchasing event.

    event
    private void BuySeasonPass()
    {
    storeController.InitiatePurchase(seasonPassProductId);
    }
  6. Assign the button.

    void Start()
    {
    ButtonAssigning();
    }

    void ButtonAssigning()
    {
    BuySeasonPassButton.onClick.AddListener(BuySeasonPass);
    }
  7. Handle Process Purchase. Note that it must return PurchaseProcessingResult.Pending because the purchased item will be synchronized with the AGS backend. See Unity's documentation on Processing Purchases. If the game client successfully purchases an item from Apple, ProcessPurchase will be triggered, else OnPurchaseFailed will be triggered.


    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs purchaseEvent)
    {
    var product = purchaseEvent.purchasedProduct;

    Debug.Log($"Purchase Complete - Product: {product.definition.id}");
    AGSSubscriptionEntitlementSync(product);

    return PurchaseProcessingResult.Pending;
    }

    public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    {
    Debug.LogError($"Purchase failed - Product: '{product.definition.id}', PurchaseFailureReason: {failureReason}");
    }
  8. Synchronize Purchased Product with AGS.

    private void AGSSubscriptionEntitlementSync(Product purchasedSubscription)
    {
    // Note that sync will work after the player is logged in using AGS service
    try
    { AccelByteSDK.GetClientRegistry().GetApi().GetEntitlement().SyncMobilePlatformSubscriptionApple(purchasedSubscription.appleOriginalTransactionID
    , result =>
    {
    if (result.IsError)
    {
    Debug.Log($"{purchasedSubscription.definition.id} failed to sync with AB [{result.Error.Code}]:{result.Error.Message}");
    return;
    }
    Debug.Log($"{purchasedSubscription.definition.id} is synced with AB");

    FinalizePurchase(purchasedSubscription);
    });
    }
    catch (Exception e)
    {
    Debug.LogError($"Failed to sync with AB {e.Message}");
    }
    }
  9. Finalize Pending Purchase.

    private void FinalizePurchase(Product purchasedProduct)
    {
    Debug.Log($"Confirm Pending Purchase for: {purchasedProduct.definition.id}");
    storeController.ConfirmPendingPurchase(purchasedProduct);
    }
  10. Query the subscription. The full script on the package samples is named "In App Purchase."

    public void QuerySubscription()
    {
    PlatformStoreId storeId = new PlatformStoreId(PlatformType.Apple);
    var userId = AccelByteSDK.GetClientRegistry().GetApi().GetUser().Session.UserId;
    AccelByteSDK.GetClientRegistry().GetApi().GetEntitlement().QueryUserSubscription(storeId, userId, result =>
    {
    if (result.IsError)
    {
    Debug.LogWarning($"Failed to Query Subscription [{result.Error.Code}]:{result.Error.Message}");
    return;
    }

    bool found = false;
    foreach (var eInfo in result.Value.Data)
    {
    if (eInfo.SubscriptionGroupId == seasonPassProductId)
    {
    found = true;
    break;
    }
    }

    Debug.Log($"Subscribe Season Pass: {found.ToString().ToUpper()}");
    });
    }

Manage player subscriptions in the Admin Portal

View player subscription details

  1. On the Admin Portal sidebar, go to Live Service Utilities > Lookup Subscribers.

  2. In the Google or Apple tab, search for a player using their player ID. You can also search for a player using their Google Product ID (for Google) or Subscription Group ID (for Apple).

    A list of players with their subscription statuses will be displayed, including:

    • User ID: The player's unique identifier.
    • Google Product ID (for Google) or Subscription Group ID (for Apple): The identifier for the subscription.
    • Status: The current subscription status, i.e., Active or Inactive.
    • Subscription End Date: The date when the subscription will expire or renew.
  3. From the results list, click View on the player with the details you want to view. The subscription details page of the player appears.

Synchronize player subscription details

To manually synchronize a player's subscription data, go to the player's subscription details page and click on the Sync button.

Retrieve player subscription data via API

Game clients can use the Public Subscription endpoint to directly interact with AGS services to query subscription data. This endpoint allows game clients to query user subscriptions from either the Apple or Google Play platform. It provides real-time access to subscription data, enabling the client to stay up-to-date with the latest changes.

API details

Path/public/namespaces/{namespace}/users/{userId}/iap/subscriptions/platforms/{platform}
MethodGET
DescriptionQuery user subscription status, sorted by updatedAt.
PermissionNAMESPACE:{namespace}:USER:{userId}:IAP [READ]
Path parameterGOOGLE or APPLE

Request parameters

ParameterTypeConditionDescription
groupIdstringOptionalThe identifier for the subscription group. A subscription group includes related subscription products with different offerings. For example, com.newspaper.subscription could be a group that includes various subscription options for a digital newspaper.
productIdstringOptionalThe unique identifier for a specific subscription product within a group. For instance, within the com.newspaper.subscription group, you might have com.newspaper.weekly, com.newspaper.monthly, and com.newspaper.yearly.
activeOnlybooleanOptionalIf set to true, only active subscriptions will be returned.
offsetintegerOptionalThe pagination offset. This parameter's default value is 0.
limitintegerOptionalThe number of results to return. This parameter's default value is 20.

Sample request

GET /public/namespaces/{namespace}/users/{userId}/iap/subscriptions/platforms/google

Response information

The response for Public Subscription endpoint requests contains the following information:

ParameterDescription
platformTarget platform of the request: APPLE or GOOGLE.
activeIndicates whether the subscription is active
statusThe subscription status, e.g., EXPIRED and ACTIVE.
subscriptionGroupIdThe subscription group identifier.
subscriptionProductIdThe product identifier for the subscription.
startAtThe start date of the subscription.
expiredAtThe expiration date of the subscription.
lastTransactionIdThe ID of the last transaction.
createdAtThe date the subscription was created.
updatedAtThe date for when the subscription data was last updated.