Freigeben über


Erste Schritte mit Economy v2, Unity und Android

Wichtig

Economy v2 ist jetzt allgemein verfügbar. Unterstützung und Feedback erhalten Sie im PlayFab-Forum.

In diesem Tutorial erfahren Sie, wie Sie In-App Purchase (IAP) mithilfe von PlayFab, dem Unity + IAP-Dienst und der Android-Abrechnungs-API einrichten.

Bevor wir beginnen

Die Android-Abrechnungs-API und PlayFab arbeiten zusammen, um Ihrem Client eine IAP-Erfahrung zu bieten:

PlayFab Economy v2 – Einlösungszeitachse

Beginnen Sie, indem Sie Ihre Produkt-IDs und Preise über PlayMarket einrichten. Anfangs sind alle Produkte gesichtslos - digitale Entitäten, die Ihr Spieler kaufen kann - aber keine Bedeutung für PlayFab-Spieler.

Damit diese Entitäten nützlich sind, müssen wir sie in den PlayFab-Elementkatalogen Spiegel. PlayFab wandelt gesichtslose Entitäten in Bündel, Container und einzelne Elemente um.

Jede hat ihr eigenes, einzigartiges Gesicht, mit:

  • Titel
  • Beschreibungen
  • Tags
  • Typen
  • Bilder
  • Verhaltensweisen

Alle Artikel sind mit Marktprodukten verknüpft, indem IDs geteilt werden.

Die beste Möglichkeit für den Zugriff auf Echtgeldartikel, die zum Kauf verfügbar sind, ist die Verwendung von GetItems.

Die ID des Elements ist die Verknüpfung zwischen PlayFab und einem beliebigen externen IAP-System. Daher übergeben wir die Element-ID an den IAP-Dienst.

An diesem Punkt beginnt der Kaufprozess. Der Spieler interagiert mit der IAP-Schnittstelle und - wenn der Kauf erfolgreich ist - erhalten Sie eine Quittung.

PlayFab überprüft den Beleg und registriert den Kauf, sodass der PlayFab-Spieler die soeben gekauften Elemente gewährt.

Einrichten einer Clientanwendung

In diesem Abschnitt erfahren Sie, wie Sie eine Anwendung zum Testen von IAP mit PlayFab, UnityIAP und der Android-Abrechnungs-API konfigurieren.

Voraussetzungen:

  • Ein Unity-Projekt.
  • Das PlayFab Unity SDK wurde importiert und konfiguriert, um mit Ihrem Titel zu arbeiten.
  • Ein Editor wie Visual Studio ist installiert und für die Arbeit mit Ihrem Unity-Projekt konfiguriert.

Unser erster Schritt ist das Einrichten von UnityIAP:

  1. Navigieren Sie zu Dienste.
  2. Stellen Sie sicher, dass die Registerkarte Dienste ausgewählt ist.
  3. Wählen Sie Ihr Unity Services-Profil oder organization aus.
  4. Wählen Sie die Schaltfläche Erstellen aus.

Einrichten des UnityIAP-Diensts

  1. Navigieren Sie als Nächstes zum Dienst In-App Purchase (IAP).

Navigieren Sie zum UnityIAP-Dienst.

  1. Stellen Sie sicher, dass Sie den Dienst aktivieren, indem Sie die Umschaltfläche Plattformübergreifende IAP vereinfachen festlegen.

  2. Wählen Sie dann die Schaltfläche Weiter aus.

Aktivieren des UnityIAP-Diensts

Eine Seite mit einer Liste von Plug-Ins wird angezeigt.

  1. Wählen Sie die Schaltfläche Importieren aus.

UnityIAP-Dienst – Importieren von Plug-Ins

Setzen Sie die Unity-Installation und den Importvorgang bis zu dem Punkt fort, an dem alle Plug-Ins importiert wurden.

  1. Vergewissern Sie sich, dass die Plug-Ins vorhanden sind.
  2. Erstellen Sie dann ein neues Skript namens AndroidIAPExample.cs.

UnityIAP: Erstellen eines neuen Skripts

AndroidIAPExample.cs enthält den folgenden Code (weitere Erläuterungen finden Sie in den Codekommentaren).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Extension;

using PlayFab;
using PlayFab.ClientModels;
using PlayFab.EconomyModels;

/// <summary>
/// Unity behavior that implements the the Unity IAP Store interface.
/// Attach as an asset to your Scene.
/// </summary>
public class AndroidIAPExample : MonoBehaviour, IDetailedStoreListener
{
    // Bundles for sale on the Google Play Store.
    private Dictionary<string, PlayFab.EconomyModels.CatalogItem> _googlePlayCatalog;

