From 3035b12c4e25740e233559d151353c1727a69583 Mon Sep 17 00:00:00 2001 From: Dan Burcaw <92536821+namidan@users.noreply.github.com> Date: Wed, 26 Jul 2023 09:24:02 -0600 Subject: [PATCH] Apple 3.1.0 with paywall action event (#223) --- .github/workflows/app_prod.yaml | 2 +- .../com/nami/reactlibrary/NamiBridgeModule.kt | 2 +- .../reactlibrary/NamiCampaignManagerBridge.kt | 4 + .../java/com/nami/reactlibrary/NamiUtil.kt | 2 + examples/Basic/App.tsx | 79 ++++++++++--------- examples/Basic/containers/CampaignScreen.tsx | 10 ++- examples/Basic/ios/StoreKitSTG.storekit | 18 +++-- examples/TestNamiTV/android/app/build.gradle | 18 ++++- examples/TestNamiTV/android/build.gradle | 1 - examples/TestNamiTV/config/index.ts | 38 ++++++++- examples/TestNamiTV/package.json | 19 ++--- ios/Nami.m | 2 +- ios/NamiCampaignManagerBridge.swift | 67 ++++++++-------- ios/NamiPurchaseManagerBridge.swift | 8 +- package.json | 2 +- react-native-nami-sdk.podspec | 2 +- src/NamiCampaignManager.d.ts | 26 ++++++ src/NamiCampaignManager.js | 8 +- src/NamiPaywallManager.d.ts | 3 + src/types.ts | 2 + 20 files changed, 208 insertions(+), 105 deletions(-) diff --git a/.github/workflows/app_prod.yaml b/.github/workflows/app_prod.yaml index 0600383e..a0a1f12a 100644 --- a/.github/workflows/app_prod.yaml +++ b/.github/workflows/app_prod.yaml @@ -254,7 +254,7 @@ jobs: pip3 install PyJWT echo "1.0" > $RUNNER_TEMP/.current_version export CURRENT_VERSION=`cat $RUNNER_TEMP/.current_version` - python3 get_next_build.py com.namiml.stg.testreactnative --prerelease --platform=TV_OS > $RUNNER_TEMP/.next_build_number + python3 get_next_build.py com.namiml.app.testreactnative --prerelease --platform=TV_OS > $RUNNER_TEMP/.next_build_number working-directory: appstoreconnect-build-tools env: APPSTORE_API_KEY_ID: "${{ secrets.APPSTORE_API_KEY_ID }}" diff --git a/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt b/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt index d50f803b..c02215a7 100644 --- a/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt +++ b/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt @@ -115,7 +115,7 @@ class NamiBridgeModule(reactContext: ReactApplicationContext) : } else { Arguments.createArray() } - val settingsList = mutableListOf("extendedClientInfo:react-native:3.0.23") + val settingsList = mutableListOf("extendedClientInfo:react-native:3.0.24") namiCommandsReact?.toArrayList()?.filterIsInstance()?.let { commandsFromReact -> settingsList.addAll(commandsFromReact) } diff --git a/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt b/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt index 49dfe447..3be0257e 100644 --- a/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt +++ b/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt @@ -29,6 +29,8 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) : const val CAMPAIGN_TYPE = "campaignType" const val CAMPAIGN_URL = "campaignUrl" const val PAYWALL_NAME = "paywallName" + const val COMPONENT_CHANGE_ID = "componentChangeId" + const val COMPONENT_CHANGE_NAME = "componentChangeName" const val SEGMENT_ID = "segmentId" const val EXTERNAL_SEGMENT_ID = "externalSegmentId" const val DEEP_LINK_URL = "deeplinkUrl" @@ -189,6 +191,8 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) : putString(CAMPAIGN_TYPE, campaignType ?: "") putString(CAMPAIGN_URL, campaignUrl ?: "") putString(PAYWALL_NAME, paywallName ?: "") + putString(COMPONENT_CHANGE_ID, "") + putString(COMPONENT_CHANGE_NAME, "") putString(SEGMENT_ID, segmentId ?: "") putString(EXTERNAL_SEGMENT_ID, externalSegmentId ?: "") putString(DEEP_LINK_URL, deeplinkUrl ?: "") diff --git a/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt b/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt index 847e3adb..7a67720d 100644 --- a/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt +++ b/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt @@ -79,6 +79,8 @@ fun NamiSKU.toSkuDict(): WritableMap { productDict.putString("skuId", this.skuId) productDict.putString("id", this.id) productDict.putString("type", this.type.toString()) + productDict.putString("promoId","") + productDict.putString("promoToken","") return productDict } diff --git a/examples/Basic/App.tsx b/examples/Basic/App.tsx index 62517413..cb82985b 100644 --- a/examples/Basic/App.tsx +++ b/examples/Basic/App.tsx @@ -48,51 +48,56 @@ const App = () => { }, []); useEffect(() => { - NamiPaywallManager.registerBuySkuHandler((sku) => { - console.log( - 'buy sku handler - need to start purchase flow for sku:', - sku.skuId, - ); + const subscriptionRemover = NamiPaywallManager.registerBuySkuHandler( + (sku) => { + console.log( + 'buy sku handler - need to start purchase flow for sku:', + sku.skuId, + sku.promoId, + ); - NamiPaywallManager.dismiss(true); + NamiPaywallManager.dismiss(true); - if (Platform.OS === 'ios' || Platform.isTVOS) { - NamiPaywallManager.buySkuCompleteApple({ - product: sku, - transactionID: '12345', - originalTransactionID: '12345', - originalPurchaseDate: 1684823428, - purchaseDate: 1684823428, - price: '120', - currencyCode: 'USD', - locale: 'US', - }); - } else if (Platform.OS === 'android') { - if (Platform.constants.Manufacturer === 'Amazon') { - NamiPaywallManager.buySkuCompleteAmazon({ + if (Platform.OS === 'ios' || Platform.isTVOS) { + NamiPaywallManager.buySkuCompleteApple({ product: sku, + transactionID: '12345', + originalTransactionID: '12345', + originalPurchaseDate: 1684823428, purchaseDate: 1684823428, - purchaseSource: 'CAMPAIGN', - receiptId: '12345', - localizedPrice: '120', - userId: '12345', - marketplace: '12345', - }); - } else { - NamiPaywallManager.buySkuCompleteGooglePlay({ - product: sku, - purchaseDate: 1684823428, - purchaseSource: 'CAMPAIGN', - purchaseToken: - 'jolbnkpmojnpnjecgmphbmkc.AO-J1OznE4AIzyUvKFe1RSVkxw4KEtv0WfyL_tkzozOqnlSvIPsyQJBphCN80gwIMaex4EMII95rFCZhMCbVPZDc-y_VVhQU5Ddua1dLn8zV7ms_tdwoDmE', - orderId: 'GPA.3317-0284-9993-42221', + price: '120', + currencyCode: 'USD', + locale: 'US', }); + } else if (Platform.OS === 'android') { + if (Platform.constants.Manufacturer === 'Amazon') { + NamiPaywallManager.buySkuCompleteAmazon({ + product: sku, + purchaseDate: 1684823428, + purchaseSource: 'CAMPAIGN', + receiptId: '12345', + localizedPrice: '120', + userId: '12345', + marketplace: '12345', + }); + } else { + NamiPaywallManager.buySkuCompleteGooglePlay({ + product: sku, + purchaseDate: 1684823428, + purchaseSource: 'CAMPAIGN', + purchaseToken: + 'jolbnkpmojnpnjecgmphbmkc.AO-J1OznE4AIzyUvKFe1RSVkxw4KEtv0WfyL_tkzozOqnlSvIPsyQJBphCN80gwIMaex4EMII95rFCZhMCbVPZDc-y_VVhQU5Ddua1dLn8zV7ms_tdwoDmE', + orderId: 'GPA.3317-0284-9993-42221', + }); + } } - } - }); + }, + ); NamiCustomerManager.setCustomerDataPlatformId('2135'); - return () => {}; + return () => { + subscriptionRemover(); + }; }, []); return ( diff --git a/examples/Basic/containers/CampaignScreen.tsx b/examples/Basic/containers/CampaignScreen.tsx index aa81e08e..508c59bc 100644 --- a/examples/Basic/containers/CampaignScreen.tsx +++ b/examples/Basic/containers/CampaignScreen.tsx @@ -115,15 +115,17 @@ const CampaignScreen: FC = ({navigation}) => { action, campaignId, paywallId, - campaignLabel, campaignName, campaignType, + campaignLabel, campaignUrl, + paywallName, segmentId, externalSegmentId, - paywallName, deeplinkUrl, skuId, + componentChangeId, + componentChangeName, purchaseError, purchases, ) => { @@ -131,15 +133,17 @@ const CampaignScreen: FC = ({navigation}) => { setAction(action); console.log('campaignId', campaignId); console.log('paywallId', paywallId); - console.log('campaignLabel', campaignLabel); console.log('campaignName', campaignName); console.log('campaignType', campaignType); + console.log('campaignLabel', campaignLabel); console.log('campaignUrl', campaignUrl); console.log('paywallName', paywallName); console.log('segmentId', segmentId); console.log('externalSegmentId', externalSegmentId); console.log('deeplinkUrl', deeplinkUrl); console.log('skuId', skuId); + console.log('componentChangeId', componentChangeId); + console.log('componentChangeName', componentChangeName); console.log('purchaseError', purchaseError); console.log('purchases', purchases); }, diff --git a/examples/Basic/ios/StoreKitSTG.storekit b/examples/Basic/ios/StoreKitSTG.storekit index abf33baf..3f9f6fdd 100644 --- a/examples/Basic/ios/StoreKitSTG.storekit +++ b/examples/Basic/ios/StoreKitSTG.storekit @@ -9,7 +9,7 @@ "settings" : { "_applicationInternalID" : "6443910111", "_developerTeamID" : "K6APTMK8Y8", - "_lastSynchronizedDate" : 706849380.87510896 + "_lastSynchronizedDate" : 712074466.26017404 }, "subscriptionGroups" : [ { @@ -21,7 +21,15 @@ "subscriptions" : [ { "adHocOffers" : [ - + { + "displayPrice" : "4.99", + "internalID" : "FD31BD5B", + "numberOfPeriods" : 1, + "offerID" : "plus_annual_promo_1", + "paymentMode" : "payAsYouGo", + "referenceName" : "Plus Annual Promo", + "subscriptionPeriod" : "P1Y" + } ], "codeOffers" : [ @@ -81,7 +89,7 @@ "groupNumber" : 2, "internalID" : "6447770869", "introductoryOffer" : { - "internalID" : "E5F54037", + "internalID" : "832A850B", "numberOfPeriods" : 1, "paymentMode" : "free", "subscriptionPeriod" : "P3D" @@ -111,7 +119,7 @@ "groupNumber" : 1, "internalID" : "6447770794", "introductoryOffer" : { - "internalID" : "6574C3D4", + "internalID" : "7985E305", "numberOfPeriods" : 1, "paymentMode" : "free", "subscriptionPeriod" : "P1W" @@ -166,7 +174,7 @@ "groupNumber" : 1, "internalID" : "6447770843", "introductoryOffer" : { - "internalID" : "B9B4646C", + "internalID" : "B3B76E7C", "numberOfPeriods" : 1, "paymentMode" : "free", "subscriptionPeriod" : "P3D" diff --git a/examples/TestNamiTV/android/app/build.gradle b/examples/TestNamiTV/android/app/build.gradle index 1677e14d..eed31459 100644 --- a/examples/TestNamiTV/android/app/build.gradle +++ b/examples/TestNamiTV/android/app/build.gradle @@ -137,7 +137,7 @@ android { manifestPlaceholders.app_icon_round = "@mipmap/ic_launcher_round" manifestPlaceholders.app_icon = "@mipmap/ic_launcher" } - flavorDimensions "default" + flavorDimensions "default", "store" productFlavors { production { applicationId "com.namiml.testreact.prod" @@ -196,6 +196,22 @@ android { proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } + + productFlavors { + amazon { + dimension "store" + repositories { + maven { url "https://packages.namiml.com/NamiSDK/Amazon/"} + } + } + play { + dimension "store" + repositories { + maven { url "https://packages.namiml.com/NamiSDK/Android/"} + } + } + } + // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> diff --git a/examples/TestNamiTV/android/build.gradle b/examples/TestNamiTV/android/build.gradle index 41abd392..e251fb35 100644 --- a/examples/TestNamiTV/android/build.gradle +++ b/examples/TestNamiTV/android/build.gradle @@ -46,6 +46,5 @@ allprojects { google() jcenter() maven { url 'https://jitpack.io' } - maven { url("https://packages.namiml.com/NamiSDK/Android/") } } } diff --git a/examples/TestNamiTV/config/index.ts b/examples/TestNamiTV/config/index.ts index f8fe0e93..ba917377 100644 --- a/examples/TestNamiTV/config/index.ts +++ b/examples/TestNamiTV/config/index.ts @@ -8,8 +8,40 @@ export function getConfigObject() { switch (flavor) { case 'staging': return { - 'appPlatformID-apple': 'APPLE_STG_APP_PLATFORM_ID', - 'appPlatformID-android': 'ANDROID_STG_APP_PLATFORM_ID', + 'appPlatformID-apple': 'APPLE_STAGE_APP_PLATFORM_ID', + 'appPlatformID-android': 'UNUSED', + logLevel: 'DEBUG', + namiCommands: ['useStagingAPI'], + initialConfig: getInitialConfig(), + }; + case 'stagingAmazon': + return { + 'appPlatformID-apple': 'UNUSED', + 'appPlatformID-android': 'AMAZON_STAGE_APP_PLATFORM_ID', + logLevel: 'DEBUG', + namiCommands: ['useStagingAPI'], + initialConfig: getInitialConfig(), + }; + case 'stagingGoogle': + return { + 'appPlatformID-apple': 'UNUSED', + 'appPlatformID-android': 'GOOGLE_PROD_APP_PLATFORM_ID', + logLevel: 'DEBUG', + namiCommands: ['useStagingAPI'], + initialConfig: getInitialConfig(), + }; + case 'productionAmazon': + return { + 'appPlatformID-apple': 'UNUSED', + 'appPlatformID-android': 'AMAZON_PROD_APP_PLATFORM_ID', + logLevel: 'DEBUG', + namiCommands: ['useStagingAPI'], + initialConfig: getInitialConfig(), + }; + case 'productionGoogle': + return { + 'appPlatformID-apple': 'UNUSED', + 'appPlatformID-android': 'GOOGLE_PROD_APP_PLATFORM_ID', logLevel: 'DEBUG', namiCommands: ['useStagingAPI'], initialConfig: getInitialConfig(), @@ -17,7 +49,7 @@ export function getConfigObject() { default: return { 'appPlatformID-apple': 'APPLE_PROD_APP_PLATFORM_ID', - 'appPlatformID-android': 'ANDROID_PROD_APP_PLATFORM_ID', + 'appPlatformID-android': 'GOOGLE_PROD_APP_PLATFORM_ID', logLevel: 'DEBUG', initialConfig: getInitialConfig(), }; diff --git a/examples/TestNamiTV/package.json b/examples/TestNamiTV/package.json index 8dc29bfe..fd381920 100644 --- a/examples/TestNamiTV/package.json +++ b/examples/TestNamiTV/package.json @@ -14,17 +14,17 @@ "lint": "eslint . --ext .js,.jsx,.ts,.tsx" }, "dependencies": { + "@react-native-community/cli-platform-android": "^11.3.1", "@react-native-community/masked-view": "^0.1.11", "@react-navigation/bottom-tabs": "^6.5.7", "@react-navigation/native": "^6.1.6", "@react-navigation/native-stack": "^6.9.12", - "react": "^18.0.0", + "react": "18.0.0", "react-native": "npm:react-native-tvos@0.69.8-2", "react-native-nami-sdk": "file:../../", - "react-native-reanimated": "^3.0.1", - "react-native-safe-area-context": "^4.5.3", - "react-native-screens": "^3.20.0", - "react-native-theoplayer": "2.8.0" + "react-native-reanimated": "^2.3.1", + "react-native-safe-area-context": "^3.3.2", + "react-native-screens": "^3.20.0" }, "devDependencies": { "@babel/core": "^7.16.5", @@ -33,19 +33,20 @@ "@tsconfig/react-native": "^2.0.3", "@types/jest": "^29.5.0", "@types/react": "^18.0.31", - "@types/react-native": "^0.63.18", + "@types/react-native": "^0.71.5", "@types/react-test-renderer": "^18.0.0", "@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/parser": "^5.57.1", "babel-jest": "^27.4.5", + "detox": "^20.9.1", "eslint": "^8.37.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-native": "^4.0.0", - "jest": "^27.4.5", - "metro-react-native-babel-preset": "^0.76.5", + "jest": "^29.5.0", + "metro-react-native-babel-preset": "^0.66.2", "prettier": "^2.8.7", "react-native-codegen": "^0.0.12", - "react-test-renderer": "^18.2.0", + "react-test-renderer": "17.0.2", "typescript": "^5.0.2" }, "jest": { diff --git a/ios/Nami.m b/ios/Nami.m index b78376f3..81a88cdc 100644 --- a/ios/Nami.m +++ b/ios/Nami.m @@ -52,7 +52,7 @@ @implementation NamiBridge (RCTExternModule) } // Start commands with header iformation for Nami to let them know this is a React client. - NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.0.23"]]; + NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.0.24"]]; // Add additional namiCommands app may have sent in. NSObject *appCommandStrings = configDict[@"namiCommands"]; diff --git a/ios/NamiCampaignManagerBridge.swift b/ios/NamiCampaignManagerBridge.swift index d3b1f70a..3485e48b 100644 --- a/ios/NamiCampaignManagerBridge.swift +++ b/ios/NamiCampaignManagerBridge.swift @@ -43,23 +43,10 @@ class RNNamiCampaignManager: RCTEventEmitter { } func handlePaywallAction( - campaignId: String?, - campaignName: String?, - campaignType: String?, - campaignLabel: String?, - campaignUrl: String?, - paywallId: String?, - paywallName: String?, - segmentId: String?, - externalSegmentId: String?, - action: NamiApple.NamiPaywallAction, - sku: NamiApple.NamiSKU?, - purchaseError: Error?, - purchases: [NamiApple.NamiPurchase], - deeplinkUrl: String? + paywallEvent: NamiPaywallEvent ) { - let actionString: String - switch action { + var actionString: String + switch paywallEvent.action { case .show_paywall: actionString = "SHOW_PAYWALL" case .close_paywall: @@ -86,29 +73,37 @@ class RNNamiCampaignManager: RCTEventEmitter { actionString = "PURCHASE_UNKNOWN" case .deeplink: actionString = "DEEPLINK" + case .toggle_change: + actionString = "TOGGLE_CHANGE" + case .page_change: + actionString = "PAGE_CHANGE" + case .slide_change: + actionString = "SLIDE_CHANGE" + @unknown default: actionString = "PURCHASE_UNKNOWN" } - let skuId = sku?.skuId - let errorSting = purchaseError?.localizedDescription + let errorSting = paywallEvent.purchaseError?.localizedDescription - let dictionaries = purchases.map { purchase in RNNamiPurchaseManager.purchaseToPurchaseDict(purchase) } + let dictionaries = paywallEvent.purchases.map { purchase in RNNamiPurchaseManager.purchaseToPurchaseDict(purchase) } let payload: [String: Any?] = [ - "campaignId": campaignId, - "campaignName": campaignName, - "campaignType": campaignType, - "campaignLabel": campaignLabel, - "campaignUrl": campaignUrl, - "paywallId": paywallId, - "paywallName": paywallName, - "segmentId": segmentId, - "externalSegmentId": externalSegmentId, + "campaignId": paywallEvent.campaignId, + "campaignName": paywallEvent.campaignName, + "campaignType": paywallEvent.campaignType, + "campaignLabel": paywallEvent.campaignLabel, + "campaignUrl": paywallEvent.campaignUrl, + "paywallId": paywallEvent.paywallId, + "paywallName": paywallEvent.paywallName, + "segmentId": paywallEvent.segmentId, + "externalSegmentId": paywallEvent.externalSegmentId, "action": actionString, - "skuId": skuId, + "skuId": paywallEvent.sku?.id, "purchaseError": errorSting, "purchases": dictionaries, - "deeplinkUrl": deeplinkUrl, + "deeplinkUrl": paywallEvent.deeplinkUrl, + "componentChangeId": paywallEvent.componentChange?.id, + "componentChangeName": paywallEvent.componentChange?.name, ] RNNamiCampaignManager.shared?.sendEvent(withName: "ResultCampaign", body: payload) @@ -156,8 +151,8 @@ class RNNamiCampaignManager: RCTEventEmitter { error: error ) }, - paywallActionHandler: { campaignId, campaignName, campaignType, campaignLabel, campaignUrl, paywallId, paywallName, segmentId, externalSegmentId, _, action, sku, purchaseError, purchases, deeplinkUrl in - self.handlePaywallAction(campaignId: campaignId, campaignName: campaignName, campaignType: campaignType, campaignLabel: campaignLabel, campaignUrl: campaignUrl, paywallId: paywallId, paywallName: paywallName, segmentId: segmentId, externalSegmentId: externalSegmentId, action: action, sku: sku, purchaseError: purchaseError, purchases: purchases, deeplinkUrl: deeplinkUrl) + paywallActionHandler: { paywallEvent in + self.handlePaywallAction(paywallEvent: paywallEvent) }) } } else if let label = label { @@ -170,8 +165,8 @@ class RNNamiCampaignManager: RCTEventEmitter { error: error ) }, - paywallActionHandler: { campaignId, campaignName, campaignType, campaignLabel, campaignUrl, paywallId, paywallName, segmentId, externalSegmentId, _, action, sku, purchaseError, purchases, deeplinkUrl in - self.handlePaywallAction(campaignId: campaignId, campaignName: campaignName, campaignType: campaignType, campaignLabel: campaignLabel, campaignUrl: campaignUrl, paywallId: paywallId, paywallName: paywallName, segmentId: segmentId, externalSegmentId: externalSegmentId, action: action, sku: sku, purchaseError: purchaseError, purchases: purchases, deeplinkUrl: deeplinkUrl) + paywallActionHandler: { paywallEvent in + self.handlePaywallAction(paywallEvent: paywallEvent) }) } } else { @@ -185,8 +180,8 @@ class RNNamiCampaignManager: RCTEventEmitter { error: error ) }, - paywallActionHandler: { campaignId, campaignName, campaignType, campaignLabel, campaignUrl, paywallId, paywallName, segmentId, externalSegmentId, _, action, sku, purchaseError, purchases, deeplinkUrl in - self.handlePaywallAction(campaignId: campaignId, campaignName: campaignName, campaignType: campaignType, campaignLabel: campaignLabel, campaignUrl: campaignUrl, paywallId: paywallId, paywallName: paywallName, segmentId: segmentId, externalSegmentId: externalSegmentId, action: action, sku: sku, purchaseError: purchaseError, purchases: purchases, deeplinkUrl: deeplinkUrl) + paywallActionHandler: { paywallEvent in + self.handlePaywallAction(paywallEvent: paywallEvent) }) } } diff --git a/ios/NamiPurchaseManagerBridge.swift b/ios/NamiPurchaseManagerBridge.swift index fc414400..71db940d 100644 --- a/ios/NamiPurchaseManagerBridge.swift +++ b/ios/NamiPurchaseManagerBridge.swift @@ -26,8 +26,8 @@ class RNNamiPurchaseManager: RCTEventEmitter { let productDict: [String: Any?] = [ "localizedTitle": product.localizedTitle, "localizedDescription": product.localizedDescription, - "localizedPrice": product.localizedPrice, - "localizedMultipliedPrice": product.localizedMultipliedPrice, + "localizedPrice": product.price, + "localizedMultipliedPrice": "", "price": product.price.stringValue, "priceLanguage": product.priceLocale.languageCode, "priceCurrency": product.priceLocale.currencyCode, @@ -37,7 +37,7 @@ class RNNamiPurchaseManager: RCTEventEmitter { static func skuToSKUDict(_ sku: NamiSKU) -> NSDictionary { var productDict: NSDictionary? - if let product = sku.product { + if let product = sku.product as? SKProduct { productDict = productToDict(product) } @@ -58,6 +58,8 @@ class RNNamiPurchaseManager: RCTEventEmitter { "skuId": sku.skuId, "type": typeString, "appleProduct": productDict, + "promoId": sku.promoId, + "promoToken": "", ] return NSDictionary(dictionary: skuDict.compactMapValues { $0 }) diff --git a/package.json b/package.json index 978c4a01..2376677d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-nami-sdk", - "version": "3.0.23", + "version": "3.0.24", "description": "React Native Module for Nami - Easy subscriptions & in-app purchases, with powerful built-in paywalls and A/B testing.", "main": "index.js", "scripts": { diff --git a/react-native-nami-sdk.podspec b/react-native-nami-sdk.podspec index 46370a96..97f304eb 100644 --- a/react-native-nami-sdk.podspec +++ b/react-native-nami-sdk.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.source_files = "ios/**/*.{h,m,swift}" s.requires_arc = true - s.dependency 'Nami', '3.0.25' + s.dependency 'Nami', '3.1.0' s.dependency 'React' end diff --git a/src/NamiCampaignManager.d.ts b/src/NamiCampaignManager.d.ts index ea2deff6..83f5be6f 100644 --- a/src/NamiCampaignManager.d.ts +++ b/src/NamiCampaignManager.d.ts @@ -1,6 +1,7 @@ import { EmitterSubscription } from "react-native"; import { NamiPurchase } from "./NamiPurchaseManager"; import { NamiPaywallAction } from "./NamiPaywallManager"; +import { NamiSKU } from "./types"; export const NamiCampaignManager: { allCampaigns: () => Promise>; @@ -23,6 +24,8 @@ export const NamiCampaignManager: { externalSegmentId?: string, deeplinkUrl?: string, skuId?: string, + componentChangeId?: string, + componentChangeName?: string, purchaseError?: string, purchases?: NamiPurchase[] ) => void @@ -72,3 +75,26 @@ export type PaywallLaunchContext = { [key: string]: string; }; }; + +export type NamiPaywallEvent = { + action: NamiPaywallAction; + campaignId?: string; + campaignName?: string; + campaignType?: string; + campaignLabel?: string; + campaignUrl?: string; + paywallId?: string; + paywallName?: string; + componentChange?: NamiPaywallComponentChange; + segmentId?: string; + externalSegmentId?: string; + deeplinkUrl?: string; + sku?: NamiSKU; + purchaseError?: string; + purchases?: NamiPurchase[]; +}; + +export type NamiPaywallComponentChange = { + id?: string; + name?: string; +}; diff --git a/src/NamiCampaignManager.js b/src/NamiCampaignManager.js index 1a36aa05..d5df6628 100644 --- a/src/NamiCampaignManager.js +++ b/src/NamiCampaignManager.js @@ -19,15 +19,17 @@ export const NamiCampaignManager = { action, campaignId, paywallId, - campaignLabel, campaignName, campaignType, + campaignLabel, campaignUrl, paywallName, segmentId, externalSegmentId, deeplinkUrl, skuId, + componentChangeId, + componentChangeName, purchaseError, purchases } = body; @@ -35,15 +37,17 @@ export const NamiCampaignManager = { action, campaignId, paywallId, - campaignLabel, campaignName, campaignType, + campaignLabel, campaignUrl, paywallName, segmentId, externalSegmentId, deeplinkUrl, skuId, + componentChangeId, + componentChangeName, purchaseError, purchases, ); diff --git a/src/NamiPaywallManager.d.ts b/src/NamiPaywallManager.d.ts index 48710f49..2e80bdf9 100644 --- a/src/NamiPaywallManager.d.ts +++ b/src/NamiPaywallManager.d.ts @@ -66,4 +66,7 @@ export enum NamiPaywallAction { PURCHASE_UNKNOWN = "PURCHASE_UNKNOWN", PURCHASE_DEFERRED = "PURCHASE_DEFERRED", DEEPLINK = "DEEPLINK", + TOGGLE_CHANGE = "TOGGLE_CHANGE", + PAGE_CHANGE = "PAGE_CHANGE", + SLIDE_CHANGE = "SLIDE_CHANGE" } diff --git a/src/types.ts b/src/types.ts index ab4fdf12..375608b0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,6 +6,8 @@ export type NamiSKU = { googleProduct?: GoogleProduct; amazonProduct?: AmazonProduct; type: NamiSKUType; + promoId?: string; + promoToken?: string; }; export enum NamiPurchaseState {