From 2a293ee65ee1a6702eaf83a6c163e1edd90b58f7 Mon Sep 17 00:00:00 2001 From: Amit Levy Date: Sun, 6 Oct 2024 11:27:46 +0300 Subject: [PATCH] Separated callbacks to onSuccess onFailure, modified native impl accordingly --- PurchaseConnector/constants/constants.ts | 8 +- .../utils/connector_callbacks.ts | 2 +- .../reactnative/PCAppsFlyerModule.java | 8 +- .../reactnative/RNAppsFlyerConstants.java | 6 +- demos/appsflyer-react-native-app/.gitignore | 3 + demos/appsflyer-react-native-app/App.js | 3 + .../android/app/build.gradle | 2 + .../android/build.gradle | 2 + .../babel.config.js | 17 ++- .../components/AppsFlyer.js | 4 +- .../components/Cart.js | 130 +++++++++++----- .../project.pbxproj | 12 +- demos/appsflyer-react-native-app/package.json | 7 +- index.d.ts | 6 +- index.js | 140 ++++++++++++------ ios/PCAppsFlyer.m | 9 +- 16 files changed, 245 insertions(+), 114 deletions(-) diff --git a/PurchaseConnector/constants/constants.ts b/PurchaseConnector/constants/constants.ts index 78aacf6a..0e73fe2d 100644 --- a/PurchaseConnector/constants/constants.ts +++ b/PurchaseConnector/constants/constants.ts @@ -3,10 +3,10 @@ class AppsFlyerConstants { static readonly MISSING_CONFIGURATION_EXCEPTION_MSG: string = "Could not create an instance without configuration"; // Adding method constants - static readonly SUBSCRIPTION_PURCHASE_VALIDATION_RESULT_LISTENER: string = - "onSubscriptionValidationResult"; - static readonly IN_APP_VALIDATION_RESULT_LISTENER: string = - "onInAppPurchaseValidationResult"; + static readonly SUBSCRIPTION_VALIDATION_SUCCESS: string = 'subscriptionValidationSuccess'; + static readonly SUBSCRIPTION_VALIDATION_FAILURE: string = 'subscriptionValidationFailure'; + static readonly IN_APP_PURCHASE_VALIDATION_SUCCESS: string = 'inAppPurchaseValidationSuccess'; + static readonly IN_APP_PURCHASE_VALIDATION_FAILURE: string = 'inAppPurchaseValidationFailure'; static readonly DID_RECEIVE_PURCHASE_REVENUE_VALIDATION_INFO: string = "onDidReceivePurchaseRevenueValidationInfo"; diff --git a/PurchaseConnector/utils/connector_callbacks.ts b/PurchaseConnector/utils/connector_callbacks.ts index 903836b7..decbbb8e 100644 --- a/PurchaseConnector/utils/connector_callbacks.ts +++ b/PurchaseConnector/utils/connector_callbacks.ts @@ -4,7 +4,7 @@ import { IosError, JVMThrowable } from "../models"; export type PurchaseConnectorListener = (data: any) => void; // Type definition for a listener which gets called when the `PurchaseConnectorImpl` receives purchase revenue validation info for iOS. -export type DidReceivePurchaseRevenueValidationInfo = (validationInfo?: Map, error?: IosError) => void; +export type onReceivePurchaseRevenueValidationInfo = (validationInfo?: Map, error?: IosError) => void; // Invoked when a 200 OK response is received from the server. // Note: An INVALID purchase is considered to be a successful response and will also be returned by this callback. diff --git a/android/src/main/java/com/appsflyer/reactnative/PCAppsFlyerModule.java b/android/src/main/java/com/appsflyer/reactnative/PCAppsFlyerModule.java index 3d01a8f6..9c95b9a4 100644 --- a/android/src/main/java/com/appsflyer/reactnative/PCAppsFlyerModule.java +++ b/android/src/main/java/com/appsflyer/reactnative/PCAppsFlyerModule.java @@ -131,12 +131,12 @@ public void stopObservingTransactions() { private final MappedValidationResultListener arsListener = new MappedValidationResultListener() { @Override public void onFailure(String result, Throwable error) { - handleError(EVENT_SUBSCRIPTION_VALIDATION_RESULT, result, error); + handleError(EVENT_SUBSCRIPTION_VALIDATION_FAILURE, result, error); } @Override public void onResponse(Map response) { - handleSuccess(EVENT_SUBSCRIPTION_VALIDATION_RESULT, response); + handleSuccess(EVENT_SUBSCRIPTION_VALIDATION_SUCCESS, response); } }; @@ -144,12 +144,12 @@ public void onResponse(Map response) { private final MappedValidationResultListener viapListener = new MappedValidationResultListener() { @Override public void onFailure(String result, Throwable error) { - handleError(EVENT_IN_APP_PURCHASE_VALIDATION_RESULT, result, error); + handleError(EVENT_IN_APP_PURCHASE_VALIDATION_FAILURE, result, error); } @Override public void onResponse(Map response) { - handleSuccess(EVENT_IN_APP_PURCHASE_VALIDATION_RESULT, response); + handleSuccess(EVENT_IN_APP_PURCHASE_VALIDATION_SUCCESS, response); } }; diff --git a/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java b/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java index 21aff74c..c14eeb51 100755 --- a/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java +++ b/android/src/main/java/com/appsflyer/reactnative/RNAppsFlyerConstants.java @@ -59,8 +59,10 @@ public class RNAppsFlyerConstants { final static String AF_ADDITIONAL_PARAMETERS = "additionalParameters"; //Purchase Connector - final static String EVENT_SUBSCRIPTION_VALIDATION_RESULT = "onSubscriptionValidationResult"; - final static String EVENT_IN_APP_PURCHASE_VALIDATION_RESULT = "onInAppPurchaseValidationResult"; + final static String EVENT_SUBSCRIPTION_VALIDATION_SUCCESS = "subscriptionValidationSuccess"; + final static String EVENT_SUBSCRIPTION_VALIDATION_FAILURE = "subscriptionValidationFailure"; + final static String EVENT_IN_APP_PURCHASE_VALIDATION_SUCCESS = "inAppPurchaseValidationSuccess"; + final static String EVENT_IN_APP_PURCHASE_VALIDATION_FAILURE = "inAppPurchaseValidationFailure"; final static String ENABLE_MODULE_MESSAGE = "Please set appsflyer.enable_purchase_connector to true in your gradle.properties file."; } diff --git a/demos/appsflyer-react-native-app/.gitignore b/demos/appsflyer-react-native-app/.gitignore index ad572e63..8631d5c4 100644 --- a/demos/appsflyer-react-native-app/.gitignore +++ b/demos/appsflyer-react-native-app/.gitignore @@ -57,3 +57,6 @@ buck-out/ # CocoaPods /ios/Pods/ + +#Secrets +.env diff --git a/demos/appsflyer-react-native-app/App.js b/demos/appsflyer-react-native-app/App.js index 18aded76..789c353e 100644 --- a/demos/appsflyer-react-native-app/App.js +++ b/demos/appsflyer-react-native-app/App.js @@ -25,6 +25,7 @@ import {createStackNavigator} from '@react-navigation/stack'; import HomeScreen from './components/HomeScreen.js'; import Cart from './components/Cart.js'; import Item from './components/Item.js'; +import {withIAPContext} from 'react-native-iap'; const Stack = createStackNavigator(); try { @@ -59,3 +60,5 @@ const App = () => { const styles = StyleSheet.create({}); export default App; + +//export default withIAPContext(App); diff --git a/demos/appsflyer-react-native-app/android/app/build.gradle b/demos/appsflyer-react-native-app/android/app/build.gradle index 7ce0d22f..e6b0cbbb 100644 --- a/demos/appsflyer-react-native-app/android/app/build.gradle +++ b/demos/appsflyer-react-native-app/android/app/build.gradle @@ -131,6 +131,8 @@ android { targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" + //RNIap + missingDimensionStrategy "store", "play" } splits { abi { diff --git a/demos/appsflyer-react-native-app/android/build.gradle b/demos/appsflyer-react-native-app/android/build.gradle index 002b28af..6613c0dc 100644 --- a/demos/appsflyer-react-native-app/android/build.gradle +++ b/demos/appsflyer-react-native-app/android/build.gradle @@ -7,6 +7,8 @@ buildscript { compileSdkVersion = 34 targetSdkVersion = 34 ndkVersion = "20.1.5948944" + //For RNIap + supportLibVersion = "28.0.0" } repositories { google() diff --git a/demos/appsflyer-react-native-app/babel.config.js b/demos/appsflyer-react-native-app/babel.config.js index f842b77f..7fbf1d05 100644 --- a/demos/appsflyer-react-native-app/babel.config.js +++ b/demos/appsflyer-react-native-app/babel.config.js @@ -1,3 +1,16 @@ module.exports = { - presets: ['module:metro-react-native-babel-preset'], -}; + presets: ["module:metro-react-native-babel-preset"], + plugins: [ + [ + "module:react-native-dotenv", + { + moduleName: "@env", + path: ".env", + blacklist: null, + whitelist: null, + safe: false, + allowUndefined: true, + }, + ], + ], +}; \ No newline at end of file diff --git a/demos/appsflyer-react-native-app/components/AppsFlyer.js b/demos/appsflyer-react-native-app/components/AppsFlyer.js index a6b992e6..71184660 100644 --- a/demos/appsflyer-react-native-app/components/AppsFlyer.js +++ b/demos/appsflyer-react-native-app/components/AppsFlyer.js @@ -14,11 +14,11 @@ export const AF_clickOnItem = 'af_click_on_item'; const initOptions = { isDebug: true, - devKey: 'Us4GmXxXx46Qed', + devKey: 'WdpTVAcYwmxsaQ4WeTspmh', onInstallConversionDataListener: true, timeToWaitForATTUserAuthorization: 10, onDeepLinkListener: true, - appId: '741993747', + appId: '1201211633', }; // AppsFlyer initialization flow. ends with initSdk. diff --git a/demos/appsflyer-react-native-app/components/Cart.js b/demos/appsflyer-react-native-app/components/Cart.js index 49572da8..a4336451 100644 --- a/demos/appsflyer-react-native-app/components/Cart.js +++ b/demos/appsflyer-react-native-app/components/Cart.js @@ -1,53 +1,105 @@ /* @flow weak */ import React from 'react'; -import {View, Text, StyleSheet, ScrollView} from 'react-native'; -import {ListItem, Avatar, Button} from 'react-native-elements' +import {View, Text, StyleSheet, ScrollView, Alert} from 'react-native'; +import {ListItem, Avatar, Button} from 'react-native-elements'; +//import {InAppPurchase} from 'react-native-iap'; const Cart = ({route, navigation}) => { - const {productList, removeProductFromCart, checkout} = route.params; + const {productList, removeProductFromCart, checkout} = route.params; + + /* + const productIds = [ + 'one1', + 'non.cons2', + 'auto.renew', + 'non.renew', + 'cons.test', + 'nonconsumable.purchase1', + 'autorenewable.purchase1', + 'nonrenewing.purchase1', + ]; - const handleRemove = product => { - removeProductFromCart(product); - navigation.goBack(); - } + InAppPurchase.getProducts(productIds) + .then(products => { + console.log('Products:', products); + }) + .catch(error => { + console.log('Error fetching products:', error); + }); + */ + + const handleRemove = product => { + removeProductFromCart(product); + navigation.goBack(); + }; - const handleCheckout = () => { - if (productList.length !== 0) { - checkout(); - navigation.goBack(); - } - } + const handleCheckout = () => { + if (productList.length !== 0) { + checkout(); + navigation.goBack(); + } else { + Alert.alert( + 'Cart Empty', // Alert Title + 'The cart is empty.', // Alert Message + [ + { + text: 'OK', + onPress: () => console.log('OK Pressed'), + style: 'cancel', + }, + ], + { + cancelable: true, // whether the alert can be dismissed by tapping outside of the alert box + onDismiss: () => console.log('Alert dismissed'), // a callback that gets called when the alert is dismissed + }, + ); + } + }; - return ( + return ( + - { - productList.map((product, index) => { - return ( handleRemove(product) - } - />}> - - - {product.name} - {`${product.price} USD`} - - ) - }) - } + {productList.map((product, index) => { + return ( + handleRemove(product)} + /> + }> + + + {product.name} + {`${product.price} USD`} + + + ); + })} -