    // In-game items for sale at the example vendor.
    private Dictionary<string, PlayFab.EconomyModels.CatalogItem> _storefrontCatalog;

    private string _purchaseIdempotencyId = null;

    private PlayFabEconomyAPIAsyncResult _lastAPICallResult = null;

    private static readonly PlayFabEconomyAPIAsync s_economyAPI = new();

    private static IStoreController s_storeController;

    // TODO: This callback is for illustrations purposes, you should create one that fits your needs
    public delegate void PlayFabProcessPurchaseCallback(PurchaseProcessingResult result);

    /// <summary>
    /// Event that is triggered when a purchase is processed.
    /// </summary>
    /// <remarks>
    /// TODO: Subscribe to this event in your game code to handle purchase results.
    /// </remarks>
    public event PlayFabProcessPurchaseCallback PlayFabProcessPurchaseEvent;

    /// <summary>
    /// True if the Store Controller, extensions, and Catalog are set.
    /// </summary>
    public bool IsInitialized => s_storeController != null
                             && _googlePlayCatalog != null
                             && _storefrontCatalog != null;

    // Start is called before the first frame update.
    public void Start()
    {
        Login();
    }

    /// <summary>
    /// Attempts to log the player in via the Android Device ID.
    /// </summary>
    private void Login()
    {
        // TODO: it is better to use LoginWithGooglePlayGamesService or a similar platform-specific login method for final game code.

        // SystemInfo.deviceUniqueIdentifier will prompt for permissions on newer devices.
        // Using a non-device specific GUID and saving to a local file
        // is a better approach. PlayFab does allow you to link multiple
        // Android device IDs to a single PlayFab account.
        PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest()
        {
            CreateAccount = true,
            CustomId = SystemInfo.deviceUniqueIdentifier
        }, result => RefreshIAPItems(), PlayFabSampleUtil.OnPlayFabError);
    }

    /// <summary>
    /// Queries the PlayFab Economy Catalog V2 for updated listings
    /// and then fills the local catalog objects.
    /// </summary>
    private async void RefreshIAPItems()
    {
        _googlePlayCatalog = new Dictionary<string, PlayFab.EconomyModels.CatalogItem>();
        SearchItemsRequest googlePlayCatalogRequest = new()
        {
            Count = 50,
            Filter = "AlternateIds/any(t: t/type eq 'GooglePlay')"
        };

        SearchItemsResponse googlePlayCatalogResponse;
        do
        {
            googlePlayCatalogResponse = await s_economyAPI.SearchItemsAsync(googlePlayCatalogRequest);
            Debug.Log("Search response: " + JsonUtility.ToJson(googlePlayCatalogResponse));

            foreach (PlayFab.EconomyModels.CatalogItem item in googlePlayCatalogResponse.Items)
            {
                _googlePlayCatalog.Add(item.Id, item);
            }

        } while (!string.IsNullOrEmpty(googlePlayCatalogResponse.ContinuationToken));

        Debug.Log($"Completed pulling from PlayFab Economy v2 googleplay Catalog: {_googlePlayCatalog.Count()} items retrieved");

        _storefrontCatalog = new Dictionary<string, PlayFab.EconomyModels.CatalogItem>();
        GetItemRequest storeCatalogRequest = new()
        {
            AlternateId = new CatalogAlternateId()
            {
                Type = "FriendlyId",
                Value = "villagerstore"
            }
        };

        GetItemResponse storeCatalogResponse;
        storeCatalogResponse = await s_economyAPI.GetItemAsync(storeCatalogRequest);
        List<string> itemIds = new();

        foreach (CatalogItemReference item in storeCatalogResponse.Item.ItemReferences)
        {
            itemIds.Add(item.Id);
        }

        GetItemsRequest itemsCatalogRequest = new()
        {
            Ids = itemIds
        };

        GetItemsResponse itemsCatalogResponse = await s_economyAPI.GetItemsAsync(itemsCatalogRequest);
        foreach (PlayFab.EconomyModels.CatalogItem item in itemsCatalogResponse.Items)
        {
            _storefrontCatalog.Add(item.Id, item);
        }

        Debug.Log($"Completed pulling from PlayFab Economy v2 villagerstore store: {_storefrontCatalog.Count()} items retrieved");

        InitializePurchasing();
    }

    /// <summary>
    /// Initializes the Unity IAP system for the Google Play Store.
    /// </summary>
    private void InitializePurchasing()
    {
        if (IsInitialized) return;

        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance(AppStore.GooglePlay));

        foreach (PlayFab.EconomyModels.CatalogItem item in _googlePlayCatalog.Values)
        {
            string googlePlayItemId = item.AlternateIds.FirstOrDefault(item => item.Type == "GooglePlay")?.Value;
            if (!string.IsNullOrWhiteSpace(googlePlayItemId))
            {
                builder.AddProduct(googlePlayItemId, ProductType.Consumable);
            }
        }

        UnityPurchasing.Initialize(this, builder);
    }

    /// <summary>
    /// Draw a debug IMGUI for testing examples.
    /// Use UI Toolkit for your production game runtime UI instead.
    /// </summary>
    public void OnGUI()
    {
        // Support high-res devices.
        GUI.matrix = Matrix4x4.TRS(new Vector3(0, 0, 0), Quaternion.identity, new Vector3(3, 3, 3));

        if (!IsInitialized)
        {
            GUILayout.Label("Initializing IAP and logging in...");
            return;
        }

        if (!string.IsNullOrEmpty(_purchaseIdempotencyId) && (!string.IsNullOrEmpty(_lastAPICallResult?.Message)
                                                           || !string.IsNullOrEmpty(_lastAPICallResult?.Error)))
        {
            GUILayout.Label(_lastAPICallResult?.Message + _lastAPICallResult?.Error);
        }

        GUILayout.Label("Shop for game currency bundles.");
        // Draw a purchase menu for each catalog item.
        foreach (PlayFab.EconomyModels.CatalogItem item in _googlePlayCatalog.Values)
        {
            // Use a dictionary to select the proper language.
            if (GUILayout.Button("Get " + (item.Title.ContainsKey("en-US") ? item.Title["en-US"] : item.Title["NEUTRAL"])))
            {
                BuyProductById(item.AlternateIds.FirstOrDefault(item => item.Type == "GooglePlay").Value);
            }
        }

        GUILayout.Label("Hmmm. (Translation: Welcome to my humble Villager store.)");
        // Draw a purchase menu for each catalog item.
        foreach (PlayFab.EconomyModels.CatalogItem item in _storefrontCatalog.Values)
        {
            // Use a dictionary to select the proper language.
            if (GUILayout.Button("Buy "
                + (item.Title.ContainsKey("en-US") ? item.Title["en-US"] : item.Title["NEUTRAL"]
                + ": "
                + item.PriceOptions.Prices.FirstOrDefault().Amounts.FirstOrDefault().Amount.ToString()
                + " Diamonds"
                )))
            {
                Task.Run(() => PlayFabPurchaseItemById(item.Id));
            }
        }
    }

    /// <summary>
    /// Integrates game purchasing with the Unity IAP API.
    /// </summary>
    public void BuyProductById(string productId)
    {
        if (!IsInitialized)
        {
            Debug.LogError("IAP Service is not initialized!");
            return;
        }

        s_storeController.InitiatePurchase(productId);
    }

    /// <summary>
    /// Purchases a PlayFab inventory item by ID.
    /// See the <see cref="PlayFabEconomyAPIAsync"/> class for details on error handling
    /// and calling patterns.
    /// </summary>
    async public Task<bool> PlayFabPurchaseItemById(string itemId)
    {
        if (!IsInitialized)
        {
            Debug.LogError("IAP Service is not initialized!");
            return false;
        }

        _lastAPICallResult = new();

        Debug.Log("Player buying product " + itemId);

        if (string.IsNullOrEmpty(_purchaseIdempotencyId))
        {
            _purchaseIdempotencyId = Guid.NewGuid().ToString();
        }

        GetItemRequest getVillagerStoreRequest = new()
        {
            AlternateId = new CatalogAlternateId()
            {
                Type = "FriendlyId",
                Value = "villagerstore"
            }
        };

        GetItemResponse getStoreResponse = await s_economyAPI.GetItemAsync(getVillagerStoreRequest);
        if (getStoreResponse == null || string.IsNullOrEmpty(getStoreResponse?.Item?.Id))
        {
            _lastAPICallResult.Error = "Unable to contact the store. Check your internet connection and try again in a few minutes.";
            return false;
        }

        CatalogPriceAmount price = _storefrontCatalog.FirstOrDefault(item => item.Key == itemId).Value.PriceOptions.Prices.FirstOrDefault().Amounts.FirstOrDefault();
        PurchaseInventoryItemsRequest purchaseInventoryItemsRequest = new()
        {
            Amount = 1,
            Item = new InventoryItemReference()
            {
                Id = itemId
            },
            PriceAmounts = new List<PurchasePriceAmount>
            {
                new()
                {
                    Amount = price.Amount,
                    ItemId = price.ItemId
                }
            },
            IdempotencyId = _purchaseIdempotencyId,
            StoreId = getStoreResponse.Item.Id
        };

        PurchaseInventoryItemsResponse purchaseInventoryItemsResponse = await s_economyAPI.PurchaseInventoryItemsAsync(purchaseInventoryItemsRequest);
        if (purchaseInventoryItemsResponse == null || purchaseInventoryItemsResponse?.TransactionIds.Count < 1)
        {
            _lastAPICallResult.Error = "Unable to purchase. Try again in a few minutes.";
            return false;
        }

        _purchaseIdempotencyId = "";
        _lastAPICallResult.Message = "Purchasing!";
        return true;
    }

    private void OnRegistration(LoginResult result)
    {
        PlayFabSettings.staticPlayer.ClientSessionTicket = result.SessionTicket;
    }

    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        s_storeController = controller;

        extensions.GetExtension<IGooglePlayStoreExtensions>().RestoreTransactions((result, error) => {
            if (result)
            {
                Debug.LogWarning("Restore transactions succeeded.");
            }
            else
            {
                Debug.LogWarning("Restore transactions failed.");
            }
        });
    }

    public void OnInitializeFailed(InitializationFailureReason error)
    {
        Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    }

    public void OnInitializeFailed(InitializationFailureReason error, string message)
    {
        Debug.Log("OnInitializeFailed InitializationFailureReason:" + error + message);
    }

    public void OnPurchaseFailed(UnityEngine.Purchasing.Product product, PurchaseFailureReason failureReason)
    {
        Debug.Log($"OnPurchaseFailed: FAIL. Product: '{product.definition.storeSpecificId}', PurchaseFailureReason: {failureReason}");
    }

    public void OnPurchaseFailed(UnityEngine.Purchasing.Product product, PurchaseFailureDescription failureDescription)
    {
        Debug.Log($"OnPurchaseFailed: FAIL. Product: '{product.definition.storeSpecificId}', PurchaseFailureReason: {failureDescription}");
    }

    /// <summary>
    /// Callback for Store purchases. Subscribe to PlayFabProcessPurchaseEvent to handle the final PurchaseProcessingResult.
    /// <see href="https://docs.unity3d.com/Packages/com.unity.purchasing@4.8/api/UnityEngine.Purchasing.PurchaseProcessingResult.html"/>
    /// </summary>
    /// <remarks>
    /// This code does not account for purchases that were pending and are
    /// delivered on application start. Production code should account for these cases.
    /// </remarks>
    /// <returns>Complete immediately upon error. Pending if PlayFab Economy is handling final processing and will trigger PlayFabProcessPurchaseEvent with the final result.</returns>
    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs purchaseEvent)
    {
        if (!IsInitialized)
        {
            Debug.LogWarning("Not initialized. Ignoring.");
            return PurchaseProcessingResult.Complete;
        }

        if (purchaseEvent.purchasedProduct == null)
        {
            Debug.LogWarning("Attempted to process purchase with unknown product. Ignoring.");
            return PurchaseProcessingResult.Complete;
        }

        if (string.IsNullOrEmpty(purchaseEvent.purchasedProduct.receipt))
        {
            Debug.LogWarning("Attempted to process purchase with no receipt. Ignoring.");
            return PurchaseProcessingResult.Complete;
        }

        Debug.Log("Attempting purchase with receipt " + purchaseEvent.purchasedProduct.receipt);
        GooglePurchase purchasePayload = GooglePurchase.FromJson(purchaseEvent.purchasedProduct.receipt);
        RedeemGooglePlayInventoryItemsRequest request = new()
        {
            Purchases = new List<GooglePlayProductPurchase>
            {
                new()
                {
                    ProductId = purchasePayload.PayloadData?.JsonData?.productId,
                    Token = purchasePayload.PayloadData?.JsonData?.purchaseToken
                }
            }
        };

        PlayFabEconomyAPI.RedeemGooglePlayInventoryItems(request, result =>
        {
            Debug.Log("Processed receipt validation.");

            if (result?.Failed.Count > 0)
            {
                Debug.Log($"Validation failed for {result.Failed.Count} receipts.");
                Debug.Log(JsonUtility.ToJson(result.Failed));
                PlayFabProcessPurchaseEvent?.Invoke(PurchaseProcessingResult.Pending);
            }
            else
            {
                Debug.Log("Validation succeeded!");
                PlayFabProcessPurchaseEvent?.Invoke(PurchaseProcessingResult.Complete);
                s_storeController.ConfirmPendingPurchase(purchaseEvent.purchasedProduct);
                Debug.Log("Confirmed purchase with Google Marketplace.");
            }
        },
        PlayFabSampleUtil.OnPlayFabError);

        return PurchaseProcessingResult.Pending;
    }
}

