@@ -607,43 +607,93 @@ - (BOOL)isExpoApp {
607607RCT_EXPORT_METHOD (validateAndLogInAppPurchaseV2: (NSDictionary *)purchaseDetails
608608 additionalParameters:(NSDictionary *)additionalParameters) {
609609
610- if (!purchaseDetails || [purchaseDetails isKindOfClass: [NSNull class ]]) {
611- [self sendEventWithName: afOnValidationResult body: @" {\" error\" : \" Purchase details are required\" }" ];
610+ if (![self validatePurchaseDetails: purchaseDetails]) {
612611 return ;
613612 }
614613
615614 NSString * purchaseType = [purchaseDetails objectForKey: @" purchaseType" ];
616615 NSString * productId = [purchaseDetails objectForKey: @" productId" ];
617616 NSString * transactionId = [purchaseDetails objectForKey: @" transactionId" ];
618617
618+ AFSDKPurchaseType afPurchaseType = [self convertPurchaseType: purchaseType];
619+ AFSDKPurchaseDetails* details = [[AFSDKPurchaseDetails alloc ] initWithProductId: productId transactionId: transactionId purchaseType: afPurchaseType];
620+ NSDictionary <NSString *, NSString *>* stringMap = [self convertToStringMap: additionalParameters];
621+
622+ [[AppsFlyerLib shared ] validateAndLogInAppPurchase: details purchaseAdditionalDetails: stringMap completion: ^(NSDictionary * _Nullable response, NSError * _Nullable error) {
623+ if (error == nil ) {
624+ [self handleValidationResponse: response];
625+ } else {
626+ [self sendValidationError: error.localizedDescription];
627+ }
628+ }];
629+ }
630+
631+ // MARK: - Helper Methods
632+
633+ - (BOOL )validatePurchaseDetails : (NSDictionary *)purchaseDetails {
634+ if (!purchaseDetails || [purchaseDetails isKindOfClass: [NSNull class ]]) {
635+ [self sendValidationError: @" Purchase details are required" ];
636+ return NO ;
637+ }
638+
639+ NSString * purchaseType = [purchaseDetails objectForKey: @" purchaseType" ];
640+ NSString * productId = [purchaseDetails objectForKey: @" productId" ];
641+ NSString * transactionId = [purchaseDetails objectForKey: @" transactionId" ];
642+
619643 if (!purchaseType || !productId || !transactionId) {
620- [self sendEventWithName: afOnValidationResult body: @" { \" error \" : \" purchaseType, productId, and transactionId are required\" } " ];
621- return ;
644+ [self sendValidationError: @" purchaseType, productId, and transactionId are required" ];
645+ return NO ;
622646 }
623647
624- // Convert purchaseType string to enum
625- AFSDKPurchaseType afPurchaseType;
648+ return YES ;
649+ }
650+
651+ - (AFSDKPurchaseType)convertPurchaseType : (NSString *)purchaseType {
626652 if ([purchaseType isEqualToString: @" subscription" ]) {
627- afPurchaseType = AFSDKPurchaseTypeSubscription;
653+ return AFSDKPurchaseTypeSubscription;
628654 } else {
629- afPurchaseType = AFSDKPurchaseTypeOneTimePurchase;
655+ return AFSDKPurchaseTypeOneTimePurchase;
630656 }
631-
632- AFSDKPurchaseDetails* details = [[AFSDKPurchaseDetails alloc ] initWithProductId: productId transactionId: transactionId purchaseType: afPurchaseType];
657+ }
633658
634- [[AppsFlyerLib shared ] validateAndLogInAppPurchaseWithPurchaseDetails: details purchaseAdditionalDetails: additionalParameters completion: ^(NSDictionary * _Nullable response, NSError * _Nullable error) {
635- if (error == nil ) {
636- BOOL valid = [response[@" result" ] boolValue ];
637- if (valid) {
638- [self sendEventWithName: afOnValidationResult body: @" {\" result\" : true, \" message\" : \" In App Purchase Validation completed successfully!\" }" ];
639- } else {
640- NSString *msg = response[@" message" ] ?: @" Purchase validation failed" ;
641- [self sendEventWithName: afOnValidationResult body: @" {\" result\" : false, \" message\" : \" Purchase validation failed\" }" ];
642- }
643- } else {
644- [self sendEventWithName: afOnValidationResult body: [NSString stringWithFormat: @" {\" error\" : \" %@ \" }" , error.localizedDescription]];
659+ - (NSDictionary <NSString*, NSString*>*)convertToStringMap : (NSDictionary *)additionalParameters {
660+ NSMutableDictionary <NSString *, NSString *>* stringMap = [[NSMutableDictionary alloc ] init ];
661+ if (additionalParameters && ![additionalParameters isKindOfClass: [NSNull class ]]) {
662+ for (NSString * key in additionalParameters) {
663+ id value = additionalParameters[key];
664+ if (value && ![value isKindOfClass: [NSNull class ]]) {
665+ stringMap[key] = [value description ];
645666 }
646- }];
667+ }
668+ }
669+ return stringMap;
670+ }
671+
672+ - (void )handleValidationResponse : (NSDictionary *)response {
673+ NSString * firstKey = [[response allKeys ] firstObject ];
674+ if (firstKey && response[firstKey] && [response[firstKey] isKindOfClass: [NSDictionary class ]]) {
675+ NSDictionary * productData = response[firstKey];
676+ BOOL valid = [productData[@" result" ] boolValue ];
677+
678+ NSString * responseJson = [self convertToJsonString: response];
679+ [self sendEventWithName: afOnValidationResult body: responseJson];
680+ } else {
681+ [self sendValidationError: @" Invalid response format" ];
682+ }
683+ }
684+
685+ - (NSString *)convertToJsonString : (NSDictionary *)dictionary {
686+ NSError * jsonError;
687+ NSData * jsonData = [NSJSONSerialization dataWithJSONObject: dictionary options: 0 error: &jsonError];
688+ if (!jsonError && jsonData) {
689+ return [[NSString alloc ] initWithData: jsonData encoding: NSUTF8StringEncoding];
690+ }
691+ return @" {\" error\" : \" Failed to serialize response\" }" ;
692+ }
693+
694+ - (void )sendValidationError : (NSString *)errorMessage {
695+ NSString * errorJson = [NSString stringWithFormat: @" {\" error\" : \" %@ \" }" , errorMessage];
696+ [self sendEventWithName: afOnValidationResult body: errorJson];
647697}
648698
649699RCT_EXPORT_METHOD (sendPushNotificationData: (NSDictionary *)pushPayload errorCallBack:(RCTResponseErrorBlock)errorCallBack) {
0 commit comments