diff --git a/.gitignore b/.gitignore index dbb0f6e0..fb6f0995 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ ios/Podfile.lock .idea .gradle local.properties +android/gradlew +android/gradlew.bat +android/gradle # node.js # diff --git a/CHANGELOG.md b/CHANGELOG.md index bcf39b7c..eae7850c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Versions +## 6.0.31 +- In-App purchase validation +- Add parameters type check to public api +- Fix crash on null callbacks +- Install Referrer v2.1 + ## 6.0.30 - iOS SDK 6.0.3 diff --git a/Docs/API.md b/Docs/API.md index 3ea3b7ef..c7efe53e 100755 --- a/Docs/API.md +++ b/Docs/API.md @@ -27,6 +27,7 @@ - [setSharingFilter](#setSharingFilter) - [disableCollectASA](#disableCollectASA) - [disableAdvertisingIdentifier](#disableAdvertisingIdentifier) +- [validateAndLogInAppPurchase](#validateAndLogInAppPurchase) --- @@ -737,4 +738,43 @@ Disables IDFA collecting appsFlyer.disableAdvertisingIdentifier(true); ``` ---- \ No newline at end of file +--- + +##### **`validateAndLogInAppPurchase(purchaseInfo, successC, errorC): Response`** +Receipt validation is a secure mechanism whereby the payment platform (e.g. Apple or Google) validates that an in-app purchase indeed occurred as reported.
+Learn more - https://support.appsflyer.com/hc/en-us/articles/207032106-Receipt-validation-for-in-app-purchases +Important! for iOS - set SandBox to ```true```
+```appsFlyer.setUseReceiptValidationSandbox(true);``` + + +| parameter | type | description | +| ---------- |----------|------------------ | +| purchaseInfo | json | In-App Purchase parameters | +| successC | function | success callback (generated link)| +| errorC | function | error callback | + + +*Example:* + +```javascript +let info = {}; +if (Platform.OS == 'android') { + info = { + publicKey: 'key', + currency: 'biz', + signature: 'sig', + purchaseData: 'data', + price: '123', + additionalParameters: {'foo': 'bar'}, + }; +} else if (Platform.OS == 'ios') { + info = { + productIdentifier: 'identifier', + currency: 'USD', + transactionId: '1000000614252747', + price: '0.99', + additionalParameters: {'foo': 'bar'}, + }; +} +appsFlyer.validateAndLogInAppPurchase(info, res => console.log(res), err => console.log(err)); +``` diff --git a/README.md b/README.md index a1144a91..1b08f250 100755 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ appsFlyer.initSdk( devKey: 'K2***********99', isDebug: false, appId: '41*****44', + onInstallConversionDataListener: true, }, (result) => { console.log(result); @@ -96,6 +97,7 @@ appsFlyer.initSdk( | devKey | Your application [devKey](https://support.appsflyer.com/hc/en-us/articles/211719806-Global-app-settings-#sdk-dev-key) provided by AppsFlyer (required) | | appId | Your iTunes [application ID](https://support.appsflyer.com/hc/en-us/articles/207377436-Adding-a-new-app#available-in-the-app-store-google-play-store-windows-phone-store) (iOS only) | | isDebug | Debug mode - set to `true` for testing only | +|onInstallConversionDataListener| Set listener for SDK init response (Optional. default=false) | ##
📖 Guides diff --git a/SampleApp/App.js b/SampleApp/App.js index 7aa7f3fd..323cd33f 100644 --- a/SampleApp/App.js +++ b/SampleApp/App.js @@ -10,289 +10,325 @@ import React, {Node} from 'react'; import appsFlyer from 'react-native-appsflyer'; import { - Button, - ImageBackground, - SafeAreaView, - ScrollView, - StatusBar, - StyleSheet, - Text, - View, + Button, + ImageBackground, + SafeAreaView, + ScrollView, + StatusBar, + StyleSheet, + Text, + View, } from 'react-native'; import { - Colors, - DebugInstructions, - LearnMoreLinks, - ReloadInstructions, + Colors, + DebugInstructions, + LearnMoreLinks, + ReloadInstructions, } from 'react-native/Libraries/NewAppScreen'; // eslint-disable-next-line no-unused-vars var onInstallConversionDataCanceller = appsFlyer.onInstallConversionData( - (res) => { - console.log('onInstallConversionData: ' + JSON.stringify(res)); - if (res.type === 'onInstallConversionSuccess') { - if (JSON.parse(res.data.is_first_launch) === true) { - if (res.data.af_status === 'Non-organic') { - var media_source = res.data.media_source; - var campaign = res.data.campaign; - console.log( - 'This is first launch and a Non-Organic install. Media source: ' + - media_source + - ' Campaign: ' + - campaign, - ); - } else if (res.data.af_status === 'Organic') { - console.log('This is first launch and a Organic Install'); + (res) => { + console.log('onInstallConversionData: ' + JSON.stringify(res)); + if (res.type === 'onInstallConversionSuccess') { + if (JSON.parse(res.data.is_first_launch) === true) { + if (res.data.af_status === 'Non-organic') { + var media_source = res.data.media_source; + var campaign = res.data.campaign; + console.log( + 'This is first launch and a Non-Organic install. Media source: ' + + media_source + + ' Campaign: ' + + campaign, + ); + } else if (res.data.af_status === 'Organic') { + console.log('This is first launch and a Organic Install'); + } + } else { + console.log('This is not first launch'); + } } - } else { - console.log('This is not first launch'); - } - } - }, + }, ); // eslint-disable-next-line no-unused-vars var onAppOpenAttributionCanceller = appsFlyer.onAppOpenAttribution((res) => { - console.log(res); + console.log(res); }); + appsFlyer.setCustomerUserId("testID"); appsFlyer.initSdk( - { - isDebug: true, - devKey: '4UGrDF4vFvPLbHq5bXtCza', - appId: '753258300', - timeToWaitForATTUserAuthorization: 60, - }, - (result) => { - console.log('initSdk: ' + result); - if (Platform.OS === 'android') { - appsFlyer.setCollectAndroidID(true) - } - }, - (error) => { - console.error('initSdk: ' + error); - }, + { + isDebug: true, + devKey: 'Us********ed', + appId: '7********1', + onInstallConversionDataListener: true, + timeToWaitForATTUserAuthorization: 10, + }, + (result) => { + console.log('initSdk: ' + result); + if (Platform.OS === 'android') { + appsFlyer.setCollectAndroidID(true) + } + }, + (error) => { + console.error('initSdk: ' + error); + }, ); const App: () => React$Node = () => { - const LogEventPressed = () => { - const eventName = 'af_test_event'; - const eventValues = { - af_event_param0: 'biz', - af_event_param1: 'buz', - af_event_param2: 'bizbuz', + const logEvent = () => { + const eventName = 'af_test_event'; + const eventValues = {'price': '123', 'amount': '5'}; + appsFlyer.logEvent( + eventName, + eventValues, + (result) => { + console.log('logEvent: ' + result); + }, + (error) => { + console.error('logEvent: ' + error); + }, + ); }; - appsFlyer.logEvent( - eventName, - eventValues, - (result) => { - console.log('logEvent: ' + result); - }, - (error) => { - console.error('logEvent: ' + error); - }, - ); - }; - const LogLocationPressed = () => { - appsFlyer.logLocation(32.0853, 34.781769, (result) => { - console.log('logLocation: ' + result); - }); - }; - const StopPressed = () => { - appsFlyer.stop(true, (res) => { - console.log('stop: ' + res); - }), - (err) => { - console.log('stop: ' + err); - }; - }; + let info = {}; + if (Platform.OS == 'android') { + info = { + publicKey: 'key', + currency: 'biz', + signature: 'sig', + purchaseData: 'data', + price: '123', + additionalParameters: {'foo': 'bar'}, + }; + } else if (Platform.OS == 'ios') { + info = { + productIdentifier: 'identifier', + currency: 'USD', + transactionId: '1000000614252747', + price: '0.99', + additionalParameters: {'foo': 'bar'}, + }; + } + appsFlyer.validateAndLogInAppPurchase(info, res => console.log(res), err => console.log(err)); - const LogCrossPromotion = () => { - appsFlyer.logCrossPromotionImpression('1192323960', 'test', { - custom_param: 'custom_value', - }); - }; + const init = () => { + appsFlyer.initSdk(option, result => console.log(result), error => console.log(error)); + }; - const logCrossPromotionAndOpenStore = () => { - appsFlyer.logCrossPromotionAndOpenStore('1192323960', 'test', { - custom_param: 'custom_value', - }); - }; + const LogLocationPressed = () => { + appsFlyer.logLocation(32.0853, 34.781769, (result) => { + console.log('logLocation: ' + result); + }); + }; - const anonymizeUser = () => { - appsFlyer.anonymizeUser(true, (res) => { - console.log('anonymizeUser: ' + res); - }); - }; + const StopPressed = () => { + appsFlyer.stop(true, (res) => { + console.log('stop: ' + res); + }), + (err) => { + console.log('stop: ' + err); + }; + }; - const Header = (): Node => ( - - - Welcome to the React Native AppsFlyer Test App! - - - ); + const LogCrossPromotion = () => { + appsFlyer.logCrossPromotionImpression('1192323960', 'test', { + custom_param: 'custom_value', + }); + }; - return ( - <> - - - -
- - Press to log event! -