/// <summary>
/// Utility classes for the sample.
/// </summary>
public class PlayFabEconomyAPIAsyncResult
{
    public string Error { get; set; } = null;

    public string Message { get; set; } = null;
}

public static class PlayFabSampleUtil
{
    public static void OnPlayFabError(PlayFabError error)
    {
        Debug.LogError(error.GenerateErrorReport());
    }
}

/// <summary>
/// Example Async wrapper for PlayFab API's.
/// 
/// This is just a quick sample for example purposes.
/// 
/// Write your own customer Logger implementation to log and handle errors
/// for user-facing scenarios. Use tags and map which PlayFab errors require your
/// game to handle GUI or gameplay updates vs which should be logged to crash and
/// error reporting services.
/// </summary>
public class PlayFabEconomyAPIAsync
{
    /// <summary>
    /// <see href="https://learn.microsoft.com/rest/api/playfab/economy/catalog/get-item"/>
    /// </summary>
    public Task<GetItemResponse> GetItemAsync(GetItemRequest request)
    {
        TaskCompletionSource<GetItemResponse> getItemAsyncTaskSource = new();
        PlayFabEconomyAPI.GetItem(request, (response) => getItemAsyncTaskSource.SetResult(response), error => 
        {
            PlayFabSampleUtil.OnPlayFabError(error);
            getItemAsyncTaskSource.SetResult(default);
        });
        return getItemAsyncTaskSource.Task;
    }

