Skip to content

Commit

Permalink
feat: add verify and track feature
Browse files Browse the repository at this point in the history
  • Loading branch information
uerceg committed Jul 8, 2024
1 parent 7da6287 commit e05358d
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 9 deletions.
1 change: 1 addition & 0 deletions Assets/Adjust/Native/iOS/AdjustUnity.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
93 changes: 93 additions & 0 deletions Assets/Adjust/Native/iOS/AdjustUnity.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
44 changes: 36 additions & 8 deletions Assets/Adjust/Scripts/Adjust.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -715,6 +707,42 @@ public static void ProcessAndResolveDeeplink(string deeplink, Action<string> cal
#endif
}

public static void VerifyAndTrackAppStorePurchase(
AdjustEvent adjustEvent,
Action<AdjustPurchaseVerificationResult> 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<AdjustPurchaseVerificationResult> 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
Expand Down
64 changes: 64 additions & 0 deletions Assets/Adjust/Scripts/AdjustAndroid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -578,6 +579,69 @@ public static void ProcessAndResolveDeeplink(string url, Action<string> resolved
ajcAdjust.CallStatic("processAndResolveDeeplink", ajoUri, ajoCurrentActivity, onDeeplinkResolvedListener);
}

public static void VerifyAndTrackPlayStorePurchase(
AdjustEvent adjustEvent,
Action<AdjustPurchaseVerificationResult> 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<string, string> testOptions)
{
Expand Down
57 changes: 56 additions & 1 deletion Assets/Adjust/Scripts/AdjustiOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class AdjustiOS
private static List<Action<string>> appSdkVersionGetterCallbacks;
private static List<Action<int>> appAttCallbacks;
private static Action<AdjustPurchaseVerificationResult> appPurchaseVerificationCallback;
private static Action<AdjustPurchaseVerificationResult> appVerifyAndTrackCallback;
private static Action<string> appResolvedDeeplinkCallback;
private static Action<string> appSkanErrorCallback;

Expand Down Expand Up @@ -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() {}

Expand Down Expand Up @@ -325,7 +341,7 @@ public static void TrackEvent(AdjustEvent adjustEvent)
deduplicationId,
stringJsonCallbackParameters,
stringJsonPartnerParameters);
}
}

public static void Enable()
{
Expand Down Expand Up @@ -587,6 +603,36 @@ public static void ProcessAndResolveDeeplink(string deeplink, Action<string> cal
_AdjustProcessAndResolveDeeplink(deeplink, ResolvedDeeplinkCallbackMonoPInvoke);
}

public static void VerifyAndTrackAppStorePurchase(
AdjustEvent adjustEvent,
Action<AdjustPurchaseVerificationResult> 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<string, string> testOptions)
{
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit e05358d

Please sign in to comment.