diff --git a/analytics/src/FirebaseAnalytics.cs b/analytics/src/FirebaseAnalytics.cs index 200b3513..1449b6b2 100644 --- a/analytics/src/FirebaseAnalytics.cs +++ b/analytics/src/FirebaseAnalytics.cs @@ -354,6 +354,25 @@ public static void SetUserId(string userId) { public static void SetUserProperty(string name, string property) { FirebaseAnalyticsInternal.SetUserProperty(name, property); } + + /// + /// Logs an in-app purchase transaction specifically for Apple's StoreKit 2. + /// + /// + /// This method is intended for Unity developers on iOS who process transactions + /// via In-app purchases and need whish to log those purchases through Google Analytics. + /// The provided ID must map 1:1 with the native Apple `Transaction.id`. + /// If a matching transaction is not found in the apple devices purchase history then + /// nothing will be logged to analytics. + /// + /// + /// The native Apple transaction identifier (e.g., + /// extracted from Unity IAP's purchasedProduct.transactionID). + /// A Task that completes when the native StoreKit 2 transaction + /// is successfully located and logged. + public static System.Threading.Tasks.Task LogAppleTransactionAsync(string transactionId) { + return FirebaseAnalyticsInternal.LogAppleTransactionAsync(transactionId); + } } } diff --git a/analytics/src/swig/analytics.i b/analytics/src/swig/analytics.i index 95d48b0b..cd42a3aa 100644 --- a/analytics/src/swig/analytics.i +++ b/analytics/src/swig/analytics.i @@ -136,6 +136,7 @@ void SetConsentWithInts(const std::map& settings) { // GetSessionId returns Future in SWIG. %include "app/src/swig/future.i" %SWIG_FUTURE(Future_LongLong, long, internal, long long, FirebaseException) +%SWIG_FUTURE(FutureVoid, void, internal, void, FirebaseException) // Ignore the Consent enums, so we can use commented ones in C# %ignore firebase::analytics::ConsentType; diff --git a/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs b/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs index 08564b79..06367b9d 100644 --- a/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs +++ b/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs @@ -192,6 +192,21 @@ public Task DisplaySessionId() { }).Unwrap(); } + // Log a dummy Apple transaction + public Task DisplayLogAppleTransaction() { + return FirebaseAnalytics.LogAppleTransactionAsync("dummy_transaction_id").ContinueWithOnMainThread(task => { + if (task.IsCanceled) { + DebugLog("LogAppleTransaction was canceled."); + } else if (task.IsFaulted) { + DebugLog(String.Format("Encountered an error logging Apple transaction: {0}", + task.Exception.ToString())); + } else if (task.IsCompleted) { + DebugLog("LogAppleTransaction completed successfully."); + } + return task; + }).Unwrap(); + } + // Output text to the debug log text field, as well as the console. public void DebugLog(string s) { print(s); @@ -257,6 +272,9 @@ void GUIDisplayControls() { if (GUILayout.Button("Test SetConsent")) { AnalyticsSetConsent(); } + if (GUILayout.Button("Test LogAppleTransaction")) { + DisplayLogAppleTransaction(); + } GUILayout.EndVertical(); GUILayout.EndScrollView(); } diff --git a/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs b/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs index c299f4f6..b0b5aad6 100644 --- a/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs +++ b/analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs @@ -43,6 +43,7 @@ public override void Start() { // Temporarily disabled until this test is deflaked. b/143603151 //TestCheckAndFixDependenciesInvalidOperation, TestCheckAndFixDependenciesDoubleCall, + TestLogAppleTransaction, }; testRunner = AutomatedTestRunner.CreateTestRunner( testsToRun: tests, @@ -254,5 +255,32 @@ Task TestResetAnalyticsData() { }); return tcs.Task; } + + Task TestLogAppleTransaction() { + // On iOS, this should fail with a dummy ID if no simulated transaction is set up. + // On other platforms, it should be a no-op and succeed. + if (Application.platform == RuntimePlatform.IPhonePlayer) { + return base.DisplayLogAppleTransaction() + .ContinueWithOnMainThread(t => { + if (t.IsFaulted) { + DebugLog("LogAppleTransaction failed as expected with dummy ID."); + DebugLog("Exception: " + t.Exception); + return true; + } else { + DebugLog("LogAppleTransaction unexpectedly succeeded with dummy ID."); + return true; + } + }); + } else { + return base.DisplayLogAppleTransaction() + .ContinueWithOnMainThread(t => { + if (t.IsFaulted) { + throw t.Exception; + } + DebugLog("LogAppleTransaction completed successfully (no-op) on this platform."); + return true; + }); + } + } } } diff --git a/analytics/testapp/readme.md b/analytics/testapp/readme.md index a5d02b7f..77af589f 100644 --- a/analytics/testapp/readme.md +++ b/analytics/testapp/readme.md @@ -187,6 +187,35 @@ Press some of the buttons to log some events to your Firebase project. After around 5 hours, data should be visible under the *Analytics* tab in the [Firebase Console](https://firebase.google.com/console/)). +## iOS Testing LogAppleTransaction + +To test the log apple transaction function, you should use the exported Xcode project and Xcode's simulated transactions. +The manual test will involve running the testapp and verifying that it logs a transaction to the console. + + - Step 1: Set up the Local Xcode Environment + - After building the sample for iOS and opening the exported project in Xcode: + - In Xcode, go to File > New > File from Template and create a StoreKit Configuration File (.storekit). + - Give the configuration any name. + - Target the `Unity-iPhone` scheme (or the relevant target for your exported app). + - Add at least one dummy product to this file. + - Do this by selecting the file in Xcode and clicking the + button in the bottom left corner. + - Choose a Consumable in app purchase product. + - Give it a Reference name of your choice (e.g. "ReferenceAppleIapProduct"). + - Give it a Product ID of your choice (e.g. "com.example.nonconsumable"). + - Make the app use the store kit file. In the top bar go to Product > Scheme > Edit Scheme... + - In the left hand menu select Run + - Select the Options tab on the top + - Set the StoreKit Configuration dropdown to your new .storekit file. + - Step 2: Validate logging transactions + - You can create a simulated transaction for testing. + - To create a simulated transaction ID: + - Go to Debug > StoreKit > Manage Transactions. + - Click the + button in the bottom left corner. + - Select the Consumable in app purchase product. + - Use the generated transaction ID in your code or test case. + - When you call `FirebaseAnalytics.LogAppleTransactionAsync(transactionId)` with the simulated transaction ID: + - It should log the transaction to the console. Both the Xcode console and firebase console should show a log for an in app purchase. + ## Troubleshooting diff --git a/docs/readme.md b/docs/readme.md index df422861..37584167 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -109,6 +109,12 @@ Support Release Notes ------------- +### Upcoming +- Changes + - Analytics: Add support for Apple's Store kit 2 transactions. Add new `LogAppleTransactionAsync` method + that takes in the App Store transaction string and logs the transaction. + + ### 13.11.0 - Changes - General: Update to Firebase C++ SDK version 13.7.0.