    /// <summary>
    /// <see href="https://learn.microsoft.com/rest/api/playfab/economy/catalog/get-items"/>
    /// </summary>
    public Task<GetItemsResponse> GetItemsAsync(GetItemsRequest request)
    {
        TaskCompletionSource<GetItemsResponse> getItemsAsyncTaskSource = new();
        PlayFabEconomyAPI.GetItems(request, (response) => getItemsAsyncTaskSource.SetResult(response), error => 
        {
            PlayFabSampleUtil.OnPlayFabError(error);
            getItemsAsyncTaskSource.SetResult(default);
        });
        return getItemsAsyncTaskSource.Task;
    }

    /// <summary>
    /// <see href="https://learn.microsoft.com/rest/api/playfab/economy/inventory/purchase-inventory-items"/>
    /// </summary>
    public Task<PurchaseInventoryItemsResponse> PurchaseInventoryItemsAsync(PurchaseInventoryItemsRequest request)
    {
        TaskCompletionSource<PurchaseInventoryItemsResponse> purchaseInventoryItemsAsyncTaskSource = new();
        PlayFabEconomyAPI.PurchaseInventoryItems(request, (response) => purchaseInventoryItemsAsyncTaskSource.SetResult(response), error => 
        {
            PlayFabSampleUtil.OnPlayFabError(error);
            purchaseInventoryItemsAsyncTaskSource.SetResult(default);
        });
        return purchaseInventoryItemsAsyncTaskSource.Task;
    }

