From e05358d1cd264f076a9e97ad200693423a840fd3 Mon Sep 17 00:00:00 2001 From: uerceg Date: Mon, 8 Jul 2024 15:54:45 +0200 Subject: [PATCH] feat: add verify and track feature --- Assets/Adjust/Native/iOS/AdjustUnity.h | 1 + Assets/Adjust/Native/iOS/AdjustUnity.mm | 93 +++++++++++++++++++++++++ Assets/Adjust/Scripts/Adjust.cs | 44 +++++++++--- Assets/Adjust/Scripts/AdjustAndroid.cs | 64 +++++++++++++++++ Assets/Adjust/Scripts/AdjustiOS.cs | 57 ++++++++++++++- 5 files changed, 250 insertions(+), 9 deletions(-) diff --git a/Assets/Adjust/Native/iOS/AdjustUnity.h b/Assets/Adjust/Native/iOS/AdjustUnity.h index 569589dc..c1c70408 100644 --- a/Assets/Adjust/Native/iOS/AdjustUnity.h +++ b/Assets/Adjust/Native/iOS/AdjustUnity.h @@ -21,6 +21,7 @@ typedef void (*AdjustDelegateLastDeeplinkGetter)(const char* lastDeeplink); typedef void (*AdjustDelegateSdkVersionGetter)(const char* sdkVersion); typedef void (*AdjustDelegateAttCallback)(int status); typedef void (*AdjustDelegatePurchaseVerificationCallback)(const char* verificationResult); +typedef void (*AdjustDelegateVerifyAndTrackCallback)(const char* verificationResult); typedef void (*AdjustDelegateResolvedDeeplinkCallback)(const char* deeplink); typedef void (*AdjustDelegateSkanErrorCallback)(const char* error); diff --git a/Assets/Adjust/Native/iOS/AdjustUnity.mm b/Assets/Adjust/Native/iOS/AdjustUnity.mm index 39bd0432..22bdeb15 100644 --- a/Assets/Adjust/Native/iOS/AdjustUnity.mm +++ b/Assets/Adjust/Native/iOS/AdjustUnity.mm @@ -764,6 +764,99 @@ void _AdjustProcessAndResolveDeeplink(const char* deeplink, AdjustDelegateResolv } } + void _AdjustVerifyAndTrackAppStorePurchase( + const char* eventToken, + double revenue, + const char* currency, + const char* receipt, + const char* productId, + const char* transactionId, + const char* callbackId, + const char* deduplicationId, + const char* jsonCallbackParameters, + const char* jsonPartnerParameters, + AdjustDelegateVerifyAndTrackCallback callback) { + NSString *strEventToken = isStringValid(eventToken) == true ? [NSString stringWithUTF8String:eventToken] : nil; + ADJEvent *event = [[ADJEvent alloc] initWithEventToken:strEventToken]; + + // revenue and currency + if (revenue != -1 && currency != NULL) { + NSString *stringCurrency = [NSString stringWithUTF8String:currency]; + [event setRevenue:revenue currency:stringCurrency]; + } + + // callback parameters + NSArray *arrayCallbackParameters = convertArrayParameters(jsonCallbackParameters); + if (arrayCallbackParameters != nil) { + NSUInteger count = [arrayCallbackParameters count]; + for (int i = 0; i < count;) { + NSString *key = arrayCallbackParameters[i++]; + NSString *value = arrayCallbackParameters[i++]; + [event addCallbackParameter:key value:value]; + } + } + + // partner parameters + NSArray *arrayPartnerParameters = convertArrayParameters(jsonPartnerParameters); + if (arrayPartnerParameters != nil) { + NSUInteger count = [arrayPartnerParameters count]; + for (int i = 0; i < count;) { + NSString *key = arrayPartnerParameters[i++]; + NSString *value = arrayPartnerParameters[i++]; + [event addPartnerParameter:key value:value]; + } + } + + // transaction ID + if (transactionId != NULL) { + NSString *strTransactionId = [NSString stringWithUTF8String:transactionId]; + [event setTransactionId:strTransactionId]; + } + + // product ID + if (productId != NULL) { + NSString *strProductId = [NSString stringWithUTF8String:productId]; + [event setProductId:strProductId]; + } + + // receipt (base64 encoded string) + if (receipt != NULL) { + NSString *strReceipt = [NSString stringWithUTF8String:receipt]; + NSData *dataReceipt = [[NSData alloc] initWithBase64EncodedString:strReceipt options:0]; + [event setReceipt:dataReceipt]; + } + + // callback ID + if (callbackId != NULL) { + NSString *strCallbackId = [NSString stringWithUTF8String:callbackId]; + [event setCallbackId:strCallbackId]; + } + + // deduplication ID + if (deduplicationId != NULL) { + NSString *strDeduplicationId = [NSString stringWithUTF8String:deduplicationId]; + [event setDeduplicationId:strDeduplicationId]; + } + + [Adjust verifyAndTrackAppStorePurchase:event + withCompletionHandler:^(ADJPurchaseVerificationResult * _Nonnull verificationResult) { + // TODO: nil checks + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + addValueOrEmpty(dictionary, @"verificationStatus", verificationResult.verificationStatus); + addValueOrEmpty(dictionary, @"code", [NSString stringWithFormat:@"%d", verificationResult.code]); + addValueOrEmpty(dictionary, @"message", verificationResult.message); + + NSData *dataVerificationInfo = [NSJSONSerialization dataWithJSONObject:dictionary + options:0 + error:nil]; + NSString *strVerificationInfo = [[NSString alloc] initWithBytes:[dataVerificationInfo bytes] + length:[dataVerificationInfo length] + encoding:NSUTF8StringEncoding]; + const char* verificationInfoCString = [strVerificationInfo UTF8String]; + callback(verificationInfoCString); + }]; + } + void _AdjustSetTestOptions(const char* overwriteUrl, const char* extraPath, long timerIntervalInMilliseconds, diff --git a/Assets/Adjust/Scripts/Adjust.cs b/Assets/Adjust/Scripts/Adjust.cs index bab0d552..9edcb904 100644 --- a/Assets/Adjust/Scripts/Adjust.cs +++ b/Assets/Adjust/Scripts/Adjust.cs @@ -685,14 +685,6 @@ public static void VerifyPlayStorePurchase( #if UNITY_IOS Debug.Log("[Adjust]: Play Store purchase verification is only supported for Android platform."); #elif UNITY_ANDROID - if (purchase == null || - purchase.ProductId == null || - purchase.PurchaseToken == null) - { - Debug.Log("[Adjust]: Invalid Play Store purchase parameters."); - return; - } - AdjustAndroid.VerifyPlayStorePurchase(purchase, verificationResultCallback); #else Debug.Log(errorMsgPlatform); @@ -715,6 +707,42 @@ public static void ProcessAndResolveDeeplink(string deeplink, Action cal #endif } + public static void VerifyAndTrackAppStorePurchase( + AdjustEvent adjustEvent, + Action callback) + { + if (IsEditor()) + { + return; + } + +#if UNITY_IOS + AdjustiOS.VerifyAndTrackAppStorePurchase(adjustEvent, callback); +#elif UNITY_ANDROID + Debug.Log("[Adjust]: App Store purchase verification is only supported for iOS platform."); +#else + Debug.Log(errorMsgPlatform); +#endif + } + + public static void VerifyAndTrackPlayStorePurchase( + AdjustEvent adjustEvent, + Action verificationResultCallback) + { + if (IsEditor()) + { + return; + } + +#if UNITY_IOS + Debug.Log("[Adjust]: Play Store purchase verification is only supported for Android platform."); +#elif UNITY_ANDROID + AdjustAndroid.VerifyAndTrackPlayStorePurchase(adjustEvent, verificationResultCallback); +#else + Debug.Log(errorMsgPlatform); +#endif + } + private static bool IsEditor() { #if UNITY_EDITOR diff --git a/Assets/Adjust/Scripts/AdjustAndroid.cs b/Assets/Adjust/Scripts/AdjustAndroid.cs index a28d3480..1066a53e 100644 --- a/Assets/Adjust/Scripts/AdjustAndroid.cs +++ b/Assets/Adjust/Scripts/AdjustAndroid.cs @@ -19,6 +19,7 @@ public class AdjustAndroid private static SessionTrackingFailedListener onSessionTrackingFailedListener; private static SessionTrackingSucceededListener onSessionTrackingSucceededListener; private static VerificationResultListener onVerificationResultListener; + private static VerificationResultListener onVerifyAndTrackListener; private static DeeplinkResolutionListener onDeeplinkResolvedListener; public static void InitSdk(AdjustConfig adjustConfig) @@ -578,6 +579,69 @@ public static void ProcessAndResolveDeeplink(string url, Action resolved ajcAdjust.CallStatic("processAndResolveDeeplink", ajoUri, ajoCurrentActivity, onDeeplinkResolvedListener); } + public static void VerifyAndTrackPlayStorePurchase( + AdjustEvent adjustEvent, + Action verificationInfoCallback) + { + AndroidJavaObject ajoAdjustEvent = new AndroidJavaObject("com.adjust.sdk.AdjustEvent", adjustEvent.EventToken); + + // check if user has set revenue for the event + if (adjustEvent.Revenue != null) + { + ajoAdjustEvent.Call("setRevenue", (double)adjustEvent.Revenue, adjustEvent.Currency); + } + + // check if user has added any callback parameters to the event + if (adjustEvent.CallbackParameters != null) + { + for (int i = 0; i < adjustEvent.CallbackParameters.Count; i += 2) + { + string key = adjustEvent.CallbackParameters[i]; + string value = adjustEvent.CallbackParameters[i + 1]; + ajoAdjustEvent.Call("addCallbackParameter", key, value); + } + } + + // check if user has added any partner parameters to the event + if (adjustEvent.PartnerParameters != null) + { + for (int i = 0; i < adjustEvent.PartnerParameters.Count; i += 2) + { + string key = adjustEvent.PartnerParameters[i]; + string value = adjustEvent.PartnerParameters[i + 1]; + ajoAdjustEvent.Call("addPartnerParameter", key, value); + } + } + + // check if user has set deduplication ID for the event + if (adjustEvent.DeduplicationId != null) + { + ajoAdjustEvent.Call("setDeduplicationId", adjustEvent.DeduplicationId); + } + + // check if user has added callback ID to the event + if (adjustEvent.CallbackId != null) + { + ajoAdjustEvent.Call("setCallbackId", adjustEvent.CallbackId); + } + + // check if user has added product ID to the event + if (adjustEvent.ProductId != null) + { + ajoAdjustEvent.Call("setProductId", adjustEvent.ProductId); + } + + // check if user has added purchase token to the event + if (adjustEvent.PurchaseToken != null) + { + ajoAdjustEvent.Call("setPurchaseToken", adjustEvent.PurchaseToken); + } + + onVerifyAndTrackListener = new VerificationResultListener(verificationInfoCallback); + + ajcAdjust.CallStatic("verifyAndTrackPlayStorePurchase", ajoAdjustEvent, onVerifyAndTrackListener); + } + // used for testing only public static void SetTestOptions(Dictionary testOptions) { diff --git a/Assets/Adjust/Scripts/AdjustiOS.cs b/Assets/Adjust/Scripts/AdjustiOS.cs index 716f607c..efe19f3a 100644 --- a/Assets/Adjust/Scripts/AdjustiOS.cs +++ b/Assets/Adjust/Scripts/AdjustiOS.cs @@ -20,6 +20,7 @@ public class AdjustiOS private static List> appSdkVersionGetterCallbacks; private static List> appAttCallbacks; private static Action appPurchaseVerificationCallback; + private static Action appVerifyAndTrackCallback; private static Action appResolvedDeeplinkCallback; private static Action appSkanErrorCallback; @@ -238,6 +239,21 @@ private static extern void _AdjustVerifyAppStorePurchase( string receipt, AdjustDelegatePurchaseVerificationCallback callback); + private delegate void AdjustDelegateVerifyAndTrackCallback(string verificationResult); + [DllImport("__Internal")] + private static extern void _AdjustVerifyAndTrackAppStorePurchase( + string eventToken, + double revenue, + string currency, + string receipt, + string productId, + string transactionId, + string callbackId, + string deduplicationId, + string jsonCallbackParameters, + string jsonPartnerParameters, + AdjustDelegatePurchaseVerificationCallback callback); + // public API public AdjustiOS() {} @@ -325,7 +341,7 @@ public static void TrackEvent(AdjustEvent adjustEvent) deduplicationId, stringJsonCallbackParameters, stringJsonPartnerParameters); - } + } public static void Enable() { @@ -587,6 +603,36 @@ public static void ProcessAndResolveDeeplink(string deeplink, Action cal _AdjustProcessAndResolveDeeplink(deeplink, ResolvedDeeplinkCallbackMonoPInvoke); } + public static void VerifyAndTrackAppStorePurchase( + AdjustEvent adjustEvent, + Action callback) + { + double revenue = AdjustUtils.ConvertDouble(adjustEvent.Revenue); + string eventToken = adjustEvent.EventToken; + string currency = adjustEvent.Currency; + string receipt = adjustEvent.Receipt; + string productId = adjustEvent.ProductId; + string transactionId = adjustEvent.TransactionId; + string callbackId = adjustEvent.CallbackId; + string deduplicationId = adjustEvent.DeduplicationId; + string stringJsonCallbackParameters = AdjustUtils.ConvertReadOnlyCollectionOfPairsToJson(adjustEvent.CallbackParameters); + string stringJsonPartnerParameters = AdjustUtils.ConvertReadOnlyCollectionOfPairsToJson(adjustEvent.PartnerParameters); + appVerifyAndTrackCallback = callback; + + _AdjustVerifyAndTrackAppStorePurchase( + eventToken, + revenue, + currency, + receipt, + productId, + transactionId, + callbackId, + deduplicationId, + stringJsonCallbackParameters, + stringJsonPartnerParameters, + VerifyAndTrackCallbackMonoPInvoke); + } + // used for testing only (don't use this in your app) public static void SetTestOptions(Dictionary testOptions) { @@ -777,6 +823,15 @@ private static void PurchaseVerificationCallbackMonoPInvoke(string verificationR } } + [AOT.MonoPInvokeCallback(typeof(AdjustDelegateVerifyAndTrackCallback))] + private static void VerifyAndTrackCallbackMonoPInvoke(string verificationResult) { + if (appVerifyAndTrackCallback != null) + { + appVerifyAndTrackCallback(new AdjustPurchaseVerificationResult(verificationResult)); + appVerifyAndTrackCallback = null; + } + } + [AOT.MonoPInvokeCallback(typeof(AdjustDelegateResolvedDeeplinkCallback))] private static void ResolvedDeeplinkCallbackMonoPInvoke(string deeplink) { if (appResolvedDeeplinkCallback != null)