diff --git a/Docs/RN_PurchaseConnector.md b/Docs/RN_PurchaseConnector.md index 7a401b51..2a1f2f9c 100644 --- a/Docs/RN_PurchaseConnector.md +++ b/Docs/RN_PurchaseConnector.md @@ -21,7 +21,7 @@ For more information please check the following pages: The Purchase Connector feature of the AppsFlyer SDK depends on specific libraries provided by Google and Apple for managing in-app purchases: - For Android, it depends on the [Google Play Billing Library](https://developer.android.com/google/play/billing/integrate) (Supported versions: 5.x.x - 7.x.x). -- For iOS, it depends on [StoreKit](https://developer.apple.com/documentation/storekit) (Supported versions: StoreKit1 and StoreKit2 (beta)). +- For iOS, it depends on [StoreKit](https://developer.apple.com/documentation/storekit) (Supported versions: StoreKit1 and StoreKit2). However, these dependencies aren't actively included with the SDK. This means that the responsibility of managing these dependencies and including the necessary libraries in your project falls on you as the consumer of the SDK. @@ -53,6 +53,19 @@ The files for the Purchase Validation feature are always included in the plugin. In such cases, you'll likely experience errors or exceptions when trying to use functionalities provided by the Purchase Validation feature. To avoid these issues, ensure that you opt-in to the feature if you intend to use any related APIs. + +## ProGuard Rules for Android + +If you are using ProGuard to obfuscate your APK for Android, you need to ensure that it doesn't interfere with the functionality of AppsFlyer SDK and its Purchase Connector feature. + +Add following keep rules to your `proguard-rules.pro` file: + +```groovy +-keep class com.appsflyer.** { *; } +-keep class kotlin.jvm.internal.Intrinsics{ *; } +-keep class kotlin.collections.**{ *; } +``` + ## Basic Integration Of The Connector ### Create PurchaseConnector Instance The `PurchaseConnector` requires a configuration object of type `PurchaseConnectorConfig` at instantiation time. This configuration object governs how the `PurchaseConnector` behaves in your application. @@ -225,6 +238,58 @@ const purchaseConnectorConfigSK2 = AppsFlyerPurchaseConnectorConfig.setConfig({ }); ``` +### Logging Consumable Transactions + +On iOS 15 and above, consumable in-app purchases are handled via StoreKit 2. The behavior depends on your iOS version: + +- **On iOS 18 and later:** + Apple introduced a new Info.plist flag: `SKIncludeConsumableInAppPurchaseHistory`. + - If you set `SKIncludeConsumableInAppPurchaseHistory` to `YES` in your Info.plist, automatic collection will happen. + - If the flag is not present or is set to `NO`, you must manually log consumable transactions as shown below. + +- **On iOS 15–17:** + Consumable purchases must always be logged manually. + +To manually log consumable transactions, use the `logConsumableTransaction` method after finishing the transaction: + +```javascript +import { Platform } from 'react-native'; +import { AppsFlyerPurchaseConnector } from 'react-native-appsflyer'; + +// Purchase update listener +purchaseUpdatedListener((purchase) => { + console.log("🛒 Purchase updated:", purchase.productId, "Transaction ID:", purchase.transactionId); + const isConsumable = consumablesItems.includes(purchase.productId); + + finishTransaction({ purchase, isConsumable }) + .then((res) => { + console.log("✅ finishTransaction success:", res); + console.log("🔍 Expecting AppsFlyer validation callback for:", purchase.productId); + + // Log consumable transaction for iOS + if (Platform.OS === 'ios' && isConsumable && purchase.transactionId) { + AppsFlyerPurchaseConnector.logConsumableTransaction(purchase.transactionId); + console.log("📝 Consumable transaction logged:", purchase.transactionId); + } + }) + .catch((error) => { + console.warn("❌ Error finishing transaction:", error); + }); +}); +``` + +### Method Signature + +```javascript +AppsFlyerPurchaseConnector.logConsumableTransaction(transactionId: string): void +``` + +**Parameters:** +- `transactionId` (string): The unique transaction identifier from the App Store transaction + +**Note:** This method is iOS-specific and should only be called on iOS devices. On Android, consumable transactions are automatically handled by the Purchase Connector. + + ## Register Validation Results Listeners You can register listeners to get the validation results once getting a response from AppsFlyer servers to let you know if the purchase was validated successfully.
@@ -304,37 +369,6 @@ const handleOnReceivePurchaseRevenueValidationInfo = (validationInfo, error) => }, []); ``` - -## Testing the Integration - -With the AppsFlyer SDK, you can select which environment will be used for validation - either **production** or **sandbox**. By default, the environment is set to production. However, while testing your app, you should use the sandbox environment. - -### Android - -For Android, testing your integration with the [Google Play Billing Library](https://developer.android.com/google/play/billing/test) should use the sandbox environment. - -To set the environment to sandbox in React Native, just set the `sandbox` parameter in the `PurchaseConnectorConfig` to `true` when instantiating `PurchaseConnector`. - -Remember to switch the environment back to production (set `sandbox` to `false`) before uploading your app to the Google Play Store. - -### iOS - -To test purchases in an iOS environment on a real device with a TestFlight sandbox account, you also need to set `sandbox` to `true`. - -> *IMPORTANT NOTE: Before releasing your app to production please be sure to set `sandbox` to `false`. If a production purchase event is sent in sandbox mode, your event will not be validated properly! * - -## ProGuard Rules for Android - -If you are using ProGuard to obfuscate your APK for Android, you need to ensure that it doesn't interfere with the functionality of AppsFlyer SDK and its Purchase Connector feature. - -Add following keep rules to your `proguard-rules.pro` file: - -```groovy --keep class com.appsflyer.** { *; } --keep class kotlin.jvm.internal.Intrinsics{ *; } --keep class kotlin.collections.**{ *; } -``` - ## Full Code Example ```javascript import appsFlyer, { @@ -535,59 +569,6 @@ const setupPurchaseDataSources = () => { }; ``` - -### Logging Consumable Transactions - -On iOS 15 and above, consumable in-app purchases are handled via StoreKit 2. The behavior depends on your iOS version: - -- **On iOS 18 and later:** - Apple introduced a new Info.plist flag: `SKIncludeConsumableInAppPurchaseHistory`. - - If you set `SKIncludeConsumableInAppPurchaseHistory` to `YES` in your Info.plist, automatic collection will happen. - - If the flag is not present or is set to `NO`, you must manually log consumable transactions as shown below. - -- **On iOS 15–17:** - Consumable purchases must always be logged manually. - -To manually log consumable transactions, use the `logConsumableTransaction` method after finishing the transaction: - -```javascript -import { Platform } from 'react-native'; -import { AppsFlyerPurchaseConnector } from 'react-native-appsflyer'; - -// Purchase update listener -purchaseUpdatedListener((purchase) => { - console.log("🛒 Purchase updated:", purchase.productId, "Transaction ID:", purchase.transactionId); - const isConsumable = consumablesItems.includes(purchase.productId); - - finishTransaction({ purchase, isConsumable }) - .then((res) => { - console.log("✅ finishTransaction success:", res); - console.log("🔍 Expecting AppsFlyer validation callback for:", purchase.productId); - - // Log consumable transaction for iOS - if (Platform.OS === 'ios' && isConsumable && purchase.transactionId) { - AppsFlyerPurchaseConnector.logConsumableTransaction(purchase.transactionId); - console.log("📝 Consumable transaction logged:", purchase.transactionId); - } - }) - .catch((error) => { - console.warn("❌ Error finishing transaction:", error); - }); -}); -``` - -### Method Signature - -```javascript -AppsFlyerPurchaseConnector.logConsumableTransaction(transactionId: string): void -``` - -**Parameters:** -- `transactionId` (string): The unique transaction identifier from the App Store transaction - -**Note:** This method is iOS-specific and should only be called on iOS devices. On Android, consumable transactions are automatically handled by the Purchase Connector. - - ### Important Notes 1. **iOS StoreKit2**: The StoreKit2 data source is only available on iOS 15.0 and later. Make sure to check the iOS version before using it. @@ -622,3 +603,21 @@ setupPurchaseDataSources(); // 3. Start observing transactions await AppsFlyerPurchaseConnector.startObservingTransactions(); ``` + +## Testing the Integration + +With the AppsFlyer SDK, you can select which environment will be used for validation - either **production** or **sandbox**. By default, the environment is set to production. However, while testing your app, you should use the sandbox environment. + +### Android + +For Android, testing your integration with the [Google Play Billing Library](https://developer.android.com/google/play/billing/test) should use the sandbox environment. + +To set the environment to sandbox in React Native, just set the `sandbox` parameter in the `PurchaseConnectorConfig` to `true` when instantiating `PurchaseConnector`. + +Remember to switch the environment back to production (set `sandbox` to `false`) before uploading your app to the Google Play Store. + +### iOS + +To test purchases in an iOS environment on a real device with a TestFlight sandbox account, you also need to set `sandbox` to `true`. + +> *IMPORTANT NOTE: Before releasing your app to production please be sure to set `sandbox` to `false`. If a production purchase event is sent in sandbox mode, your event will not be validated properly! *