    /// <summary>
    /// <see href="https://learn.microsoft.com/rest/api/playfab/economy/catalog/search-items"/>
    /// </summary>
    public Task<SearchItemsResponse> SearchItemsAsync(SearchItemsRequest request)
    {
        TaskCompletionSource<SearchItemsResponse> searchItemsAsyncTaskSource = new();
        PlayFabEconomyAPI.SearchItems(request, (response) => searchItemsAsyncTaskSource.SetResult(response), error => 
        {
            PlayFabSampleUtil.OnPlayFabError(error);
            searchItemsAsyncTaskSource.SetResult(default);
        });
        return searchItemsAsyncTaskSource.Task;
    }
}

[Serializable]
public class PurchaseJsonData
{
    public string orderId;
    public string packageName;
    public string productId;
    public string purchaseToken;
    public long   purchaseTime;
    public int    purchaseState;
}

[Serializable]
public class PurchasePayloadData
{
    public PurchaseJsonData JsonData;

    public string signature;
    public string json;

    public static PurchasePayloadData FromJson(string json)
    {
        var payload = JsonUtility.FromJson<PurchasePayloadData>(json);
        payload.JsonData = JsonUtility.FromJson<PurchaseJsonData>(payload.json);
        return payload;
    }
}

[Serializable]
public class GooglePurchase
{
    public PurchasePayloadData PayloadData;

