react-native-nami-sdk 3.0.9 → 3.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.eslintrc.js +12 -0
- package/.github/workflows/CI.yaml +610 -0
- package/.github/workflows/app_prod.yaml +316 -0
- package/.github/workflows/app_stg.yaml +114 -1
- package/.pre-commit-config.yaml +0 -1
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt +5 -18
- package/android/src/main/java/com/nami/reactlibrary/NamiBridgePackage.java +0 -1
- package/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt +45 -27
- package/android/src/main/java/com/nami/reactlibrary/NamiCustomerManagerBridge.kt +26 -20
- package/android/src/main/java/com/nami/reactlibrary/NamiEntitlementManagerBridgeModule.kt +15 -12
- package/android/src/main/java/com/nami/reactlibrary/NamiMLManagerBridgeModule.kt +8 -0
- package/android/src/main/java/com/nami/reactlibrary/NamiPaywallManagerBridgeModule.kt +142 -95
- package/android/src/main/java/com/nami/reactlibrary/NamiPurchaseManagerBridge.kt +12 -14
- package/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt +3 -47
- package/ios/Nami.m +3 -25
- package/ios/NamiCampaignManagerBridge.swift +13 -7
- package/ios/NamiCustomerManager.swift +26 -7
- package/ios/NamiEntitlementManagerBridge.swift +9 -1
- package/ios/NamiMLManagerBridge.m +0 -2
- package/ios/NamiPaywallManagerBridge.m +2 -59
- package/ios/NamiPaywallManagerBridge.swift +67 -58
- package/ios/NamiPurchaseManagerBridge.m +2 -98
- package/ios/NamiPurchaseManagerBridge.swift +45 -5
- package/ios/RNNami-Bridging-Header.h +0 -1
- package/ios/RNNami.xcodeproj/project.pbxproj +1 -62
- package/ios/RNNami.xcworkspace/contents.xcworkspacedata +0 -3
- package/package.json +14 -4
- package/react-native-nami-sdk.podspec +4 -2
- package/src/Nami.d.ts +0 -1
- package/src/NamiCustomerManager.js +2 -2
- package/src/NamiMLManager.d.ts +3 -3
- package/src/NamiMLManager.js +1 -1
- package/src/NamiPaywallManager.d.ts +11 -30
- package/src/NamiPaywallManager.js +13 -8
- package/src/NamiPurchaseManager.d.ts +7 -3
- package/src/types.ts +10 -3
- package/android/src/main/java/com/nami/reactlibrary/NamiEmitter.kt +0 -163
- package/ios/NamiBridgeUtil.h +0 -32
- package/ios/NamiBridgeUtil.m +0 -231
- package/ios/NamiEmitter.m +0 -350
- package/ios/Podfile +0 -71
|
@@ -4,7 +4,6 @@ import android.util.Log
|
|
|
4
4
|
import com.facebook.react.bridge.*
|
|
5
5
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
6
6
|
import com.namiml.billing.NamiPurchaseManager
|
|
7
|
-
import com.namiml.paywall.NamiPaywallManager
|
|
8
7
|
|
|
9
8
|
class NamiPurchaseManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
10
9
|
ReactContextBaseJavaModule(reactContext) {
|
|
@@ -13,13 +12,6 @@ class NamiPurchaseManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
13
12
|
return "RNNamiPurchaseManager"
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
@ReactMethod
|
|
17
|
-
fun clearBypassStorePurchases() {
|
|
18
|
-
reactApplicationContext.runOnUiQueueThread {
|
|
19
|
-
NamiPurchaseManager.clearBypassStorePurchases()
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
15
|
@ReactMethod
|
|
24
16
|
fun purchases(resultsCallback: Callback) {
|
|
25
17
|
reactApplicationContext.runOnUiQueueThread {
|
|
@@ -76,7 +68,7 @@ class NamiPurchaseManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
76
68
|
putBoolean("success", false)
|
|
77
69
|
putString(
|
|
78
70
|
"error",
|
|
79
|
-
"Google Play
|
|
71
|
+
"Google Play or Amazon Appstore on Android devices do not provide an API method to restore purchases.",
|
|
80
72
|
)
|
|
81
73
|
}
|
|
82
74
|
resultsCallback.invoke(resultMap)
|
|
@@ -84,7 +76,7 @@ class NamiPurchaseManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
84
76
|
|
|
85
77
|
@ReactMethod
|
|
86
78
|
fun registerPurchasesChangedHandler() {
|
|
87
|
-
NamiPurchaseManager.registerPurchasesChangedHandler{purchases, purchaseState, error ->
|
|
79
|
+
NamiPurchaseManager.registerPurchasesChangedHandler { purchases, purchaseState, error ->
|
|
88
80
|
run {
|
|
89
81
|
val resultPurchases: WritableArray = WritableNativeArray()
|
|
90
82
|
|
|
@@ -100,11 +92,17 @@ class NamiPurchaseManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
100
92
|
payload.putString("error", error)
|
|
101
93
|
|
|
102
94
|
reactApplicationContext
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
96
|
+
.emit("PurchasesChanged", payload)
|
|
107
97
|
}
|
|
108
98
|
}
|
|
109
99
|
}
|
|
100
|
+
|
|
101
|
+
@ReactMethod
|
|
102
|
+
fun addListener(eventName: String?) {
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@ReactMethod
|
|
106
|
+
fun removeListeners(count: Int?) {
|
|
107
|
+
}
|
|
110
108
|
}
|
|
@@ -9,21 +9,13 @@ import com.facebook.react.bridge.WritableNativeMap
|
|
|
9
9
|
import com.namiml.billing.NamiPurchase
|
|
10
10
|
import com.namiml.customer.CustomerJourneyState
|
|
11
11
|
import com.namiml.entitlement.NamiEntitlement
|
|
12
|
-
import com.namiml.paywall.LegalCitations
|
|
13
|
-
import com.namiml.paywall.NamiLocaleConfig
|
|
14
|
-
import com.namiml.paywall.NamiPaywall
|
|
15
|
-
import com.namiml.paywall.NamiPurchaseSource
|
|
16
12
|
import com.namiml.paywall.NamiSKU
|
|
17
|
-
import com.namiml.paywall.SubscriptionPeriod
|
|
18
|
-
import com.namiml.util.extensions.getFormattedPrice
|
|
19
|
-
import com.namiml.util.extensions.getSubscriptionPeriodEnum
|
|
20
13
|
import java.text.DateFormat
|
|
21
14
|
import java.text.SimpleDateFormat
|
|
22
15
|
import java.util.Date
|
|
23
16
|
import java.util.Locale
|
|
24
17
|
import java.util.TimeZone
|
|
25
18
|
|
|
26
|
-
|
|
27
19
|
fun List<*>.toWritableArray(): WritableArray {
|
|
28
20
|
val convertedArray = Arguments.createArray()
|
|
29
21
|
for (value in this) {
|
|
@@ -84,45 +76,9 @@ fun Map<*, *>.toWritableMap(): WritableMap {
|
|
|
84
76
|
fun NamiSKU.toSkuDict(): WritableMap {
|
|
85
77
|
val productDict = Arguments.createMap()
|
|
86
78
|
|
|
87
|
-
productDict.putString("
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// productDict.putString("localizedPrice", skuDetails.price)
|
|
91
|
-
// productDict.putString("localizedMultipliedPrice", skuDetails.price)
|
|
92
|
-
productDict.putBoolean("featured", featured)
|
|
93
|
-
// productDict.putString("displayText", displayText)
|
|
94
|
-
// productDict.putString("displaySubText", displaySubText)
|
|
95
|
-
// productDict.putString("price", skuDetails.getFormattedPrice().toString())
|
|
96
|
-
productDict.putString("priceLanguage", Locale.getDefault().language)
|
|
97
|
-
productDict.putString("priceCountry", Locale.getDefault().country)
|
|
98
|
-
// productDict.putString("priceCurrency", skuDetails.priceCurrencyCode)
|
|
99
|
-
productDict.putString("numberOfUnits", "1")
|
|
100
|
-
// val subscriptionPeriod = when (skuDetails.getSubscriptionPeriodEnum()) {
|
|
101
|
-
// SubscriptionPeriod.MONTHLY -> {
|
|
102
|
-
// "month"
|
|
103
|
-
// }
|
|
104
|
-
// SubscriptionPeriod.HALF_YEAR -> {
|
|
105
|
-
// "half_year"
|
|
106
|
-
// }
|
|
107
|
-
// SubscriptionPeriod.WEEKLY -> {
|
|
108
|
-
// "week"
|
|
109
|
-
// }
|
|
110
|
-
// SubscriptionPeriod.QUARTERLY -> {
|
|
111
|
-
// "quarter"
|
|
112
|
-
// }
|
|
113
|
-
// SubscriptionPeriod.ANNUAL -> {
|
|
114
|
-
// "year"
|
|
115
|
-
// }
|
|
116
|
-
// SubscriptionPeriod.FOUR_WEEKS -> {
|
|
117
|
-
// "four_weeks"
|
|
118
|
-
// }
|
|
119
|
-
// else -> {
|
|
120
|
-
// null
|
|
121
|
-
// }
|
|
122
|
-
// }
|
|
123
|
-
// if (subscriptionPeriod != null) {
|
|
124
|
-
// productDict.putString("periodUnit", subscriptionPeriod)
|
|
125
|
-
// }
|
|
79
|
+
productDict.putString("skuId", this.skuId)
|
|
80
|
+
productDict.putString("id", this.id)
|
|
81
|
+
productDict.putString("type", this.type.toString())
|
|
126
82
|
|
|
127
83
|
return productDict
|
|
128
84
|
}
|
package/ios/Nami.m
CHANGED
|
@@ -51,23 +51,8 @@ RCT_EXPORT_METHOD(configure: (NSDictionary *)configDict completion: (RCTResponse
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
NSObject *bypassString = configDict[@"bypassStore"];
|
|
55
|
-
if ( bypassString != NULL )
|
|
56
|
-
{
|
|
57
|
-
NSLog(@"bypassStore from dictionary is %@", configDict[@"bypassStore"]);
|
|
58
|
-
if ([bypassString isKindOfClass:[NSNumber class]]) {
|
|
59
|
-
config.bypassStore = [((NSNumber *)bypassString) boolValue];
|
|
60
|
-
} else if ([bypassString isKindOfClass:[NSString class]] ) {
|
|
61
|
-
if ([[((NSString *)bypassString) lowercaseString] hasPrefix:@"t"] )
|
|
62
|
-
{
|
|
63
|
-
// bypass is false by default, so we only worry about checking for enabling bypass
|
|
64
|
-
config.bypassStore = true;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
54
|
// Start commands with header iformation for Nami to let them know this is a React client.
|
|
70
|
-
NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.0.
|
|
55
|
+
NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.0.10"]];
|
|
71
56
|
|
|
72
57
|
// Add additional namiCommands app may have sent in.
|
|
73
58
|
NSObject *appCommandStrings = configDict[@"namiCommands"];
|
|
@@ -91,10 +76,6 @@ RCT_EXPORT_METHOD(configure: (NSDictionary *)configDict completion: (RCTResponse
|
|
|
91
76
|
}
|
|
92
77
|
}
|
|
93
78
|
|
|
94
|
-
RCT_EXPORT_METHOD(performNamiCommand: (NSString *)command) {
|
|
95
|
-
[NamiCommand performCommand:command];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
79
|
@end
|
|
99
80
|
|
|
100
81
|
@implementation NamiBridge
|
|
@@ -102,13 +83,10 @@ RCT_EXPORT_MODULE_NO_LOAD(NamiBridge, NamiBridge)
|
|
|
102
83
|
|
|
103
84
|
- (dispatch_queue_t)methodQueue
|
|
104
85
|
{
|
|
105
|
-
|
|
86
|
+
return dispatch_get_main_queue();
|
|
106
87
|
}
|
|
107
88
|
|
|
108
89
|
+ (BOOL)requiresMainQueueSetup {
|
|
109
|
-
|
|
90
|
+
return YES;
|
|
110
91
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
92
|
@end
|
|
@@ -11,8 +11,15 @@ import React
|
|
|
11
11
|
|
|
12
12
|
@objc(RNNamiCampaignManager)
|
|
13
13
|
class RNNamiCampaignManager: RCTEventEmitter {
|
|
14
|
+
public static var shared: RNNamiCampaignManager?
|
|
15
|
+
|
|
16
|
+
override init() {
|
|
17
|
+
super.init()
|
|
18
|
+
RNNamiCampaignManager.shared = self
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
override func supportedEvents() -> [String]! {
|
|
15
|
-
|
|
22
|
+
return ["AvailableCampaignsChanged", "ResultCampaign"]
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
private func campaignInToDictionary(_ campaign: NamiCampaign) -> NSDictionary {
|
|
@@ -58,14 +65,13 @@ class RNNamiCampaignManager: RCTEventEmitter {
|
|
|
58
65
|
actionString = "PURCHASE_CANCELLED"
|
|
59
66
|
case .purchase_unknown:
|
|
60
67
|
actionString = "PURCHASE_UNKNOWN"
|
|
61
|
-
case .show_paywall:
|
|
62
|
-
actionString = "SHOW_PAYWALL"
|
|
63
68
|
@unknown default:
|
|
64
69
|
actionString = "PURCHASE_UNKNOWN"
|
|
65
70
|
}
|
|
66
71
|
let skuId = sku?.skuId
|
|
67
72
|
let errorSting = purchaseError?.localizedDescription
|
|
68
|
-
|
|
73
|
+
|
|
74
|
+
let dictionaries = purchases.map { purchase in RNNamiPurchaseManager.purchaseToPurchaseDict(purchase) }
|
|
69
75
|
let payload: [String: Any?] = [
|
|
70
76
|
"campaignId": campaignId,
|
|
71
77
|
"campaignLabel": campaignLabel,
|
|
@@ -73,9 +79,9 @@ class RNNamiCampaignManager: RCTEventEmitter {
|
|
|
73
79
|
"action": actionString,
|
|
74
80
|
"skuId": skuId,
|
|
75
81
|
"purchaseError": errorSting,
|
|
76
|
-
"purchases": dictionaries
|
|
82
|
+
"purchases": dictionaries,
|
|
77
83
|
]
|
|
78
|
-
|
|
84
|
+
RNNamiCampaignManager.shared?.sendEvent(withName: "ResultCampaign", body: payload)
|
|
79
85
|
})
|
|
80
86
|
}
|
|
81
87
|
|
|
@@ -106,7 +112,7 @@ class RNNamiCampaignManager: RCTEventEmitter {
|
|
|
106
112
|
func registerForAvailableCampaigns() {
|
|
107
113
|
NamiCampaignManager.registerAvailableCampaignsHandler { availableCampaigns in
|
|
108
114
|
let dictionaries = availableCampaigns.map { campaign in self.campaignInToDictionary(campaign) }
|
|
109
|
-
|
|
115
|
+
RNNamiCampaignManager.shared?.sendEvent(withName: "AvailableCampaignsChanged", body: dictionaries)
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
}
|
|
@@ -11,6 +11,13 @@ import React
|
|
|
11
11
|
|
|
12
12
|
@objc(RNNamiCustomerManager)
|
|
13
13
|
class RNNamiCustomerManager: RCTEventEmitter {
|
|
14
|
+
public static var shared: RNNamiCustomerManager?
|
|
15
|
+
|
|
16
|
+
override init() {
|
|
17
|
+
super.init()
|
|
18
|
+
RNNamiCustomerManager.shared = self
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
override func supportedEvents() -> [String]! {
|
|
15
22
|
return ["JourneyStateChanged", "AccountStateChanged"]
|
|
16
23
|
}
|
|
@@ -53,12 +60,12 @@ class RNNamiCustomerManager: RCTEventEmitter {
|
|
|
53
60
|
func setCustomerDataPlatformId(cdpId: String) {
|
|
54
61
|
NamiCustomerManager.setCustomerDataPlatformId(with: cdpId)
|
|
55
62
|
}
|
|
56
|
-
|
|
63
|
+
|
|
57
64
|
@objc(clearCustomerDataPlatformId)
|
|
58
65
|
func clearCustomerDataPlatformId() {
|
|
59
66
|
NamiCustomerManager.clearCustomerDataPlatformId()
|
|
60
67
|
}
|
|
61
|
-
|
|
68
|
+
|
|
62
69
|
@objc(journeyState:rejecter:)
|
|
63
70
|
func journeyState(resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
|
|
64
71
|
if let journeyState = NamiCustomerManager.journeyState() {
|
|
@@ -105,28 +112,40 @@ class RNNamiCustomerManager: RCTEventEmitter {
|
|
|
105
112
|
func registerJourneyStateHandler() {
|
|
106
113
|
NamiCustomerManager.registerJourneyStateHandler { journeyState in
|
|
107
114
|
let dictionary = self.journeyStateToDictionary(journeyState)
|
|
108
|
-
|
|
115
|
+
RNNamiCustomerManager.shared?.sendEvent(withName: "JourneyStateChanged", body: dictionary)
|
|
109
116
|
}
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
@objc(registerAccountStateHandler)
|
|
113
120
|
func registerAccountStateHandler() {
|
|
114
|
-
NamiCustomerManager.registerAccountStateHandler
|
|
121
|
+
NamiCustomerManager.registerAccountStateHandler { action, success, error in
|
|
115
122
|
let actionString: String
|
|
116
123
|
switch action {
|
|
117
124
|
case .login:
|
|
118
125
|
actionString = "login"
|
|
119
126
|
case .logout:
|
|
120
127
|
actionString = "logout"
|
|
128
|
+
case .customer_data_platform_id_set:
|
|
129
|
+
actionString = "customer_data_platform_id_set"
|
|
130
|
+
case .customer_data_platform_id_cleared:
|
|
131
|
+
actionString = "customer_data_platform_id_cleared"
|
|
132
|
+
case .advertising_id_set:
|
|
133
|
+
actionString = "advertising_id_set"
|
|
134
|
+
case .advertising_id_cleared:
|
|
135
|
+
actionString = "advertising_id_cleared"
|
|
136
|
+
case .vendor_id_set:
|
|
137
|
+
actionString = "vendor_id_set"
|
|
138
|
+
case .vendor_id_cleared:
|
|
139
|
+
actionString = "vendor_id_cleared"
|
|
121
140
|
@unknown default:
|
|
122
141
|
actionString = "unknown"
|
|
123
142
|
}
|
|
124
143
|
let payload: [String: Any?] = [
|
|
125
144
|
"action": actionString,
|
|
126
145
|
"success": success,
|
|
127
|
-
"error": error?._code as Any
|
|
146
|
+
"error": error?._code as Any,
|
|
128
147
|
]
|
|
129
|
-
|
|
130
|
-
}
|
|
148
|
+
RNNamiCustomerManager.shared?.sendEvent(withName: "AccountStateChanged", body: payload)
|
|
149
|
+
}
|
|
131
150
|
}
|
|
132
151
|
}
|
|
@@ -11,6 +11,13 @@ import React
|
|
|
11
11
|
|
|
12
12
|
@objc(RNNamiEntitlementManager)
|
|
13
13
|
class RNNamiEntitlementManager: RCTEventEmitter {
|
|
14
|
+
public static var shared: RNNamiEntitlementManager?
|
|
15
|
+
|
|
16
|
+
override init() {
|
|
17
|
+
super.init()
|
|
18
|
+
RNNamiEntitlementManager.shared = self
|
|
19
|
+
}
|
|
20
|
+
|
|
14
21
|
override func supportedEvents() -> [String]! {
|
|
15
22
|
return ["EntitlementsChanged"]
|
|
16
23
|
}
|
|
@@ -40,6 +47,7 @@ class RNNamiEntitlementManager: RCTEventEmitter {
|
|
|
40
47
|
]
|
|
41
48
|
return NSDictionary(dictionary: dictionary.compactMapValues { $0 })
|
|
42
49
|
}
|
|
50
|
+
|
|
43
51
|
@objc(isEntitlementActive:resolver:rejecter:)
|
|
44
52
|
func isEntitlementActive(referenceId: String, resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
|
|
45
53
|
let isEntitlementActive = NamiEntitlementManager.isEntitlementActive(referenceId)
|
|
@@ -68,7 +76,7 @@ class RNNamiEntitlementManager: RCTEventEmitter {
|
|
|
68
76
|
let dictionary = self.entitlementInToDictionary(entitlement)
|
|
69
77
|
return dictionary
|
|
70
78
|
}
|
|
71
|
-
|
|
79
|
+
RNNamiEntitlementManager.shared?.sendEvent(withName: "EntitlementsChanged", body: dictionaries)
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
82
|
}
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
// NamiMLManagerBridge.m
|
|
3
3
|
// RNNami
|
|
4
4
|
//
|
|
5
|
-
// Created by Kendall Gelner on 4/6/20.
|
|
6
5
|
// Copyright © 2020-2023 Nami ML Inc. All rights reserved.
|
|
7
6
|
//
|
|
8
7
|
#import <Foundation/Foundation.h>
|
|
9
8
|
#import <NamiApple/NamiApple.h>
|
|
10
|
-
#import "NamiBridgeUtil.h"
|
|
11
9
|
|
|
12
10
|
#import <React/RCTBridgeModule.h>
|
|
13
11
|
#import <React/RCTEventEmitter.h>
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
#import <Foundation/Foundation.h>
|
|
10
10
|
#import <NamiApple/NamiApple.h>
|
|
11
|
-
#import "NamiBridgeUtil.h"
|
|
12
11
|
|
|
13
12
|
#import <React/RCTBridgeModule.h>
|
|
14
13
|
#import <React/RCTEventEmitter.h>
|
|
@@ -21,68 +20,12 @@ RCT_EXTERN_METHOD(buySkuComplete:(NSDictionary)dict)
|
|
|
21
20
|
|
|
22
21
|
RCT_EXTERN_METHOD(registerBuySkuHandler)
|
|
23
22
|
|
|
24
|
-
RCT_EXTERN_METHOD(registerCloseHandler
|
|
23
|
+
RCT_EXTERN_METHOD(registerCloseHandler)
|
|
25
24
|
|
|
26
|
-
RCT_EXTERN_METHOD(dismiss:(BOOL)animated
|
|
27
|
-
|
|
28
|
-
RCT_EXTERN_METHOD(displayedViewController)
|
|
29
|
-
|
|
30
|
-
+ (BOOL)requiresMainQueueSetup {
|
|
31
|
-
return YES;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@end
|
|
35
|
-
|
|
36
|
-
@interface NamiEmitter : RCTEventEmitter
|
|
37
|
-
- (void)sendEventPreparePaywallForDisplayFinishedWithResult:(BOOL)success developerPaywallID: (NSString * _Nullable) developerPaywallID error:(NSError * _Nullable) error;
|
|
38
|
-
+ (NamiEmitter *) reactInstance;
|
|
39
|
-
@end
|
|
40
|
-
|
|
41
|
-
@interface NamiPaywallManagerBridge : NSObject <RCTBridgeModule>
|
|
42
|
-
@property (atomic) BOOL blockPaywallRaise;
|
|
43
|
-
@end
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
@implementation NamiPaywallManagerBridge (RCTExternModule)
|
|
47
|
-
|
|
48
|
-
- (instancetype)init
|
|
49
|
-
{
|
|
50
|
-
self = [super init];
|
|
51
|
-
if (self) {
|
|
52
|
-
[self setBlockPaywallRaise:false];
|
|
53
|
-
}
|
|
54
|
-
return self;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
RCT_EXTERN_METHOD(raisePaywall)
|
|
58
|
-
- (void)raisePaywall {
|
|
59
|
-
[NamiCampaignManager launch];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
RCT_EXPORT_METHOD(raisePaywallByDeveloperPaywallId)
|
|
63
|
-
{
|
|
64
|
-
[NamiCampaignManager launch];
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
RCT_EXPORT_METHOD(blockPaywallRaise:(BOOL)blockRaise)
|
|
68
|
-
{
|
|
69
|
-
[self setBlockPaywallRaise:blockRaise];
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
@end
|
|
73
|
-
|
|
74
|
-
@implementation NamiPaywallManagerBridge
|
|
75
|
-
RCT_EXPORT_MODULE_NO_LOAD(NamiPaywallManagerBridge, NamiPaywallManagerBridge)
|
|
76
|
-
|
|
77
|
-
- (dispatch_queue_t)methodQueue
|
|
78
|
-
{
|
|
79
|
-
return dispatch_get_main_queue();
|
|
80
|
-
}
|
|
25
|
+
RCT_EXTERN_METHOD(dismiss:(BOOL)animated)
|
|
81
26
|
|
|
82
27
|
+ (BOOL)requiresMainQueueSetup {
|
|
83
28
|
return YES;
|
|
84
29
|
}
|
|
85
30
|
|
|
86
|
-
|
|
87
|
-
|
|
88
31
|
@end
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// NamiPaywallManagerBridge.swift
|
|
3
3
|
// RNNami
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
// Copyright © 2023 Nami ML INc.. All rights reserved.
|
|
5
|
+
// Copyright © 2023 Nami ML Inc. All rights reserved.
|
|
7
6
|
//
|
|
8
7
|
|
|
9
8
|
import Foundation
|
|
@@ -12,50 +11,71 @@ import React
|
|
|
12
11
|
|
|
13
12
|
@objc(RNNamiPaywallManager)
|
|
14
13
|
class RNNamiPaywallManager: RCTEventEmitter {
|
|
14
|
+
public static var shared: RNNamiPaywallManager?
|
|
15
|
+
|
|
16
|
+
override init() {
|
|
17
|
+
super.init()
|
|
18
|
+
RNNamiPaywallManager.shared = self
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
override func supportedEvents() -> [String]! {
|
|
16
|
-
|
|
22
|
+
return ["RegisterBuySKU", "PaywallCloseRequested"]
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
@objc(buySkuComplete:)
|
|
20
26
|
func buySkuComplete(dict: NSDictionary) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
do {
|
|
26
|
-
let decoder = JSONDecoder()
|
|
27
|
-
let product = try decoder.decode(NamiSKU.self, from: jsonData)
|
|
28
|
-
|
|
29
|
-
let dateFormatter = DateFormatter()
|
|
30
|
-
dateFormatter.locale = .init(identifier: "en_US_POSIX")
|
|
31
|
-
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
|
32
|
-
|
|
33
|
-
if
|
|
34
|
-
let transactionID = dict["transactionID"] as? String,
|
|
35
|
-
let originalTransactionID = dict["originalTransactionID"] as? String,
|
|
36
|
-
let priceDecimal = Decimal(string: dict["price"] as! String),
|
|
37
|
-
let currencyCode = dict["currencyCode"] as? String,
|
|
38
|
-
let localeString = dict["locale"] as? String
|
|
27
|
+
if let product = dict["product"] as? [String: Any] {
|
|
28
|
+
if let storeId = product["skuId"] as? String,
|
|
29
|
+
let namiId = product["id"] as? String,
|
|
30
|
+
let skuType = product["type"] as? String
|
|
39
31
|
{
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
32
|
+
let namiSkuType: NamiSKUType
|
|
33
|
+
switch skuType {
|
|
34
|
+
case "unknown":
|
|
35
|
+
namiSkuType = .unknown
|
|
36
|
+
case "one_time_purchase":
|
|
37
|
+
namiSkuType = .one_time_purchase
|
|
38
|
+
case "subscription":
|
|
39
|
+
namiSkuType = .subscription
|
|
40
|
+
default:
|
|
41
|
+
namiSkuType = .unknown
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let namiSku = NamiSKU(namiId: namiId, storeId: storeId, skuType: namiSkuType)
|
|
45
|
+
|
|
46
|
+
do {
|
|
47
|
+
let dateFormatter = DateFormatter()
|
|
48
|
+
dateFormatter.locale = .init(identifier: "en_US_POSIX")
|
|
49
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
|
50
|
+
|
|
51
|
+
if
|
|
52
|
+
let transactionID = dict["transactionID"] as? String,
|
|
53
|
+
let originalTransactionID = dict["originalTransactionID"] as? String,
|
|
54
|
+
let priceDecimal = Decimal(string: dict["price"] as! String),
|
|
55
|
+
let currencyCode = dict["currencyCode"] as? String,
|
|
56
|
+
let localeString = dict["locale"] as? String
|
|
57
|
+
{
|
|
58
|
+
let expiresDate = Date(timeIntervalSince1970: dict["purchaseDate"] as! Double? ?? 0)
|
|
59
|
+
let originalPurchaseDate = Date(timeIntervalSince1970: dict["originalPurchaseDate"] as! Double)
|
|
60
|
+
let purchaseDate = Date(timeIntervalSince1970: dict["purchaseDate"] as! Double)
|
|
61
|
+
let locale = Locale(identifier: localeString)
|
|
62
|
+
let purchaseSuccess = NamiPurchaseSuccess(
|
|
63
|
+
product: namiSku,
|
|
64
|
+
transactionID: transactionID,
|
|
65
|
+
originalTransactionID: originalTransactionID,
|
|
66
|
+
originalPurchaseDate: originalPurchaseDate,
|
|
67
|
+
purchaseDate: purchaseDate,
|
|
68
|
+
expiresDate: expiresDate,
|
|
69
|
+
price: priceDecimal,
|
|
70
|
+
currencyCode: currencyCode,
|
|
71
|
+
locale: locale
|
|
72
|
+
)
|
|
73
|
+
NamiPaywallManager.buySkuComplete(purchaseSuccess: purchaseSuccess)
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
print("RNNamiPaywallManager - buySkuComplete error - decoding JSON: \(error)")
|
|
77
|
+
}
|
|
56
78
|
}
|
|
57
|
-
} catch {
|
|
58
|
-
print("Error decoding JSON: \(error)")
|
|
59
79
|
}
|
|
60
80
|
}
|
|
61
81
|
|
|
@@ -63,31 +83,20 @@ class RNNamiPaywallManager: RCTEventEmitter {
|
|
|
63
83
|
func registerBuySkuHandler() {
|
|
64
84
|
NamiPaywallManager.registerBuySkuHandler { sku in
|
|
65
85
|
let dictionary = RNNamiPurchaseManager.skuToSKUDict(sku)
|
|
66
|
-
|
|
86
|
+
RNNamiPaywallManager.shared?.sendEvent(withName: "RegisterBuySKU", body: dictionary)
|
|
67
87
|
}
|
|
68
88
|
}
|
|
69
89
|
|
|
70
|
-
@objc(registerCloseHandler
|
|
71
|
-
func registerCloseHandler(
|
|
90
|
+
@objc(registerCloseHandler)
|
|
91
|
+
func registerCloseHandler() {
|
|
72
92
|
NamiPaywallManager.registerCloseHandler { _ in
|
|
73
|
-
let dictionary = NSDictionary(dictionary: ["
|
|
74
|
-
|
|
75
|
-
if (blockDismiss) {
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
NamiPaywallManager.dismiss(animated: true, completion: {})
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@objc(dismiss:callback:)
|
|
83
|
-
func dismiss(animated: Bool, callback: @escaping RCTResponseSenderBlock) {
|
|
84
|
-
NamiPaywallManager.dismiss(animated: animated) {
|
|
85
|
-
callback([])
|
|
93
|
+
let dictionary = NSDictionary(dictionary: ["PaywallCloseRequested": true].compactMapValues { $0 })
|
|
94
|
+
RNNamiPaywallManager.shared?.sendEvent(withName: "PaywallCloseRequested", body: dictionary)
|
|
86
95
|
}
|
|
87
96
|
}
|
|
88
97
|
|
|
89
|
-
@objc(
|
|
90
|
-
func
|
|
91
|
-
|
|
98
|
+
@objc(dismiss:)
|
|
99
|
+
func dismiss(animated: Bool) {
|
|
100
|
+
NamiPaywallManager.dismiss(animated: animated) {}
|
|
92
101
|
}
|
|
93
102
|
}
|