PlayFab integration V2
This guide explains how to configure PlayFab services for UniPay, specifically cloud save and receipt validation. Additionally, methods are being explained for keeping local user inventory in sync with PlayFab.
This guide integrates PlayFab Economy V2, which is not backwards compatible with V1. V2 required several major changes in UniPay. Because of that, you cannot just import V2 in an older version of UniPay.
Compared to Economy V1 (legacy), Economy V2 changed the following things:
- PayPal was removed as a payment option. If you would like to continue using PayPal payments, please consider using the native PayPal option in UniPay, or in combination with IAPGUARD for securing and server-validating PayPal payments
- The
Validation Only
option was removed that allowed creating an anonymous user only when making a purchase, instead of requiring the user already being logged in with PlayFab before that - Subscriptions that charge real money are still not supported, however now virtual subscriptions are now supported (e.g. in exchange for spending virtual currency that was previously bought with real money)
- Products offered on an App Store need to be of type Bundle and need to include another product of type Item, even if this is a single product purchase like 'no Ads'. PlayFab is working to resolve this inconvenience
- There is no button in the dashboard to mass-upload products using a JSON file anymore, instead this needs to be done via their backend API
Please see the first chapter below for limitations and restrictions that apply when using PlayFab.
Prerequisites
What else can you do to avoid cheating? To put it simple – don’t do everything on the client, but verify each user action on external servers.
The PlayFab integration is a great starting point for that by keeping everything in sync with cloud save and doing critical transactions (like purchase validation) on their servers only.
If you're using PlayFab, this means that no data is saved on the device. Since that requires an online connection throughout the whole play session, it is the most secure solution by far, although better suited for online games and devices supporting a reliable internet connection (desktop pc's via ethernet or mobile devices using wi-fi). Please keep that in mind when making use of this. Basically you have two options with online-only games when there is no internet connection available:
- logging into PlayFab is not possible - it would be best to disallow entering the game at this state
- or, only permit offline mode without earning & spending (such as a training mode with local scores)
Also note that with the various different native plugins supporting mobile login via PlayFab (i.e. Play Game Services by Google), I am not able to write a separate integration guide for each of them. The default login method is via registered email addresses, or automatic login on platform where a user is already authenticated (like Steam), which are the most common techniques for desktop applications. Please refer to the PlayFab documentation for implementing other login methods.
With that out of the way, let's continue by creating your PlayFab developer account.
Creating a PlayFab account
Creating a PlayFab developer account is easy and free. Sign up here: PlayFab Website
Once you're logged in, you will be greeted by a somewhat empty screen, where you can define your company and game name. In PlayFab, when speaking about games, they are usually referred to as Titles. Each game must have its own title (or dashboard), which is used to independently track users, purchases, cloud scripts and all the other stuff PlayFab provides.
After you've created your first title, it should be shown under your games page along with its generated title identifier.
Creating your store catalog
Now with the title created in PlayFab, we need a way to transfer all the different in-app purchase products from Unity to PlayFab. Unfortunately with Economy V2, PlayFab removed its dashboard button to upload a JSON configuration directly from UniPay. At the moment, you will have to create your products manually, or use their backend API.
Navigate to the Economy > Catalogs (V2)
section. If your game uses a virtual currency, start with that and create your other products later. There are a few specific configurations that need to be done for each product type, which will be explained below. Since fullscreen images would clutter this guide too much, each of the catalog screenshots are linked rather than shown here: open them to see them in their original size.
Virtual Currency
For your products to be purchased with virtual currency, you have to define a currency in PlayFab first. This is similar to the Project Settings > UniPay In-App Purchasing > Currencies
section in Unity. The Friendly ID
in PlayFab should be set to your currency identifier in UniPay. In this case, coins.
Products for Real Money
Products for real money need to be defined in the Bundles tab on PlayFab, since only this type of products support App Store identifier mapping. As an example, we are going to add a currency bundle and a no ads product.
In the currency bundle, there are 3 important settings:
- Friendly ID: this needs match your product identifier entered in
Project Settings > UniPay In-App Purchasing > Products
- ITEMS: here you add how much currency should be granted to the user, matching what is defined in UniPay
- MARKETPLACE MAPPING: these are your App Store product identifiers. Add them, even if they are the same as the Friendly ID
Now for the no ads bundle, there is a workaround we have to take due to PlayFab requiring each bundle granting an item. So the no ads bundle needs to grant a separate no ads product, basically. And if the bundle grants an item, we have to create the item before the bundle. Navigate to the Items tab and create the no ads product. As always, the Friendly ID
needs to match your product identifier in UniPay.
Note that all other product categories are left empty and there is no marketplace mapping that we could populate. So, navigate to the Bundles tab and create your no ads bundle. The most important part is the Friendly ID
: it is kept empty! This is because we do not want this bundle to be a separate product, but only have it grant one no ads item when purchased via the marketplace mapping identifier.
Products for Virtual Currency
After you've created a virtual currency, creating virtual products is very easy. Just make sure that the currency price and item grants match what is defined in UniPay, otherwise PlayFab will report that it cannot find that product constellation.
Subscriptions
PlayFab only supports virtual subscriptions, in exchange for virtual currency, not real money. And since a subscription needs to grant an item too, like a bundle, we have to define that item first, then the subscription. Here comes the special thing: the virtual subscription and the item it grants when active are actually two distinct products. So while the player purchases the subscription, you have to check the item to determine whether they currently own the subscription. However while that item needs to be defined in UniPay as well, it should not be displayed in a shop anywhere (only the subscription product).
Importing the PlayFab Unity SDK
First of all, download the PlayFab Unity SDK from the official Microsoft Landing page. The Editor Extensions package is not necessary.
After downloading, import the PlayFab SDK into your Unity project. For establishing the relation between the SDK and your title on PlayFab's servers, you will have to enter its title ID in the SDK settings. Locate the PlayFabSharedSettings
file in your project as shown below, then enter the title ID that has been generated for you in PlayFab's dashboard (see first screenshot in this guide). The Developer Secret Key
is located at Title Settings > Secret Keys > Default Key
.
Next, open Project Settings > UniPay In-App Purchasing
and import the PlayFab (External SDK) package by pressing the corresponding button.
Marketplace Setup
Your in-app purchase receipts will get sent to PlayFab for validation and approval, so only verified transactions are granted the correct amount of products or currency. For this, PlayFab needs some of your App Store secret keys to validate their authenticity for you. Head over to the Add-ons section, where you'll have to activate one or many of the platforms you would like to use.
For a list of platforms supported by Economy V2's receipt validation, please see this page. UniPay has been tested with Google Play, Apple App Store and Steam.
- Google App Package ID: Google Play Developer Console, App > Dashboard, below your app name
- Google App License Key: Google Play Developer Console, App > Monetisation setup > License, Base64-encoded RSA public key
- Service account key: Key ID after following the official documentation
- iOS App Bundle ID: App Store Connect, Apps > App Information, Bundle ID
- iOS App Shared Secret: App Store Connect, Apps > App Information, App-Specific Shared Secret
- Steam Application ID: Steamworks dashboard, the number after your app name
- Steam Web API Key: Steamworks dashboard, Users & Permissions > Manage Groups > Everyone (WebAPI), create key on right side
Logging in the user in Unity
With PlayFab integrated, our DBManager will not save any data locally on the device. This is also reflected by the DBManager's Storage Target = Memory mode, which is activated automatically for this, and means that players need to download their own data from the PlayFab servers each time your app is launched. This complies with a high-security app environment, as there is no local data or any save games regarding in-app purchases that could be tampered with.
This also means that players need a way to get their purchase data, and only their data, by logging in to PlayFab servers. UniPay provides a very basic example login scene that you can learn from, use or customize.
The login example scene offers registration and login via email & password. On platforms where players are already authenticated when launching the game, like on Steam, you would want to skip any manual authentication flow. This is why when running on Steam, the example login scene authenticates the user automatically with PlayFab using their Steam session token so they do not need to enter anything.
If you are creating your own login scene, note that the important configuration in this scene is having the PlayFabManager
prefab present. Additionally, it needs to contain the IAPManager
prefab with the Auto Initialize toggle disabled. After logging in, the PlayFabManager
will then make a call to initialize the IAPManager
automatically.
Feature Overview
Now that we've implemented PlayFab, in this chapter we're going to take a look at everything the integration does for us.
Receipt Validation
Receipt validation happens whenever users purchase any product in the shop. Both real money and virtual purchases, as well as the result (e.g. inventory and virtual currency balances) are synchronized with PlayFab - nothing exists locally on the device.
On the PlayFab dashboard, this allows you to go into great detail about monetization, track purchase amounts across platforms and even inspecting single users on what they bought in your game. For a more aggregated summary on what your users are buying in your game, along with how often they do it, you can set up a query in the Analytics section for a bar chart analysis.
Cloud Save
Since all transaction related actions are acknowledged by the PlayFab servers, they are registered on the user's PlayFab account. In the user's perspective this means that, combined with a login system described in the last chapter, users can switch devices, uninstall & reinstall the app, still retrieve their data and continue playing without any loss of data (more on synchronization in the next chapter). In an administrator's perspective (yours), having everything flowing over PlayFab's servers allows you to control virtual currency economies, modifying currency balances or inventory of hacking users, banning their accounts, giving out product keys as promotions or just looking at what your players are doing.
Introducing Sales
Temporary sales for products could be a way to make specific items or purchases in general more appealing - the big benefit here is that you can introduce IAP sales without updating your app. If you know you would like to run sales in the future, just check the Fetch checkbox for both real money and virtual products in the IAP Project Settings.
What this does is not only fetching and displaying localized prices of real money products from the App Stores, but also downloading current virtual product prices from your title's economy catalog in PlayFab. So in order to run a sale for a specific virtual product, just open it in PlayFab's catalog and edit its price. The new price will be effective when users relaunch your app.
In-game Synchronization
Many game actions are automatically synchronized with PlayFab at the time they happen in your app. This applies to everything that requires an interaction with PlayFab's servers, basically. For example, these are the actions which get auto-synced:
- user purchases real money product (product is assigned to inventory)
- user purchases virtual currency (currency amount is updated)
- user purchases virtual product (currency amount is updated, product is assigned to inventory)
- user purchases virtual product with usage count (currency amount is updated, product usage is updated in inventory)
- user selects/unselects product (selection value is updated in Player Data (Title))
As you can see, most of the shop synchronization is handled for you already. What UniPay cannot know though, is what you are doing with these items in your game. This means that everything dependent on your own game-specific use case also has to be handled and synchronized by you. The PlayFabManager
(link to Scripting Reference) provides several methods, described below, for syncing your data back to PlayFab. Each method is explained with a sample use case and the point when it's best to call it.
SetPurchase
Use case: the player finds a new weapon in-game and you would like to give it to them for free. Note that this method is best suited for non-consumable products, as for consumable products you should call the other methods directly to minimize web requests. When: at any point during the game.
Use case: the player previously bought some power-ups with usage count. They then activate them in-game, which you are tracking via DBManager.ConsumePurchase (to substract the power-up usage count). You then want to synchronize the remaining usage count with PlayFab by calling this method. When: only at the end of a round or level, to minimize web requests.
SetPlayerData
Use case: the player reached a certain level or you want to save a progress value for each level (1, 2, 3 stars). You have tracked this via DBManager.Set/AddPlayerData. You then want to synchronize these custom values with PlayFab by calling this method. When: only at the end of a round or level, to minimize web requests.
SetCurrency
Use case: the player collects coins during the game, which you are tracking via DBManager.IncreaseFunds. You then want to synchronize the current currency amount with PlayFab by calling this method. When: only at the end of a round or level, to minimize web requests.
SetSelected
Use case: you have an in-game inventory display where players can select and deselect e.g. weapons. Note that the selection in the shop scene is synced for you already. When: at any point during the game.
Adding Cloud Scripts
Some of the methods listed in the previous chapters are calling custom code on PlayFab's servers, referred to as cloud scripts. Each title on PlayFab has its own server code section hosted on Microsoft Azure using Functions, where you can execute actions which should not be in the hands of users (to prevent hacking), such as granting products or virtual currency, or just to add another security measure by checking the values it receives for feasibility. You have to setup some Azure functions with the code mentioned below, so that UniPay is able to properly call them for your title. Note that the Microsoft Azure subscription includes a generous free tier for calling and executing functions.
In the (Azure Portal), create a new Functions application with an unique URL. When created, it should look similar to this:
Under the Configuration section, add a PLAYFAB_DEV_SECRET_KEY
variable with the value found in your PlayFab's title, under Title settings > Secret Keys > Secret Key
. If there is no Default Key yet, create one first. This key serves as an authorization mechanism for allowing your Azure functions to call the PlayFab API.
Next, set up a Visual Studio or Visual Studio Code project for Functions deployment. For more information on how to create a project for this, please see (the official quickstart documentation). In this project, add a PlayFabFunctions.cs
file and copy-paste the code included in UniPay, located at UniPay > Extensions > PlayFab > Scripts > CloudScript.txt
. Note that there are a few NuGet packages required as described in the quickstart guide, namely the PlayFabAllSDK and PlayFabCloudScriptPlugin packages. Additionally, add a CS2AFHelperClasses.cs
file with the code found (on this respository).
With the function code deployed to Azure, you should see a setItems and addItems function in your application dashboard. For each function, open it and copy the function URL.
In PlayFab, register these functions with a HTTP trigger and insert the URL copied from Azure before.
Congratulations, you've made it to the end!