    public string Store;
    public string TransactionID;
    public string Payload;

    public static GooglePurchase FromJson(string json)
    {
        var purchase = JsonUtility.FromJson<GooglePurchase>(json);

        // Only fake receipts are returned in Editor play.
        if (Application.isEditor)
        {
            return purchase;
        }

        purchase.PayloadData = PurchasePayloadData.FromJson(purchase.Payload);
        return purchase;
    }
}
  1. Erstellen Sie ein neues GameObject mit dem Namen Code.
  2. Fügen Sie ihr die AndroidIAPExample Komponente hinzu (Klicken und Ziehen oder).
  3. Stellen Sie sicher, dass Sie die Szene speichern .

UnityIAP: Erstellen eines Beispielspielobjekts

Navigieren Sie abschließend zu Buildeinstellungen.

  1. Vergewissern Sie sich, dass Ihre Szene dem Bereich Szenen im Build hinzugefügt wurde.
  2. Stellen Sie sicher, dass die Android-Plattform ausgewählt wurde.
  3. Wechseln Sie zum Bereich Spielereinstellungen .
  4. Weisen Sie Ihren Paketnamen zu.

Notiz

Stellen Sie sicher, dass Sie Ihren eigenen Paketnamen verwenden, um PlayMarket-Konflikte zu vermeiden.

UnityIAP: Hinzufügen eines Beispielspielobjekts

Erstellen Sie schließlich die Anwendung wie gewohnt, und stellen Sie sicher, dass ein APK vorhanden ist.

Zum Testen müssen wir PlayMarket und PlayFab konfigurieren.

Einrichten einer PlayMarket-Anwendung für IAP

In diesem Abschnitt werden die Besonderheiten der Aktivierung von IAP für Ihre PlayMarket-Anwendung beschrieben.

Notiz

Das Einrichten der Anwendung selbst geht über den Rahmen dieses Tutorials hinaus. Wir gehen davon aus, dass Sie bereits über eine Anwendung verfügen, die so konfiguriert ist, dass mindestens Alphaversionen veröffentlicht werden.

Aktivieren der PlayMarket-Anwendung

Nützliche Hinweise:

  • Um zu diesem Punkt zu gelangen, müssen Sie ein APK hochgeladen haben. Verwenden Sie das APK, das wir im vorherigen Abschnitt erstellt haben.
  • Laden Sie das APK als Alpha- oder Betaanwendung hoch, um die IAP-Sandbox zu aktivieren.
  • Das Konfigurieren der Inhaltsbewertung umfasst Fragen zur Aktivierung von IAP in der Anwendung.
  • PlayMarket erlaubt Herausgebern nicht , IAP zu verwenden oder zu testen. Wählen Sie zu Testzwecken ein anderes Google-Konto aus, und fügen Sie es als Tester für Ihren Alpha/Beta-Build hinzu.
  1. Veröffentlichen Sie den Anwendungsbuild.

  2. Wählen Sie im Menü In-App-Produkte aus.

    • Wenn Sie nach einem Händlerkonto gefragt werden, verknüpfen oder erstellen Sie eins.
  3. Wählen Sie die Schaltfläche Neues Produkt hinzufügen aus.

    PlayMarket neues Produkt hinzufügen

  4. Wählen Sie auf dem Bildschirm "Neues Produkt " die Option Verwaltetes Produkt aus.

  5. Geben Sie ihm eine beschreibende Produkt-ID wie 100diamonds.

  6. Wählen Sie Weiter aus.

    PlayMarket: Produkt-ID hinzufügen

  7. PlayMarket erfordert, dass Sie einen Titel (1) und eine Beschreibung (2) eingeben, z. B 100 Diamonds . und A pack of 100 diamonds to spend in-game.

    Datenelementdaten stammen ausschließlich aus dem PlayFab-Dienst und erfordern nur IDs, die übereinstimmen.

    PlayMarket: Produkttitelbeschreibung hinzufügen

  8. Scrollen Sie weiter, und wählen Sie die Schaltfläche Add a price (Preis hinzufügen) aus .

    PlayMarket produktpreis hinzufügen

  9. Geben Sie einen gültigen Preis ein, z. B. "0,99 USD" (beachten Sie, wie der Preis für jedes Land/jede Region unabhängig konvertiert wird).

  10. Wählen Sie die Schaltfläche Übernehmen aus.

    PlayMarket produkt hinzufügen lokale Preise anwenden

  11. Scrollen Sie schließlich zurück zum oberen Bildschirmrand, und ändern Sie den status des Elements in Aktiv.

    PlayMarket macht produkt aktiv

  12. Speichern Sie den Lizenzierungsschlüssel , um PlayFab mit PlayMarket zu verknüpfen.

  13. Navigieren Sie im Menü zu Dienste &-APIs .

  14. Suchen Und speichern Sie dann die Base64-Version des Schlüssels.

