diff --git a/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp b/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp index bc8294e..0539aac 100644 --- a/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp +++ b/Classes/AppsFlyer/AFSDKXPurchaseDetails.cpp @@ -8,14 +8,18 @@ #include #include "AFSDKXPurchaseDetails.h" -AFSDKXPurchaseDetails::AFSDKXPurchaseDetails(const std::string &productId, - const std::string &price, - const std::string ¤cy, - const std::string &transactionId) - : productId_(productId), - price_(price), - currency_(currency), - transactionId_(transactionId) { +AFSDKXPurchaseDetails::AFSDKXPurchaseDetails(const AFXPurchaseType &purchaseType, + const std::string &purchaseToken, + const std::string &productId, + const std::string &price, + const std::string ¤cy, + const std::string &transactionId) + :purchaseType_(purchaseType), + purchaseToken_(purchaseToken), + productId_(productId), + price_(price), + currency_(currency), + transactionId_(transactionId) { } std::string AFSDKXPurchaseDetails::getProductId() const { @@ -49,3 +53,34 @@ std::string AFSDKXPurchaseDetails::getTransactionId() const { void AFSDKXPurchaseDetails::setTransactionId(const std::string &transactionId) { transactionId_ = transactionId; } + +std::string AFSDKXPurchaseDetails::getPurchaseToken() const { + return purchaseToken_; +} + +void AFSDKXPurchaseDetails::setPurchaseToken(const std::string &purchaseToken) { + purchaseToken_ = purchaseToken; +} + +std::string AFSDKXPurchaseDetails::getPurchaseType() const { + std::string purchaseTypeStr = purchaseTypeToString(); + return purchaseTypeStr; +} + +void AFSDKXPurchaseDetails::setPurchaseType(AFXPurchaseType &purchaseType) { + purchaseType_ = purchaseType; +} + +// Function to get the string value of the enum +std::string AFSDKXPurchaseDetails::purchaseTypeToString() const{ + switch (purchaseType_) { + case AFXPurchaseType::SUBSCRIPTION: + return "subscription"; + case AFXPurchaseType::ONE_TIME_PURCHASE: + return "one_time_purchase"; + case AFXPurchaseType::APPLE: + return ""; + default: + return ""; + } +} diff --git a/Classes/AppsFlyer/AFSDKXPurchaseDetails.h b/Classes/AppsFlyer/AFSDKXPurchaseDetails.h index 275542c..2f24148 100644 --- a/Classes/AppsFlyer/AFSDKXPurchaseDetails.h +++ b/Classes/AppsFlyer/AFSDKXPurchaseDetails.h @@ -12,6 +12,12 @@ #include "cocos2d.h" #include "AFSDKXValidateAndLogResult.h" +enum class AFXPurchaseType { + SUBSCRIPTION, + ONE_TIME_PURCHASE, + APPLE +}; + class AFSDKXPurchaseDetails { public: @@ -19,10 +25,12 @@ class AFSDKXPurchaseDetails { AFSDKXPurchaseDetails() = delete; // Constructor with parameters to initialize the properties. - AFSDKXPurchaseDetails(const std::string &productId, - const std::string &price, - const std::string ¤cy, - const std::string &transactionId); + AFSDKXPurchaseDetails(const AFXPurchaseType &purchaseType, + const std::string &purchaseToken, + const std::string &productId, + const std::string &price, + const std::string ¤cy, + const std::string &transactionId); // Default destructor. virtual ~AFSDKXPurchaseDetails() = default; @@ -44,11 +52,23 @@ class AFSDKXPurchaseDetails { std::string getTransactionId() const; void setTransactionId(const std::string &transactionId); + // Propperties related to Android impl + // For Apple implementation, please pass APPLE, it will be interpreted as an empty string + std::string purchaseTypeToString() const; + std::string getPurchaseType() const; + void setPurchaseType(AFXPurchaseType &purchaseType); + + // Android purchase token, for iOS impl, please use empty string + std::string getPurchaseToken() const; + void setPurchaseToken(const std::string &purchaseToken); + private: // Private member variables. std::string productId_; std::string price_; std::string currency_; std::string transactionId_; + std::string purchaseToken_; + AFXPurchaseType purchaseType_; }; #endif /* AFSDKXPurchaseDetails_h */ diff --git a/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp index 729320a..9b31f7f 100644 --- a/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp +++ b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.cpp @@ -13,7 +13,7 @@ AFSDKXValidateAndLogResult::AFSDKXValidateAndLogResult( AFSDKXValidateAndLogStatus status, const cocos2d::ValueMap& result, const cocos2d::ValueMap& errorData, - const std::shared_ptr& error) + const cocos2d::ValueMap& error) : status_(status), result_(result), errorData_(errorData), error_(error) { } @@ -30,6 +30,21 @@ cocos2d::ValueMap AFSDKXValidateAndLogResult::getErrorData() const { return errorData_; } -std::shared_ptr AFSDKXValidateAndLogResult::getError() const { +cocos2d::ValueMap AFSDKXValidateAndLogResult::getError() const { return error_; } + +// Function to map Objective-C enum to C++ enum +AFSDKXValidateAndLogStatus AFSDKXValidateAndLogResult::objcEnumToCppEnum(int objcStatus) { + switch (objcStatus) { + case 0: + return AFSDKXValidateAndLogStatus::Success; + case 1: + return AFSDKXValidateAndLogStatus::Failure; + case 2: + return AFSDKXValidateAndLogStatus::Error; + default: + // Handle unknown cases, or return a default value + return AFSDKXValidateAndLogStatus::Error; + } +} diff --git a/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h index 60c0d31..1136b1e 100644 --- a/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h +++ b/Classes/AppsFlyer/AFSDKXValidateAndLogResult.h @@ -33,20 +33,22 @@ class AFSDKXValidateAndLogResult { AFSDKXValidateAndLogResult(AFSDKXValidateAndLogStatus status, const cocos2d::ValueMap& result, const cocos2d::ValueMap& errorData, - const std::shared_ptr& error); + const cocos2d::ValueMap& error); // Getter methods AFSDKXValidateAndLogStatus getStatus() const; + static AFSDKXValidateAndLogStatus objcEnumToCppEnum(int objcStatus); cocos2d::ValueMap getResult() const; cocos2d::ValueMap getErrorData() const; - std::shared_ptr getError() const; + cocos2d::ValueMap getError() const; + private: // Member variables. AFSDKXValidateAndLogStatus status_; cocos2d::ValueMap result_; cocos2d::ValueMap errorData_; - std::shared_ptr error_; + cocos2d::ValueMap error_; }; #endif /* AFSDKXValidateAndLogResult_h */ diff --git a/Classes/AppsFlyer/AFXAdRevenueData.cpp b/Classes/AppsFlyer/AFXAdRevenueData.cpp index ceb2250..ded3ac3 100644 --- a/Classes/AppsFlyer/AFXAdRevenueData.cpp +++ b/Classes/AppsFlyer/AFXAdRevenueData.cpp @@ -28,6 +28,41 @@ AppsFlyerXAdRevenueMediationNetworkType AFXAdRevenueData::getMediationNetwork() return mediationNetwork; } +std::string AFXAdRevenueData::meditationNetworkString() const { + switch (mediationNetwork) { + case AppsFlyerXAdRevenueMediationNetworkType::GoogleAdMob: + return "GOOGLE_ADMOB"; + case AppsFlyerXAdRevenueMediationNetworkType::IronSource: + return "IRONSOURCE"; + case AppsFlyerXAdRevenueMediationNetworkType::ApplovinMax: + return "APPLOVIN_MAX"; + case AppsFlyerXAdRevenueMediationNetworkType::Fyber: + return "FYBER"; + case AppsFlyerXAdRevenueMediationNetworkType::Appodeal: + return "APPODEAL"; + case AppsFlyerXAdRevenueMediationNetworkType::Admost: + return "ADMOST"; + case AppsFlyerXAdRevenueMediationNetworkType::Topon: + return "TOPON"; + case AppsFlyerXAdRevenueMediationNetworkType::Tradplus: + return "TRADPLUS"; + case AppsFlyerXAdRevenueMediationNetworkType::Yandex: + return "YANDEX"; + case AppsFlyerXAdRevenueMediationNetworkType::ChartBoost: + return "CHARTBOOST"; + case AppsFlyerXAdRevenueMediationNetworkType::Unity: + return "UNITY"; + case AppsFlyerXAdRevenueMediationNetworkType::ToponPte: + return "TOPON_PTE"; + case AppsFlyerXAdRevenueMediationNetworkType::Custom: + return "CUSTOM_MEDIATION"; + case AppsFlyerXAdRevenueMediationNetworkType::DirectMonetization: + return "DIRECT_MONETIZATION_NETWORK"; + default: + return "unknown"; + } +}; + std::string AFXAdRevenueData::getCurrencyIso4217Code() const { return currencyIso4217Code; } diff --git a/Classes/AppsFlyer/AFXAdRevenueData.h b/Classes/AppsFlyer/AFXAdRevenueData.h index 9fe0a61..d045d6f 100644 --- a/Classes/AppsFlyer/AFXAdRevenueData.h +++ b/Classes/AppsFlyer/AFXAdRevenueData.h @@ -63,6 +63,7 @@ class AFXAdRevenueData { std::string getCurrencyIso4217Code() const; double getEventRevenue() const; int convertMeditationType(AppsFlyerXAdRevenueMediationNetworkType a); + std::string meditationNetworkString() const; private: // Private member variables diff --git a/Classes/AppsFlyer/AppsFlyerX.cpp b/Classes/AppsFlyer/AppsFlyerX.cpp index c85ff80..74312a8 100644 --- a/Classes/AppsFlyer/AppsFlyerX.cpp +++ b/Classes/AppsFlyer/AppsFlyerX.cpp @@ -335,6 +335,8 @@ void AppsFlyerX::validateAndLogInAppPurchase(const std::string& publicKey, void AppsFlyerX::logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap additionalParameters) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) // Android implementation + CCLOGWARN("Log AdRevenue Android"); + AppsFlyerXAndroid::logAdRevenue(adRevenueData, additionalParameters); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) AppsFlyerXApple::logAdRevenue(adRevenueData, additionalParameters); #endif @@ -343,6 +345,7 @@ void AppsFlyerX::logAdRevenue(AFXAdRevenueData adRevenueData, cocos2d::ValueMap void AppsFlyerX::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) // Android implementation + AppsFlyerXAndroid::validateAndLogInAppPurchase(details, std::move(params), std::move(completionHandler)); #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) AppsFlyerXApple::validateAndLogInAppPurchase(details, params, completionHandler); #endif diff --git a/Classes/AppsFlyer/AppsFlyerXAndroid.cpp b/Classes/AppsFlyer/AppsFlyerXAndroid.cpp index 5d05f54..2d692c4 100644 --- a/Classes/AppsFlyer/AppsFlyerXAndroid.cpp +++ b/Classes/AppsFlyer/AppsFlyerXAndroid.cpp @@ -5,6 +5,7 @@ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include +#include "stdlib.h" #include "AppsFlyerXAndroid.h" #include "AppsFlyerProxyX.h" @@ -396,10 +397,6 @@ void callSetPluginInfo(jobject extensionObject) { } } -void AppsFlyerXAndroid::logEvent(const std::string &eventName, const std::string &value) { - -} - void AppsFlyerXAndroid::logEvent(const std::string &eventName, cocos2d::ValueMap values) { cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); @@ -443,6 +440,98 @@ void AppsFlyerXAndroid::logEvent(const std::string &eventName, cocos2d::ValueMap } } + +void AppsFlyerXAndroid::logAdRevenue(const AFXAdRevenueData &adRevenueData, cocos2d::ValueMap params) { + cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); + + jobject afInstance = (jobject) jniGetInstance.env->CallStaticObjectMethod( + jniGetInstance.classID, jniGetInstance.methodID); + + std::string appsFlyerUid; + + cocos2d::JniMethodInfo miGetContext; + + if (!cocos2d::JniHelper::getStaticMethodInfo(miGetContext, "org/cocos2dx/lib/Cocos2dxActivity", + "getContext", "()Landroid/content/Context;")) { + return; + } + jobject jContext = (jobject) miGetContext.env->CallStaticObjectMethod(miGetContext.classID, + miGetContext.methodID); + + jobject hashMapObj = valueMapToHashMap(jniGetInstance, params); + + if (NULL != afInstance) { + // CCLOG("%s", "com/appsflyer/AppsFlyerLib is loaded"); + jclass afAdRevenueDataClass = jniGetInstance.env->FindClass( + "com/appsflyer/AFAdRevenueData"); + jmethodID afAdRevenueDataMethodId = jniGetInstance.env->GetMethodID(afAdRevenueDataClass, + "", + "(Ljava/lang/String;Lcom/appsflyer/MediationNetwork;Ljava/lang/String;D)V"); + + jclass mediationNetworkClass = jniGetInstance.env->FindClass("com/appsflyer/MediationNetwork"); + + // Get the enum value by name (e.g., "IRONSOURCE", "APPLOVIN_MAX") + jmethodID valueOfMethod = jniGetInstance.env->GetStaticMethodID(mediationNetworkClass, "valueOf", "(Ljava/lang/String;)Lcom/appsflyer/MediationNetwork;"); + + // Check if the valueOf method was found + if (valueOfMethod == nullptr) { + // Handle error, method not found + return; + } + + // Create a Java string from the enumName + jstring enumNameString = jniGetInstance.env->NewStringUTF(adRevenueData.meditationNetworkString().c_str()); + + // Call the valueOf method to get the enum constant + jobject jMediationNetworkEnumObject = jniGetInstance.env->CallStaticObjectMethod(mediationNetworkClass, valueOfMethod, enumNameString); + jobject jMonetizationNetwork = jniGetInstance.env->NewStringUTF(adRevenueData.getMonetizationNetwork().c_str()); + jobject jCurrencyCode = jniGetInstance.env->NewStringUTF(adRevenueData.getCurrencyIso4217Code().c_str()); + +// jclass doubleClass = jniGetInstance.env->FindClass("java/lang/Double"); +// +// // Check if the class was found +// if (doubleClass == nullptr) { +// // Handle error +// return nullptr; +// } +// +// // Get the Double class constructor that takes a double (D) as a parameter +// jmethodID doubleConstructor = jniGetInstance.env->GetMethodID(doubleClass, "", "(D)V"); +// +// // Check if the constructor was found +// if (doubleConstructor == nullptr) { +// // Handle error +// return; +// } + +// jobject jRevenue = jniGetInstance.env->NewObject(doubleClass, doubleConstructor,); + + jobject afAdRevenueDataObject = jniGetInstance.env->NewObject(afAdRevenueDataClass, afAdRevenueDataMethodId, + jMonetizationNetwork, + jMediationNetworkEnumObject, + jCurrencyCode, + adRevenueData.getEventRevenue()); + + jclass cls = jniGetInstance.env->GetObjectClass(afInstance); + + jmethodID methodId = jniGetInstance.env->GetMethodID(cls, "logAdRevenue", + "(Lcom/appsflyer/AFAdRevenueData;" + "Ljava/util/Map;)V"); + + jniGetInstance.env->CallVoidMethod(afInstance, methodId, afAdRevenueDataObject, hashMapObj); + + // cleanup + jniGetInstance.env->DeleteLocalRef(enumNameString); + jniGetInstance.env->DeleteLocalRef(afAdRevenueDataObject); + jniGetInstance.env->DeleteLocalRef(jMediationNetworkEnumObject); + jniGetInstance.env->DeleteLocalRef(jMonetizationNetwork); + jniGetInstance.env->DeleteLocalRef(jCurrencyCode); + jniGetInstance.env->DeleteLocalRef(afInstance); + } else { + CCLOGWARN("com/appsflyer/AppsFlyerLib is not loaded"); + } +} + void AppsFlyerXAndroid::setUserEmails(std::vector userEmails, EmailCryptTypeX type) { } @@ -634,6 +723,129 @@ void AppsFlyerXAndroid::validateAndLogInAppPurchase(const std::string &publicKey } } +void AppsFlyerXAndroid::validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler) { + cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); + + jobject afInstance = (jobject) jniGetInstance.env->CallStaticObjectMethod( + jniGetInstance.classID, jniGetInstance.methodID); + + cocos2d::JniMethodInfo miGetContext; + + if (!cocos2d::JniHelper::getStaticMethodInfo(miGetContext, "org/cocos2dx/lib/Cocos2dxActivity", + "getContext", "()Landroid/content/Context;")) { + return; + } + jobject jContext = (jobject) miGetContext.env->CallStaticObjectMethod(miGetContext.classID, + miGetContext.methodID); + + + // Convert string params to jstring + std::string jPurchaseTypeString = details.getPurchaseType(); + jstring jPurchaseToken = jniGetInstance.env->NewStringUTF(details.getPurchaseToken().c_str()); + jstring jProductId = jniGetInstance.env->NewStringUTF(details.getProductId().c_str()); + jstring jPrice = jniGetInstance.env->NewStringUTF(details.getPrice().c_str()); + jstring jCurrency = jniGetInstance.env->NewStringUTF(details.getCurrency().c_str()); + + jobject hashMapObj = valueMapToHashMap(jniGetInstance, params); + + + if (NULL != afInstance) { + // CCLOG("%s", "com/appsflyer/AppsFlyerLib is loaded"); + jclass afPurchaseDetailsClass = jniGetInstance.env->FindClass("com/appsflyer/AFPurchaseDetails"); + jmethodID purchaseDetails = jniGetInstance.env->GetMethodID(afPurchaseDetailsClass, "", + "(Lcom/appsflyer/AFPurchaseType;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;" + "Ljava/lang/String;)V"); + + jclass afPurchaseTypeClass = jniGetInstance.env->FindClass("com/appsflyer/AFPurchaseType"); + +// Get the valueOf method for AFPurchaseType + jmethodID afPurchaseTypeMethodId = jniGetInstance.env->GetStaticMethodID(afPurchaseTypeClass, "values", "()[Lcom/appsflyer/AFPurchaseType;"); + jobjectArray afPurchaseTypeArray = (jobjectArray) jniGetInstance.env->CallStaticObjectMethod(afPurchaseTypeClass, afPurchaseTypeMethodId); + if (afPurchaseTypeArray == nullptr) { + CCLOG("Error: Call to values() returned null."); + return; + } + +// Get the length of the array + jsize arrayLength = jniGetInstance.env->GetArrayLength(afPurchaseTypeArray); + CCLOG("AFPurchaseType array length: %d", arrayLength); + +// Access the first constant (SUBSCRIPTION) + jobject selectedPurchaseType; + if (jPurchaseTypeString.compare("subscription") == 0) { + CCLOG("Purchase type is 'subscription'."); + selectedPurchaseType = jniGetInstance.env->GetObjectArrayElement(afPurchaseTypeArray, 0); + CCLOG("First enum constant (SUBSCRIPTION): %p", selectedPurchaseType); + } else if (jPurchaseTypeString.compare("one_time_purchase") == 0) { + CCLOG("Purchase type is 'one_time_purchase'."); + selectedPurchaseType = jniGetInstance.env->GetObjectArrayElement(afPurchaseTypeArray, 1); + CCLOG("Second enum constant (ONE_TIME_PURCHASE): %p", selectedPurchaseType); + } else { + CCLOG("Error: Unknown purchase type."); + return; + } + + CCLOG("afPurchaseTypeClass: %p", afPurchaseTypeClass); + jobject jPurchaseDetails = jniGetInstance.env->NewObject(afPurchaseDetailsClass, + purchaseDetails, + selectedPurchaseType, + jPurchaseToken, + jProductId, + jPrice, + jCurrency); + + CCLOG("Purchase details: %p", jPurchaseDetails); + jclass cls = jniGetInstance.env->GetObjectClass(afInstance); + jmethodID methodId = jniGetInstance.env->GetMethodID( + cls, + "validateAndLogInAppPurchase", + "(Lcom/appsflyer/AFPurchaseDetails;" + "Ljava/util/Map;" + "Lcom/appsflyer/AppsFlyerInAppPurchaseValidationCallback;)V" + ); + + +// CCLOG("Success, will proceed to get vallback class"); +// jclass callbackClass = jniGetInstance.env->FindClass("com/appsflyer/AppsFlyerInAppPurchaseValidationCallback"); +// if (callbackClass == nullptr) { +// CCLOG("Error: Cannot find class 'InAppPurchaseValidationCallback'."); +// return; +// } +// CCLOG("Success, will proceed to get callback constructor"); +//// Get the constructor for InAppPurchaseValidationCallback, which takes a long (native pointer) +// jmethodID constructor = jniGetInstance.env->GetMethodID(callbackClass, "", "()V"); +// if (constructor == nullptr) { +// CCLOG("Error: Cannot find constructor for 'InAppPurchaseValidationCallback'."); +// return; +// } +// CCLOG("Success, will proceed to create an instance of callback constructor"); +//// Create an instance of InAppPurchaseValidationCallback with the native pointer +// jobject jValidationCallback = jniGetInstance.env->NewObject(callbackClass, constructor); +// if (jValidationCallback == nullptr) { +// CCLOG("Error: Failed to create InAppPurchaseValidationCallback instance."); +// return; +// } + + CCLOG("Calling the API"); + jniGetInstance.env->CallVoidMethod(afInstance, methodId, jPurchaseDetails, hashMapObj, + nullptr); + + jniGetInstance.env->DeleteLocalRef(hashMapObj); + jniGetInstance.env->DeleteLocalRef(afInstance); + jniGetInstance.env->DeleteLocalRef(jniGetInstance.classID); + + jniGetInstance.env->DeleteLocalRef(jPurchaseToken); + jniGetInstance.env->DeleteLocalRef(jProductId); + jniGetInstance.env->DeleteLocalRef(jPrice); + jniGetInstance.env->DeleteLocalRef(jCurrency); + } else { + CCLOGERROR("%s", "'AppsFlyerLib' is not loaded"); + } +} + //Sharing data filter void AppsFlyerXAndroid::sharingFilter(std::vector partners){ cocos2d::JniMethodInfo jniGetInstance = getAppsFlyerInstance(); diff --git a/Classes/AppsFlyer/AppsFlyerXAndroid.h b/Classes/AppsFlyer/AppsFlyerXAndroid.h index fc273c5..1e2c5e1 100644 --- a/Classes/AppsFlyer/AppsFlyerXAndroid.h +++ b/Classes/AppsFlyer/AppsFlyerXAndroid.h @@ -75,12 +75,14 @@ class AppsFlyerXAndroid { static void start(); - static void logEvent(const std::string& eventName, const std::string& value); - static void logEvent(const std::string& eventName, cocos2d::ValueMap values); + static void logAdRevenue(const AFXAdRevenueData& adRevenueData, cocos2d::ValueMap params); + static void validateAndLogInAppPurchase(std::string productIdentifier, std::string price, std::string currency, std::string tranactionId, cocos2d::ValueMap params, void (*successBlock)(cocos2d::ValueMap response), void (*failedBlock)(void* error, void* responce)); + static void validateAndLogInAppPurchase(AFSDKXPurchaseDetails &details, cocos2d::ValueMap params, std::function completionHandler); + static void logLocation(double longitude, double latitude); static std::string getAppsFlyerUID(); diff --git a/Classes/AppsFlyer/AppsFlyerXApple.mm b/Classes/AppsFlyer/AppsFlyerXApple.mm index ca1098d..e0c5400 100644 --- a/Classes/AppsFlyer/AppsFlyerXApple.mm +++ b/Classes/AppsFlyer/AppsFlyerXApple.mm @@ -271,6 +271,18 @@ [[AppsFlyerLib shared] validateAndLogInAppPurchase:afPurchaseDetails extraEventValues:lParams completionHandler:^(AFSDKValidateAndLogResult * _Nullable result) { // TODO: - add result to completionHandler NSLog(@"[ValidateAndLog] Result: %@", result); + AFSDKXValidateAndLogStatus status = AFSDKXValidateAndLogResult::objcEnumToCppEnum(result.status); + cocos2d::ValueMap resultX = AppsFlyerXAppleHelper::nsDictionary2ValueMap(result.result); + cocos2d::ValueMap errorData = AppsFlyerXAppleHelper::nsDictionary2ValueMap(result.errorData); + + NSMutableDictionary *errorDictionary = [NSMutableDictionary dictionary]; + if (result.error) { + errorDictionary[@"errorCode"] = [NSNumber numberWithInteger:result.error.code]; + errorDictionary[@"errorDescription"] = result.error.localizedDescription; + } + AFSDKXValidateAndLogResult validateResult = AFSDKXValidateAndLogResult(status, resultX, errorData, AppsFlyerXAppleHelper::nsDictionary2ValueMap(errorDictionary)); + + completionHandler(validateResult); }]; } diff --git a/Classes/HelloWorldScene.cpp b/Classes/HelloWorldScene.cpp index 4fa37f8..8481adc 100644 --- a/Classes/HelloWorldScene.cpp +++ b/Classes/HelloWorldScene.cpp @@ -111,19 +111,13 @@ bool HelloWorld::init() std::cout << "Log event raised" << std::endl; ValueMap params; - AFSDKXPurchaseDetails details = AFSDKXPurchaseDetails("customId", "6.99", "USD", "transactionId"); +// AFXAdRevenueData data = AFXAdRevenueData("someVal", AppsFlyerXAdRevenueMediationNetworkType::ApplovinMax, "USD", 7.99); +// AppsFlyerX::logAdRevenue(data, params); + AFSDKXPurchaseDetails details = AFSDKXPurchaseDetails(AFXPurchaseType::SUBSCRIPTION, "", "customId", "6.99", "USD", "transactionId"); AppsFlyerX::validateAndLogInAppPurchase(details, params, [](const AFSDKXValidateAndLogResult& result) { std::cout << "Result Status: " << static_cast(result.getStatus()) << std::endl; + }); -// AppsFlyerX::validateAndLogInAppPurchase("1", "2", "USD", "3", params, [&](cocos2d::ValueMap result) { -// for (auto& t : result) -// std::cout << t.first << " " -// << t.second.asString() << "\n"; -// }, [&](cocos2d::ValueMap error) { -// for (auto& t : error) -// std::cout << t.first << " " -// << t.second.asString() << "\n"; -// }); break; } default: diff --git a/Classes/InAppPurchaseValidationCallback b/Classes/InAppPurchaseValidationCallback new file mode 100644 index 0000000..8406823 --- /dev/null +++ b/Classes/InAppPurchaseValidationCallback @@ -0,0 +1,27 @@ +import com.appsflyer.AppsFlyerInAppPurchaseValidationCallback + + +public class CocosInAppPurchaseValidationCallback implements AppsFlyerInAppPurchaseValidationCallback { + + private long nativePointer; // Store a pointer to the native (C++) code + + public InAppPurchaseValidationCallback(long nativePointer) { + this.nativePointer = nativePointer; + } + + @Override + public void onInAppPurchaseValidationFinished(Map validationResult) { + // Call native method + nativeOnPurchaseValidationFinished(nativePointer, validationResult); + } + + @Override + public void onInAppPurchaseValidationError(Map validationError) { + // Call native method + nativeOnPurchaseValidationError(nativePointer, validationError); + } + + // Declare native methods to call back into C++ + private native void nativeOnPurchaseValidationFinished(long nativePointer, Map validationResult); + private native void nativeOnPurchaseValidationError(long nativePointer, Map validationError); +} \ No newline at end of file diff --git a/proj.android-studio/app/AndroidManifest.xml b/proj.android-studio/app/AndroidManifest.xml index a97bcb7..3748764 100644 --- a/proj.android-studio/app/AndroidManifest.xml +++ b/proj.android-studio/app/AndroidManifest.xml @@ -1,9 +1,11 @@ - + + + + + package="com.example.yourapp"> -