In-app purchases enable you to offer additional content and features to users. You can use this as a means to monetize a free application or to provide additional paid content for your application. This page provides iOS-specific information, but you must be familiar with the general in-app purchases information described in the Using In-App Purchases documentation.
Apple App Store Details
The information below is vague in some cases. Please check official App Store and StoreKit documentation for additional details
Querying product information
In-app products are identified by the string based product ID you configure for each product on your application in AppStoreConnect.
StoreKit handles initiating a purchase for an in-app product or subscription the same way. Before you can initiate a purchase for a given product, you need to query its updated information at some point since some internal objects from this query are used to trigger the purchase flow. You can query for product information using the Read In App Purchase Information2 blueprint node or IOnlineStore::QueryOffersById in C++.
If the methods described in this document don't function due to changes in the API, you can check the App Store Server APIs to find the proper API for server validation, you can check subscriptions state server-side, and/or you can use the App Store Server Notifications.
Validation
You should validate your receipts to avoid fraud. Check the official documentation about receipt validation for more information.
Take into account that when using local validation, there is no way to check for subscription state and expiration times. You can gather validation information using the Get Transaction Info endpoint, and you can gather subscription state and expiration information using the Get All Subscription Statuses endpoint.
You should finalize all transactions locally on device once validated and the product is granted. You can accomplished this by calling IOnlinePurchase::FinalizePurchase or use the Finalize In-App Purchase Transaction blueprint node on the completed receipt. Not finalizing transactions may lead to bad device performance
Product Types
App Store differentiates between consumable in-app products, non-consumable in-app products, and subscriptions. Transactions for all of them are handled the same way and they need to be finalized when completed. Autorenewed subscriptions generate a new receipt each time they are renewed
Receipts and Receipt Persistence
Only receipts for non-completed transactions can be gathered at any point. Once a transaction is finished, by calling IOnlinePurchase::FinalizePurchase or using the Finalize In-App Purchase Transaction Blueprint node, it won’t generate a receipt on following queries for receipts. For that reason, you must always keep a record of the user-granted products.
When a subscription is renewed it generates a new receipt. To detect those events while the game is running you can register to the OnUnexpectedPurchaseReceipt delegate in IOnlinePurchase. Subsequent calls to query receipts will contain the new receipt until it is handled and finalized.
Successful deferred and interrupted purchases will also be notified through OnUnexpectedPurchaseReceipt. Those types of transactions initially generate a failed receipt with a deferred or canceled state, and can generate a new successful transaction when they succeed.
See the official StoreKit documentation for more information.
ValidationInfo stored in the receipt for each line item contains a FString containing the Base64 encoded AppReceipt that should be used for validation.
Subscription Expiration Management
Subscription status and expiration times are not available on devices. After the receipt is finalized there is no information regarding a possible active subscription. You can check the subscription state and expiration times server-side using the Get All Subscription Statuses endpoint.
StoreKit does not notify devices in any way for subscription expiration, cancellation, or refund. Apple offers App Store Server Notifications to detect those events server side.
Testing In-app Purchases
You can test in-app purchases using StoreKit testing in Xcode or a sandbox environment. StoreKit testing in Xcode does not need in-app products to be configured in the AppStore connect application, but if they are already set up it can import the configuration to use it in a local environment. The application must be launched from Xcode and there are some tools to control transaction lifetime.
A sandbox environment uses real product information and you can use it to test server to server transactions. To use sandbox environments you need to setup a Sandbox Apple ID and use a development signed app properly configured in App Store connect.
Restore Transactions
At any moment you can restore transactions using the Restore Owned In-App Products blueprint node or invoking IOnlinePurchase::QueryReceipts with the
bRestore
argument set to true. In that case a restore transactions operation is triggered, caching a receipt for each successful non-consumable or subscription transaction made in the past including subscription renewals. This can be useful to recover the full list of transactions when using the same App Store credentials in a new device.
Receipts marked as Restored do not need to be finalized.
Configuration
Set up your in-app purchase in iTunes Connect:Google Play requires the id to be all lowercase, and it's best to have the ID for iOS and Android match as much as possible for ease of Blueprint setup.
Make a note of the ID you use, as well as if the item is consumable or non-consumable or subscription
Product IDs for subscriptions can be used directly on iOS implementation while GooglePlay implementation has some specific details
If you have a code project and have not already set up your project to use online subsystems, add the following block to your project's
Build.csfile:C#if (Target.Platform == UnrealTargetPlatform.IOS) { PrivateDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "OnlineSubsystem" }); DynamicallyLoadedModuleNames.Add("OnlineSubsystemIOS"); }Edit
[ProjectName]/Config/IOS/IOSEngine.ini:Config[OnlineSubsystem] DefaultPlatformService=IOS [OnlineSubsystemIOS.Store] bSupportsInAppPurchasing=TrueBlueprint nodes need the
OnlineIdentityto be properly enabled. To use GameCenter edit[ProjectName]/Config/DefaultEngine.ini:Config[/Script/IOSRuntimeSettings.IOSRuntimeSettings] bEnableGameCenterSupport=TrueYour provisioning profile AppID must match your App Store application bundle ID and must have the In-App Purchases entitlement. In-app purchases will not work using a wildcard provisioning profile.
If you are having difficulty configuring your in-app purchases, refer to the Troubleshoot section of the main in app purchases documentation.