PlayMarket: Speichern des Produktlizenzschlüssels

Der nächste Schritt besteht darin, IAP-Tests zu aktivieren. Die Sandbox ist zwar automatisch für Alpha- und Betabuilds aktiviert, aber wir müssen Konten einrichten, die zum Testen der App autorisiert sind:

  1. Navigieren Sie zu Start.
  2. Suchen Sie im Menü auf der linken Seite die Kontodetails , und wählen Sie sie aus.
  3. Suchen Sie den Bereich Lizenztests .
  4. Vergewissern Sie sich, dass Ihre Testkonten in der Liste enthalten sind.
  5. Stellen Sie sicher, dass die Lizenztestantwort auf RESPOND_NORMALLY festgelegt ist.

Vergessen Sie nicht, die Einstellungen anzuwenden!

PlayMarket: Aktivieren von IAP-Tests

Die Play Market-Seite der Integration sollte an diesem Punkt eingerichtet werden.

Einrichten eines PlayFab-Titels

Unser letzter Schritt besteht darin, einen PlayFab-Titel so zu konfigurieren, dass er unsere Produkte widerspiegelt, und die Integration in die Google-Abrechnungs-API.

  1. Wählen Sie Add-Ons aus.
  2. Wählen Sie dann das Google-Add-On aus.

PlayFab: Google-Add-On öffnen

  1. Geben Sie Ihre Paket-ID ein.
  2. Geben Sie den Google App-Lizenzschlüssel ein, den Sie im vorherigen Abschnitt erworben haben.
  3. Committen Sie Ihre Änderungen, indem Sie die Schaltfläche Google installieren auswählen.

Unser nächster Schritt ist unser 100 Diamonds Bundle in PlayFab:

  1. Erstellen Sie eine neue Economy Catalog (V2)-Währung.

  2. Bearbeiten Sie den Titel , und fügen Sie eine Beschreibung hinzu, Diamondsz. B. , Our in-game currency of choice..

  3. Fügen Sie eine benutzerfreundliche ID hinzu, um die Suche nach Ihrer Währung diamondszu erleichtern.

  4. Wählen Sie Speichern und veröffentlichen aus, um die Änderungen abzuschließen.

  5. Beobachten Sie Ihre Währung in der Liste Währungen .

  6. Erstellen Sie als Nächstes ein neues Economy Catalog (V2)-Paket.

  7. Bearbeiten Sie den Titel , und fügen Sie eine Beschreibung hinzu, 100 Diamonds Bundlez. B. , A pack of 100 diamonds to spend in-game..

    {
        "NEUTRAL": "100 Diamonds Bundle",
        "en-US": "100 Diamonds Bundle",
        "en-GB": "100 Diamonds Bundle",
        "de-DE": "100 Diamantenbüschel"
    }
    

    Notiz

    Beachten Sie, dass diese Daten nichts mit dem Titel und der Beschreibung des Play Market Item zu tun haben, da sie unabhängig sind.

  8. Sie können den Inhaltstyp verwenden, um Ihre Bündel zu organisieren, appstorebundlesz. B. . Inhaltstypen werden in ⚙️ > Titeleinstellungen > Economy (V2) verwaltet.

  9. Verfolgen Sie reale Preise nach, indem Sie den Anzeigeeigenschaften lokalisierte Preise hinzufügen.

    {
        "prices": [
            "en-us": 0.99,
            "en-gb": 0.85,
            "de-de": 0.45
        ]
    }
    
  10. Fügen Sie dem Bundle ein neues Element hinzu. Wählen Sie im Filter Währungen und dann die Währung aus, die Sie im vorherigen Satz erstellt haben. Legen Sie die Menge so fest, dass sie dem Betrag der Währung entspricht, die Sie in diesem Bündel verkaufen möchten.

  11. Fügen Sie eine neue Plattform für den Marketplace "GooglePlay" hinzu. Wenn Sie noch nicht über den GooglePlay Marketplace verfügen, können Sie ihn auf der Seite Mit den Wirtschaftseinstellungen erstellen. Legen Sie die Marketplace-ID so fest, dass sie mit der Google Play Console-Produkt-ID übereinstimmt, die Sie im vorherigen Abschnitt erstellt haben.

  12. Wählen Sie Speichern und veröffentlichen aus, um die Änderungen abzuschließen.

  13. Beobachten Sie Ihr Bündel in der Liste Bundles .

Als Nächstes können wir Spielkäufe festlegen, für die Spieler ihre Währung in einem PlayFab Store ausgeben können, um einen NPC-Anbieter im Spiel zu repräsentieren:

  1. Erstellen Sie ein neues Economy Catalog (V2)-Element.
  2. Bearbeiten Sie den Titel , und fügen Sie eine Beschreibung hinzu, z. B. "Goldenes Schwert", "Ein Schwert aus Gold.".
  3. Sie können lokalisierte Schlüsselwörter hinzufügen, damit Spieler Ihr Element im Store finden können. Fügen Sie Tags und einen Inhaltstyp hinzu, um Ihre Elemente für den späteren Abruf über die API zu organisieren. Verwenden Sie Anzeigeeigenschaften zum Speichern von Spieldaten wie Rüstungswerten, einem relativen Pfad zu Kunstobjekten oder anderen Daten, die Sie für Ihr Spiel speichern müssen.
  4. Fügen Sie einen neuen Preis hinzu, und wählen Sie die Währung aus, die Sie im vorherigen Schritt erstellt haben. Legen Sie den Betrag auf den Preis fest, den Sie standardmäßig festlegen möchten. Sie können den Preis später in jedem Store überschreiben, den Sie erstellen.
  5. Wählen Sie Speichern und veröffentlichen aus, um die Änderungen abzuschließen.
  6. Beobachten Sie Ihr Element in der Liste Elemente .
  7. Erstellen Sie abschließend einen neuen Economy Catalog (V2)-Store.
  8. Bearbeiten Sie den Titel , und fügen Sie eine Beschreibung hinzu, Villager Storez. B. , A humble store run by a humble villager..
  9. Geben Sie ihm eine benutzerfreundliche ID , um den Abruf zu vereinfachen, z. B villagerstore. .
  10. Fügen Sie dem Store das Element hinzu, das Sie im vorherigen Schritt erstellt haben. Sie können einem Geschäft mehrere Elemente hinzufügen und bei Bedarf alle Standardpreise außer Kraft setzen.
  11. Wählen Sie Speichern und veröffentlichen aus, um die Änderungen abzuschließen.
  12. Beobachten Sie Ihren Store in der Liste Stores .

Wir haben das Setup für Ihren PlayFab-Titel abgeschlossen.

Testen

Laden Sie die App zu Testzwecken mithilfe der Alpha/Beta-Version herunter.

  • Stellen Sie sicher, dass Sie ein Testkonto und ein echtes Android-Gerät verwenden.
  • Nachdem Sie die App gestartet haben, sollte IAP initialisiert und eine Schaltfläche angezeigt werden, die Ihr Element darstellt.
  • Wählen Sie diese Schaltfläche aus.

Test-App – Schaltfläche

Der IAP-Kauf wird initiiert. Befolgen Sie die Anweisungen von Google Play bis zu dem Punkt, an dem der Kauf erfolgreich ist.

Test-App – Google Play – Zahlung erfolgreich

Navigieren Sie schließlich im PlayFab Game Manager-Dashboard zu Ihrem Titel, und suchen Sie nach Neue Ereignisse.

Überprüfen Sie, ob der Kauf bereitgestellt, überprüft und an das PlayFab-Ökosystem weitergeleitet wurde.

Sie haben UnityIAP und die Android-Abrechnungs-API erfolgreich in Ihre PlayFab-Anwendung integriert!

Weitere Schritte

  1. Erstellen Sie eine Unity UI Toolkit-Schnittstelle für den Kauf, um die IMGUI-Demoanzeige zu ersetzen.
  2. Erstellen Sie eine benutzerdefinierte Unity-Protokollierung, um PlayFab-Fehler zu behandeln und dem Benutzer anzuzeigen.
  3. Fügen Sie ihrem Feld PlayFab-Elemente Bilder Symbolbilder hinzu, die auf der Unity-Benutzeroberfläche angezeigt werden sollen.