@capgo/capacitor-appsflyer 8.0.0
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/CapgoCapacitorAppsflyer.podspec +27 -0
- package/LICENSE +21 -0
- package/Package.swift +30 -0
- package/README.md +1257 -0
- package/android/build.gradle +178 -0
- package/android/src/main/AndroidManifest.xml +7 -0
- package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AFHelpers.kt +76 -0
- package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AppsFlyerConstants.kt +76 -0
- package/android/src/main/java/capacitor/plugin/appsflyer/sdk/AppsFlyerPlugin.kt +812 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +2145 -0
- package/dist/esm/Appsflyer_constants.d.ts +29 -0
- package/dist/esm/Appsflyer_constants.js +33 -0
- package/dist/esm/Appsflyer_constants.js.map +1 -0
- package/dist/esm/appsflyer_interfaces.d.ts +200 -0
- package/dist/esm/appsflyer_interfaces.js +18 -0
- package/dist/esm/appsflyer_interfaces.js.map +1 -0
- package/dist/esm/definitions.d.ts +219 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/plugin.cjs.js +60 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +63 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/AppsFlyerPlugin/AppsFlyerAttribution.swift +60 -0
- package/ios/Sources/AppsFlyerPlugin/AppsFlyerConstants.swift +86 -0
- package/ios/Sources/AppsFlyerPlugin/AppsFlyerPlugin.swift +1007 -0
- package/ios/Sources/AppsFlyerPlugin/Extensions.swift +78 -0
- package/ios/Tests/AppsFlyerPluginTests/AppsFlyerPluginTests.swift +8 -0
- package/package.json +93 -0
|
@@ -0,0 +1,1007 @@
|
|
|
1
|
+
// swiftlint:disable all
|
|
2
|
+
import Foundation
|
|
3
|
+
import Capacitor
|
|
4
|
+
import AppsFlyerLib
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@objc(AppsFlyerPlugin)
|
|
8
|
+
public class AppsFlyerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
9
|
+
public let identifier = "AppsFlyerPlugin"
|
|
10
|
+
public let jsName = "AppsFlyerPlugin"
|
|
11
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
12
|
+
CAPPluginMethod(name: "initSDK", returnType: CAPPluginReturnPromise),
|
|
13
|
+
CAPPluginMethod(name: "startSDK", returnType: CAPPluginReturnPromise),
|
|
14
|
+
CAPPluginMethod(name: "logEvent", returnType: CAPPluginReturnPromise),
|
|
15
|
+
CAPPluginMethod(name: "setCustomerUserId", returnType: CAPPluginReturnNone),
|
|
16
|
+
CAPPluginMethod(name: "setCurrencyCode", returnType: CAPPluginReturnNone),
|
|
17
|
+
CAPPluginMethod(name: "updateServerUninstallToken", returnType: CAPPluginReturnNone),
|
|
18
|
+
CAPPluginMethod(name: "setAppInviteOneLink", returnType: CAPPluginReturnNone),
|
|
19
|
+
CAPPluginMethod(name: "setOneLinkCustomDomain", returnType: CAPPluginReturnNone),
|
|
20
|
+
CAPPluginMethod(name: "appendParametersToDeepLinkingURL", returnType: CAPPluginReturnNone),
|
|
21
|
+
CAPPluginMethod(name: "setResolveDeepLinkURLs", returnType: CAPPluginReturnNone),
|
|
22
|
+
CAPPluginMethod(name: "addPushNotificationDeepLinkPath", returnType: CAPPluginReturnNone),
|
|
23
|
+
CAPPluginMethod(name: "setSharingFilter", returnType: CAPPluginReturnNone),
|
|
24
|
+
CAPPluginMethod(name: "setSharingFilterForAllPartners", returnType: CAPPluginReturnNone),
|
|
25
|
+
CAPPluginMethod(name: "setSharingFilterForPartners", returnType: CAPPluginReturnNone),
|
|
26
|
+
CAPPluginMethod(name: "setAdditionalData", returnType: CAPPluginReturnNone),
|
|
27
|
+
CAPPluginMethod(name: "getAppsFlyerUID", returnType: CAPPluginReturnPromise),
|
|
28
|
+
CAPPluginMethod(name: "anonymizeUser", returnType: CAPPluginReturnNone),
|
|
29
|
+
CAPPluginMethod(name: "stop", returnType: CAPPluginReturnPromise),
|
|
30
|
+
CAPPluginMethod(name: "disableSKAdNetwork", returnType: CAPPluginReturnNone),
|
|
31
|
+
CAPPluginMethod(name: "disableAdvertisingIdentifier", returnType: CAPPluginReturnNone),
|
|
32
|
+
CAPPluginMethod(name: "disableCollectASA", returnType: CAPPluginReturnNone),
|
|
33
|
+
CAPPluginMethod(name: "setHost", returnType: CAPPluginReturnNone),
|
|
34
|
+
CAPPluginMethod(name: "generateInviteLink", returnType: CAPPluginReturnPromise),
|
|
35
|
+
CAPPluginMethod(name: "validateAndLogInAppPurchaseAndroid", returnType: CAPPluginReturnPromise),
|
|
36
|
+
CAPPluginMethod(name: "validateAndLogInAppPurchaseIos", returnType: CAPPluginReturnPromise),
|
|
37
|
+
CAPPluginMethod(name: "getSdkVersion", returnType: CAPPluginReturnPromise),
|
|
38
|
+
CAPPluginMethod(name: "enableFacebookDeferredApplinks", returnType: CAPPluginReturnPromise),
|
|
39
|
+
CAPPluginMethod(name: "sendPushNotificationData", returnType: CAPPluginReturnNone),
|
|
40
|
+
CAPPluginMethod(name: "setCurrentDeviceLanguage", returnType: CAPPluginReturnPromise),
|
|
41
|
+
CAPPluginMethod(name: "logCrossPromoteImpression", returnType: CAPPluginReturnPromise),
|
|
42
|
+
CAPPluginMethod(name: "setUserEmails", returnType: CAPPluginReturnPromise),
|
|
43
|
+
CAPPluginMethod(name: "logLocation", returnType: CAPPluginReturnPromise),
|
|
44
|
+
CAPPluginMethod(name: "setPhoneNumber", returnType: CAPPluginReturnPromise),
|
|
45
|
+
CAPPluginMethod(name: "setPartnerData", returnType: CAPPluginReturnPromise),
|
|
46
|
+
CAPPluginMethod(name: "logInvite", returnType: CAPPluginReturnPromise),
|
|
47
|
+
CAPPluginMethod(name: "setDisableNetworkData", returnType: CAPPluginReturnNone),
|
|
48
|
+
CAPPluginMethod(name: "enableTCFDataCollection", returnType: CAPPluginReturnNone),
|
|
49
|
+
CAPPluginMethod(name: "setConsentData", returnType: CAPPluginReturnNone),
|
|
50
|
+
CAPPluginMethod(name: "logAdRevenue", returnType: CAPPluginReturnNone),
|
|
51
|
+
CAPPluginMethod(name: "setConsentDataV2", returnType: CAPPluginReturnNone),
|
|
52
|
+
CAPPluginMethod(name: "isSDKStarted", returnType: CAPPluginReturnPromise),
|
|
53
|
+
CAPPluginMethod(name: "isSDKStopped", returnType: CAPPluginReturnPromise),
|
|
54
|
+
CAPPluginMethod(name: "disableAppSetId", returnType: CAPPluginReturnNone),
|
|
55
|
+
CAPPluginMethod(name: "validateAndLogInAppPurchaseV2", returnType: CAPPluginReturnPromise)
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
private let APPSFLYER_PLUGIN_VERSION = "8.0.0"
|
|
59
|
+
private var conversion = true
|
|
60
|
+
private var oaoa = true
|
|
61
|
+
private var udl = false
|
|
62
|
+
private var hasSDKStarted: Bool = false
|
|
63
|
+
|
|
64
|
+
override public func load() {
|
|
65
|
+
|
|
66
|
+
NotificationCenter.default
|
|
67
|
+
.addObserver(
|
|
68
|
+
self,
|
|
69
|
+
selector: #selector(self.handleUrlOpened(notification:)),
|
|
70
|
+
name: Notification.Name.capacitorOpenURL,
|
|
71
|
+
object: nil
|
|
72
|
+
)
|
|
73
|
+
NotificationCenter.default
|
|
74
|
+
.addObserver(
|
|
75
|
+
self,
|
|
76
|
+
selector: #selector(self.handleUniversalLink(notification:)),
|
|
77
|
+
name: Notification.Name.capacitorOpenUniversalLink,
|
|
78
|
+
object: nil
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@objc func initSDK(_ call: CAPPluginCall){
|
|
85
|
+
let appsflyer = AppsFlyerLib.shared()
|
|
86
|
+
|
|
87
|
+
appsflyer
|
|
88
|
+
.setPluginInfo(
|
|
89
|
+
plugin: .capacitor,
|
|
90
|
+
version: APPSFLYER_PLUGIN_VERSION,
|
|
91
|
+
additionalParams: nil
|
|
92
|
+
)
|
|
93
|
+
guard let devKey = call.getString(AppsFlyerConstants.AF_DEV_KEY) else{
|
|
94
|
+
call.reject("devkey is missing")
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
guard let appID = call.getString(AppsFlyerConstants.AF_APP_ID) else{
|
|
98
|
+
call.reject("appID is missing")
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
let attInterval = call.getInt(AppsFlyerConstants.AF_ATT)
|
|
102
|
+
|
|
103
|
+
let debug = call.getBool(AppsFlyerConstants.AF_DEBUG, false)
|
|
104
|
+
let sandbox = call.getBool(AppsFlyerConstants.AF_SANDBOX, false)
|
|
105
|
+
let receiptSandbox = call.getBool(
|
|
106
|
+
AppsFlyerConstants.AF_RECEIPT_SANDBOX,
|
|
107
|
+
false
|
|
108
|
+
)
|
|
109
|
+
let manualStart = call.getBool(
|
|
110
|
+
AppsFlyerConstants.AF_MANUAL_START,
|
|
111
|
+
false
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
conversion = call
|
|
115
|
+
.getBool(AppsFlyerConstants.AF_CONVERSION_LISTENER, true)
|
|
116
|
+
oaoa = call.getBool(AppsFlyerConstants.AF_OAOA, true)
|
|
117
|
+
udl = call.getBool(AppsFlyerConstants.AF_UDL, false)
|
|
118
|
+
|
|
119
|
+
appsflyer.isDebug = debug
|
|
120
|
+
appsflyer.appsFlyerDevKey = devKey
|
|
121
|
+
appsflyer.appleAppID = appID
|
|
122
|
+
appsflyer.useUninstallSandbox = sandbox
|
|
123
|
+
appsflyer.useReceiptValidationSandbox = receiptSandbox
|
|
124
|
+
|
|
125
|
+
if let minTime = call.getInt(AppsFlyerConstants.AF_MIN_TIME){
|
|
126
|
+
appsflyer.minTimeBetweenSessions = UInt(minTime)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if let timeout = call.getInt(AppsFlyerConstants.AF_DEEP_LINK_TIME_OUT){
|
|
130
|
+
appsflyer.deepLinkTimeout = UInt(timeout)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if conversion || oaoa {
|
|
134
|
+
appsflyer.delegate = self
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if udl {
|
|
138
|
+
appsflyer.deepLinkDelegate = self
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
reportBridgeReady()
|
|
142
|
+
|
|
143
|
+
#if !AFSDK_NO_IDFA
|
|
144
|
+
if attInterval != nil {
|
|
145
|
+
appsflyer
|
|
146
|
+
.waitForATTUserAuthorization(
|
|
147
|
+
timeoutInterval: Double(attInterval!)
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
#endif
|
|
151
|
+
|
|
152
|
+
if !manualStart {
|
|
153
|
+
startSDK(call)
|
|
154
|
+
} else {
|
|
155
|
+
call
|
|
156
|
+
.resolve(
|
|
157
|
+
["res": "SDK initiated successfully. SDK has NOT started yet"]
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@objc func startSDK(_ call: CAPPluginCall) {
|
|
163
|
+
NotificationCenter.default
|
|
164
|
+
.addObserver(
|
|
165
|
+
self,
|
|
166
|
+
selector: #selector(sendLaunch),
|
|
167
|
+
name: UIApplication.didBecomeActiveNotification,
|
|
168
|
+
object: nil
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
AppsFlyerLib.shared().start { [weak self] dictionary, error in
|
|
172
|
+
if let error = error {
|
|
173
|
+
call.reject(error.localizedDescription)
|
|
174
|
+
} else {
|
|
175
|
+
self?.hasSDKStarted = true
|
|
176
|
+
call.resolve(["res": "success"])
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@objc func logEvent(_ call: CAPPluginCall){
|
|
182
|
+
guard let eventName = call.getString(AppsFlyerConstants.AF_EVENT_NAME) else{
|
|
183
|
+
call.reject("missing event name")
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
let eventValue = call.getObject(AppsFlyerConstants.AF_EVENT_VALUE)
|
|
187
|
+
|
|
188
|
+
AppsFlyerLib
|
|
189
|
+
.shared()
|
|
190
|
+
.logEvent(name: eventName, values: eventValue) { (
|
|
191
|
+
response: [String : Any]?,
|
|
192
|
+
error: Error?
|
|
193
|
+
) in
|
|
194
|
+
if let response = response {
|
|
195
|
+
call.resolve(["res":response])
|
|
196
|
+
}
|
|
197
|
+
if let error = error {
|
|
198
|
+
call.reject(error.localizedDescription, nil, error)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@objc func setCustomerUserId(_ call: CAPPluginCall) {
|
|
204
|
+
guard let cuid = call.getString(AppsFlyerConstants.AF_CUID) else {
|
|
205
|
+
call.reject("Invalid Customer User ID")
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
AppsFlyerLib.shared().customerUserID = cuid
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@objc func logAdRevenue(_ call: CAPPluginCall) {
|
|
213
|
+
let adRevenueData = call.jsObjectRepresentation
|
|
214
|
+
if adRevenueData.isEmpty {
|
|
215
|
+
call
|
|
216
|
+
.reject(
|
|
217
|
+
"adRevenueData is missing, the data mandatory to use this API."
|
|
218
|
+
)
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Parse the fields from the adRevenueData object
|
|
223
|
+
guard let myMonetizationNetwork = adRevenueData[AppsFlyerConstants.AF_MONETIZATION_NETWORK] as? String else {
|
|
224
|
+
call.reject("monetizationNetwork is missing")
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
guard let myCurrencyIso4217Code = adRevenueData[AppsFlyerConstants.AF_CURRENCY_ISO4217_CODE] as? String else {
|
|
228
|
+
call.reject("currencyIso4217Code is missing")
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
guard let revenue = adRevenueData[AppsFlyerConstants.AF_REVENUE] as? NSNumber else {
|
|
232
|
+
call.reject("revenue is missing or not a number")
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
guard let mediationNetworkString = adRevenueData[AppsFlyerConstants.AF_MEDIATION_NETWORK] as? String else {
|
|
236
|
+
call.reject("mediationNetwork is missing")
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
let additionalParams = adRevenueData[AppsFlyerConstants.AF_ADDITIONAL_PARAMETERS] as? [String: Any]
|
|
241
|
+
|
|
242
|
+
// Handle the mediation network mapping to AppsFlyer SDK enum
|
|
243
|
+
guard let myMediationNetwork = MediationNetworkType(rawValue: mediationNetworkString) else {
|
|
244
|
+
call.reject("Invalid mediation network")
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Create the AFAdRevenueData instance
|
|
249
|
+
let myAdRevenueData = AFAdRevenueData(
|
|
250
|
+
monetizationNetwork: myMonetizationNetwork,
|
|
251
|
+
mediationNetwork: myMediationNetwork,
|
|
252
|
+
currencyIso4217Code: myCurrencyIso4217Code,
|
|
253
|
+
eventRevenue: revenue
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
// Log the ad revenue to the AppsFlyer SDK
|
|
257
|
+
AppsFlyerLib
|
|
258
|
+
.shared()
|
|
259
|
+
.logAdRevenue(
|
|
260
|
+
myAdRevenueData,
|
|
261
|
+
additionalParameters: additionalParams
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
call.resolve()
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Helper function to map mediation network string to the AppsFlyer enum
|
|
268
|
+
private func MediationNetworkType(rawValue: String) -> MediationNetworkType? {
|
|
269
|
+
switch rawValue {
|
|
270
|
+
case "google_admob":
|
|
271
|
+
return .googleAdMob
|
|
272
|
+
case "fyber":
|
|
273
|
+
return .fyber
|
|
274
|
+
case "ironsource":
|
|
275
|
+
return .ironSource
|
|
276
|
+
case "applovin_max":
|
|
277
|
+
return .applovinMax
|
|
278
|
+
case "appodeal":
|
|
279
|
+
return .appodeal
|
|
280
|
+
case "admost":
|
|
281
|
+
return .admost
|
|
282
|
+
case "topon":
|
|
283
|
+
return .topon
|
|
284
|
+
case "tradplus":
|
|
285
|
+
return .tradplus
|
|
286
|
+
case "yandex":
|
|
287
|
+
return .yandex
|
|
288
|
+
case "chartboost":
|
|
289
|
+
return .chartBoost
|
|
290
|
+
case "unity":
|
|
291
|
+
return .unity
|
|
292
|
+
case "topon_pte":
|
|
293
|
+
return .toponPte
|
|
294
|
+
case "custom_mediation":
|
|
295
|
+
return .custom
|
|
296
|
+
case "direct_monetization_network":
|
|
297
|
+
return .directMonetization
|
|
298
|
+
default:
|
|
299
|
+
return nil
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@objc func setCurrencyCode(_ call: CAPPluginCall){
|
|
304
|
+
guard let code = call.getString(AppsFlyerConstants.AF_CURRENCY_CODE) else {
|
|
305
|
+
call.reject("Invalid Currency Code")
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
AppsFlyerLib.shared().currencyCode = code
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@objc func updateServerUninstallToken(_ call: CAPPluginCall){
|
|
314
|
+
guard let token = call.getString(AppsFlyerConstants.AF_TOKEN) else {
|
|
315
|
+
call.reject("Invalid device token")
|
|
316
|
+
|
|
317
|
+
return
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
guard let deviceTokenData = token.hexadecimalToData else{
|
|
321
|
+
call.reject("Invalid device token")
|
|
322
|
+
return
|
|
323
|
+
}
|
|
324
|
+
AppsFlyerLib.shared().registerUninstall(deviceTokenData)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@objc func setAppInviteOneLink(_ call: CAPPluginCall){
|
|
328
|
+
guard let id = call.getString(AppsFlyerConstants.AF_ONELINK_ID) else {
|
|
329
|
+
call.reject("Onelink id is missing")
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
AppsFlyerLib.shared().appInviteOneLinkID = id
|
|
333
|
+
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
@objc func setOneLinkCustomDomain(_ call: CAPPluginCall){
|
|
337
|
+
guard let arr = call.getArray(AppsFlyerConstants.AF_ONELINK_DOMAIN) else {
|
|
338
|
+
call.reject("Domains are missing")
|
|
339
|
+
return
|
|
340
|
+
}
|
|
341
|
+
var domains :[String] = []
|
|
342
|
+
for dom in arr {
|
|
343
|
+
domains.append(dom as! String)
|
|
344
|
+
}
|
|
345
|
+
AppsFlyerLib.shared().oneLinkCustomDomains = domains
|
|
346
|
+
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
@objc func appendParametersToDeepLinkingURL(_ call: CAPPluginCall){
|
|
350
|
+
guard let contains = call.getString(AppsFlyerConstants.AF_CONTAINS) else {
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
guard let parameters = call.getObject(AppsFlyerConstants.AF_PARAMETERS) else {
|
|
354
|
+
return
|
|
355
|
+
}
|
|
356
|
+
var params: [String:String] = [:]
|
|
357
|
+
for (k,v) in parameters{
|
|
358
|
+
params[k] = (v as! String)
|
|
359
|
+
}
|
|
360
|
+
AppsFlyerLib
|
|
361
|
+
.shared()
|
|
362
|
+
.appendParametersToDeeplinkURL(
|
|
363
|
+
contains: contains,
|
|
364
|
+
parameters:params
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@objc func setResolveDeepLinkURLs(_ call: CAPPluginCall){
|
|
371
|
+
guard let arr = call.getArray(AppsFlyerConstants.AF_DEEPLINK_URLS) else {
|
|
372
|
+
call.reject("URLs are missing")
|
|
373
|
+
return
|
|
374
|
+
}
|
|
375
|
+
var urls :[String] = []
|
|
376
|
+
for url in arr {
|
|
377
|
+
urls.append(url as! String)
|
|
378
|
+
}
|
|
379
|
+
AppsFlyerLib.shared().resolveDeepLinkURLs = urls
|
|
380
|
+
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@objc func addPushNotificationDeepLinkPath(_ call: CAPPluginCall){
|
|
384
|
+
guard let arr = call.getArray(AppsFlyerConstants.AF_PATH) else {
|
|
385
|
+
call.reject("Path is missing")
|
|
386
|
+
return
|
|
387
|
+
}
|
|
388
|
+
var path :[String] = []
|
|
389
|
+
for p in arr {
|
|
390
|
+
path.append(p as! String)
|
|
391
|
+
}
|
|
392
|
+
AppsFlyerLib.shared().addPushNotificationDeepLinkPath(path)
|
|
393
|
+
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
@available(*, deprecated, message: "Use setSharingFilterForPartners")
|
|
397
|
+
@objc func setSharingFilter(_ call: CAPPluginCall){
|
|
398
|
+
let filters = call.getArray(AppsFlyerConstants.AF_FILTERS , String.self)
|
|
399
|
+
|
|
400
|
+
AppsFlyerLib.shared().sharingFilter = filters
|
|
401
|
+
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
@available(*, deprecated, message: "Use setSharingFilterForPartners")
|
|
405
|
+
@objc func setSharingFilterForAllPartners(_ call: CAPPluginCall){
|
|
406
|
+
|
|
407
|
+
AppsFlyerLib.shared().setSharingFilterForAllPartners()
|
|
408
|
+
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
@objc func setSharingFilterForPartners(_ call: CAPPluginCall){
|
|
412
|
+
guard let filters = call.getArray(AppsFlyerConstants.AF_FILTERS , String.self) else{
|
|
413
|
+
return call.reject("cannot extract the filters value")
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
AppsFlyerLib.shared().setSharingFilterForPartners(filters)
|
|
417
|
+
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
@objc func setAdditionalData(_ call: CAPPluginCall){
|
|
421
|
+
guard let data = call.getObject(AppsFlyerConstants.AF_ADDITIONAL_DATA) else {
|
|
422
|
+
call.reject("Data is missing")
|
|
423
|
+
return
|
|
424
|
+
}
|
|
425
|
+
AppsFlyerLib.shared().customData = data
|
|
426
|
+
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
@objc func getAppsFlyerUID(_ call: CAPPluginCall){
|
|
431
|
+
let uid = AppsFlyerLib.shared().getAppsFlyerUID()
|
|
432
|
+
call.resolve(["uid":uid])
|
|
433
|
+
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
@objc func setDisableNetworkData(_ call: CAPPluginCall){
|
|
437
|
+
call.unavailable("Android only method - has no effact on iOS apps")
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
@objc func enableTCFDataCollection(_ call: CAPPluginCall){
|
|
441
|
+
guard let shouldEnableTCFDataCollection = call.getBool(AppsFlyerConstants.AF_ENABLE_TCF_DATA_COLLECTION) else {
|
|
442
|
+
call.reject("Missing boolean value shouldEnableTCFDataCollection")
|
|
443
|
+
return
|
|
444
|
+
}
|
|
445
|
+
AppsFlyerLib
|
|
446
|
+
.shared()
|
|
447
|
+
.enableTCFDataCollection(shouldEnableTCFDataCollection)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
@objc func setConsentData(_ call: CAPPluginCall) {
|
|
451
|
+
guard let consentData = call.getObject("data") else {
|
|
452
|
+
call.reject("Consent data is missing")
|
|
453
|
+
return
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
let isUserSubjectToGDPR = consentData[AppsFlyerConstants.AF_IS_SUBJECTED_TO_DGPR] as? Bool ?? false
|
|
457
|
+
let hasConsentForDataUsage = consentData[AppsFlyerConstants.AF_CONSENT_FOR_DATA_USAGE] as? Bool ?? false
|
|
458
|
+
let hasConsentForAdsPersonalization = consentData[AppsFlyerConstants.AF_CONSENT_FOR_ADS_PERSONALIZATION] as? Bool ?? false
|
|
459
|
+
|
|
460
|
+
let consentObject: AppsFlyerConsent
|
|
461
|
+
if isUserSubjectToGDPR {
|
|
462
|
+
consentObject = AppsFlyerConsent(
|
|
463
|
+
forGDPRUserWithHasConsentForDataUsage: hasConsentForDataUsage,
|
|
464
|
+
hasConsentForAdsPersonalization: hasConsentForAdsPersonalization
|
|
465
|
+
)
|
|
466
|
+
} else {
|
|
467
|
+
consentObject = AppsFlyerConsent(nonGDPRUser: ())
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
AppsFlyerLib.shared().setConsentData(consentObject)
|
|
471
|
+
|
|
472
|
+
call.resolve()
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
@objc func setConsentDataV2(_ call: CAPPluginCall) {
|
|
476
|
+
// inner helper: convert Bool? to NSNumber?
|
|
477
|
+
func toNSNumber(_ value: Bool?) -> NSNumber? {
|
|
478
|
+
guard let value = value else { return nil }
|
|
479
|
+
return NSNumber(value: value)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
let isUserSubjectToGDPR = toNSNumber(call.getBool(AppsFlyerConstants.AF_IS_SUBJECTED_TO_DGPR))
|
|
483
|
+
let hasConsentForDataUsage = toNSNumber(call.getBool(AppsFlyerConstants.AF_CONSENT_FOR_DATA_USAGE))
|
|
484
|
+
let hasConsentForAdsPersonalization = toNSNumber(call.getBool(AppsFlyerConstants.AF_CONSENT_FOR_ADS_PERSONALIZATION))
|
|
485
|
+
let hasConsentForAdStorage = toNSNumber(call.getBool(AppsFlyerConstants.AF_CONSENT_FOR_ADS_STORAGE))
|
|
486
|
+
|
|
487
|
+
// Build consent options object and pass to AppsFlyer SDK
|
|
488
|
+
let consentOptions = AppsFlyerConsent(
|
|
489
|
+
isUserSubjectToGDPR: isUserSubjectToGDPR,
|
|
490
|
+
hasConsentForDataUsage: hasConsentForDataUsage,
|
|
491
|
+
hasConsentForAdsPersonalization: hasConsentForAdsPersonalization,
|
|
492
|
+
hasConsentForAdStorage: hasConsentForAdStorage
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
AppsFlyerLib.shared().setConsentData(consentOptions)
|
|
496
|
+
call.resolve()
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
@objc func anonymizeUser(_ call: CAPPluginCall){
|
|
500
|
+
guard let anonymize = call.getBool(AppsFlyerConstants.AF_ANONYMIZE_USER) else{
|
|
501
|
+
call.reject("Missing boolean value anonymizeUser")
|
|
502
|
+
return
|
|
503
|
+
}
|
|
504
|
+
AppsFlyerLib.shared().anonymizeUser = anonymize
|
|
505
|
+
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
@objc func stop(_ call: CAPPluginCall){
|
|
509
|
+
let stop = call.getBool(AppsFlyerConstants.AF_STOP)
|
|
510
|
+
if stop != nil {
|
|
511
|
+
AppsFlyerLib.shared().isStopped = stop!
|
|
512
|
+
}
|
|
513
|
+
call
|
|
514
|
+
.resolve(
|
|
515
|
+
[AppsFlyerConstants.AF_IS_STOP : AppsFlyerLib.shared().isStopped ]
|
|
516
|
+
)
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
@objc func disableSKAdNetwork(_ call: CAPPluginCall){
|
|
520
|
+
guard let disable = call.getBool(AppsFlyerConstants.AF_DISABLE_SKAD) else {
|
|
521
|
+
call.reject("Missing boolean value shouldDisable")
|
|
522
|
+
return
|
|
523
|
+
}
|
|
524
|
+
AppsFlyerLib.shared().disableSKAdNetwork = disable
|
|
525
|
+
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
#if !AFSDK_NO_IDFA
|
|
529
|
+
@objc func disableAdvertisingIdentifier(_ call: CAPPluginCall){
|
|
530
|
+
guard let disable = call.getBool(AppsFlyerConstants.AF_DISABLE_SKAD) else {
|
|
531
|
+
call.reject("Missing boolean value shouldDisable")
|
|
532
|
+
return
|
|
533
|
+
}
|
|
534
|
+
AppsFlyerLib.shared().disableAdvertisingIdentifier = disable
|
|
535
|
+
|
|
536
|
+
}
|
|
537
|
+
#endif
|
|
538
|
+
|
|
539
|
+
@objc func disableCollectASA(_ call: CAPPluginCall){
|
|
540
|
+
guard let disable = call.getBool(AppsFlyerConstants.AF_DISABLE_SKAD) else {
|
|
541
|
+
call.reject("Missing boolean value shouldDisable")
|
|
542
|
+
return
|
|
543
|
+
}
|
|
544
|
+
AppsFlyerLib.shared().disableCollectASA = disable
|
|
545
|
+
|
|
546
|
+
}
|
|
547
|
+
@objc func setHost(_ call: CAPPluginCall){
|
|
548
|
+
let pre = call.getString(AppsFlyerConstants.AF_HOST_PREFIX)
|
|
549
|
+
let post = call.getString(AppsFlyerConstants.AF_HOST_POSTFIX)
|
|
550
|
+
if (pre != nil && post != nil) {
|
|
551
|
+
AppsFlyerLib.shared().setHost(post!, withHostPrefix: pre!)
|
|
552
|
+
} else {
|
|
553
|
+
call.reject("Missing host prefix and/or host name")
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
@objc func generateInviteLink(_ call: CAPPluginCall){
|
|
558
|
+
AppsFlyerShareInviteHelper.generateInviteUrl(
|
|
559
|
+
linkGenerator:
|
|
560
|
+
{(
|
|
561
|
+
_ generator: AppsFlyerLinkGenerator
|
|
562
|
+
) -> AppsFlyerLinkGenerator in
|
|
563
|
+
if let channel = call.getString(AppsFlyerConstants.AF_CHANNEL){
|
|
564
|
+
generator.setChannel(channel)
|
|
565
|
+
}
|
|
566
|
+
if let brandDomain = call.getString(AppsFlyerConstants.AF_BRAND_DOMAIN){
|
|
567
|
+
generator.brandDomain = brandDomain
|
|
568
|
+
}
|
|
569
|
+
if let campaign = call.getString(AppsFlyerConstants.AF_CAMPAIGN){
|
|
570
|
+
generator.setCampaign(campaign)
|
|
571
|
+
}
|
|
572
|
+
if let referrerName = call.getString(
|
|
573
|
+
AppsFlyerConstants.AF_REFERRER_NAME
|
|
574
|
+
){
|
|
575
|
+
generator.setReferrerName(referrerName)
|
|
576
|
+
}
|
|
577
|
+
if let referrerImageURL = call.getString(
|
|
578
|
+
AppsFlyerConstants.AF_REFERRER_IMAGE_URL
|
|
579
|
+
){
|
|
580
|
+
generator.setReferrerImageURL(referrerImageURL)
|
|
581
|
+
}
|
|
582
|
+
if let referrerCustomerId = call.getString(
|
|
583
|
+
AppsFlyerConstants.AF_REFERRER_CUSTOMER_ID
|
|
584
|
+
){
|
|
585
|
+
generator.setReferrerCustomerId(referrerCustomerId)
|
|
586
|
+
}
|
|
587
|
+
if let baseDeeplink = call.getString(
|
|
588
|
+
AppsFlyerConstants.AF_BASE_DEEPLINK
|
|
589
|
+
){
|
|
590
|
+
generator.setBaseDeeplink(baseDeeplink)
|
|
591
|
+
}
|
|
592
|
+
if let addParameters = call.getObject(
|
|
593
|
+
AppsFlyerConstants.AF_ADD_PARAMETERS
|
|
594
|
+
){
|
|
595
|
+
generator.addParameters(addParameters)
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return generator
|
|
599
|
+
},
|
|
600
|
+
completionHandler: {url in
|
|
601
|
+
if url != nil{
|
|
602
|
+
call.resolve([AppsFlyerConstants.AF_LINK_READY: url!.absoluteString])
|
|
603
|
+
}else{
|
|
604
|
+
call.reject("Failed to generate a link")
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
}
|
|
610
|
+
@available(*, deprecated, message: "Use validateAndLogInAppPurchaseV2 instead")
|
|
611
|
+
@objc func validateAndLogInAppPurchaseAndroid(_ call: CAPPluginCall){
|
|
612
|
+
call.unavailable()
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
@available(*, deprecated, message: "Use validateAndLogInAppPurchaseV2 instead")
|
|
616
|
+
@objc func validateAndLogInAppPurchaseIos(_ call: CAPPluginCall){
|
|
617
|
+
let currency = call.getString(AppsFlyerConstants.AF_CURRENCY)
|
|
618
|
+
let price = call.getString(AppsFlyerConstants.AF_PRICE)
|
|
619
|
+
let _inAppPurchase = call.getString(
|
|
620
|
+
AppsFlyerConstants.AF_IN_APP_PURCHASE
|
|
621
|
+
)
|
|
622
|
+
let transactionId = call.getString(AppsFlyerConstants.AF_TRANSACTION_ID)
|
|
623
|
+
let additionalParameters = call.getObject(AppsFlyerConstants.AF_ADDITIONAL_PARAMETERS) ?? [:]
|
|
624
|
+
|
|
625
|
+
if currency != nil && price != nil && _inAppPurchase != nil && transactionId != nil && currency != nil {
|
|
626
|
+
AppsFlyerLib.shared().validateAndLog(
|
|
627
|
+
inAppPurchase: _inAppPurchase,
|
|
628
|
+
price: price,
|
|
629
|
+
currency: currency,
|
|
630
|
+
transactionId: transactionId,
|
|
631
|
+
additionalParameters: additionalParameters,
|
|
632
|
+
success: {result in
|
|
633
|
+
call.resolve(["res":result])
|
|
634
|
+
},
|
|
635
|
+
failure: { error, result in
|
|
636
|
+
guard let emptyInApp = result as? [String:Any]
|
|
637
|
+
else
|
|
638
|
+
{
|
|
639
|
+
call.reject((error)?.localizedDescription ?? "error" )
|
|
640
|
+
return
|
|
641
|
+
}
|
|
642
|
+
call.reject((error)?.localizedDescription ?? "error" , emptyInApp.jsonStringRepresentation)
|
|
643
|
+
})
|
|
644
|
+
}else{
|
|
645
|
+
call.reject("Missing some fields")
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
@objc func getSdkVersion(_ call: CAPPluginCall){
|
|
652
|
+
|
|
653
|
+
call.resolve(["res": AppsFlyerLib.shared().getSDKVersion()])
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
@objc func enableFacebookDeferredApplinks(_ call: CAPPluginCall){
|
|
657
|
+
guard let enable = call.getBool(AppsFlyerConstants.AF_FB) else {
|
|
658
|
+
call.reject("missing boolean value: \(AppsFlyerConstants.AF_FB)")
|
|
659
|
+
return
|
|
660
|
+
}
|
|
661
|
+
if enable{
|
|
662
|
+
#if canImport(FacebookCore)
|
|
663
|
+
AppsFlyerLib.shared().enableFacebookDeferredApplinks(with: FBSDKAppLinkUtility.self)
|
|
664
|
+
call.resolve(["res": "enabled"])
|
|
665
|
+
#else
|
|
666
|
+
call.reject("Please install FBSDK First!")
|
|
667
|
+
#endif
|
|
668
|
+
}else{
|
|
669
|
+
AppsFlyerLib.shared().enableFacebookDeferredApplinks(with: nil)
|
|
670
|
+
call.resolve(["res": "disabled"])
|
|
671
|
+
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
@objc func sendPushNotificationData(_ call: CAPPluginCall){
|
|
677
|
+
let json = call.getObject(AppsFlyerConstants.AF_PUSH_PAYLOAD)
|
|
678
|
+
AppsFlyerLib.shared().handlePushNotification(json)
|
|
679
|
+
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
@objc func setCurrentDeviceLanguage(_ call: CAPPluginCall){
|
|
684
|
+
guard let language = call.getString(AppsFlyerConstants.AF_LANGUAGE) else {
|
|
685
|
+
call.reject("cannot extract the language value")
|
|
686
|
+
return
|
|
687
|
+
}
|
|
688
|
+
AppsFlyerLib.shared().currentDeviceLanguage = language
|
|
689
|
+
call.resolve(["res": "ok"])
|
|
690
|
+
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
@objc func logCrossPromoteImpression(_ call: CAPPluginCall){
|
|
694
|
+
guard let appID = call.getString(AppsFlyerConstants.AF_APP_ID) else {
|
|
695
|
+
call.reject("cannot extract the appID value")
|
|
696
|
+
return
|
|
697
|
+
}
|
|
698
|
+
guard let campaign = call.getString(AppsFlyerConstants.AF_CAMPAIGN) else {
|
|
699
|
+
call.reject("cannot extract the campaign value")
|
|
700
|
+
return
|
|
701
|
+
}
|
|
702
|
+
guard let parameters = call.getObject(AppsFlyerConstants.AF_PARAMETERS) else {
|
|
703
|
+
call.reject("cannot extract the parameters value")
|
|
704
|
+
return
|
|
705
|
+
}
|
|
706
|
+
AppsFlyerCrossPromotionHelper
|
|
707
|
+
.logCrossPromoteImpression(
|
|
708
|
+
appID,
|
|
709
|
+
campaign: campaign,
|
|
710
|
+
parameters: parameters
|
|
711
|
+
)
|
|
712
|
+
call.resolve(["res": "ok"])
|
|
713
|
+
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
@objc func setUserEmails(_ call: CAPPluginCall){
|
|
717
|
+
guard let emails = call.getArray(AppsFlyerConstants.AF_EMAILS, String.self) else {
|
|
718
|
+
call.reject("cannot extract the emails value")
|
|
719
|
+
return
|
|
720
|
+
}
|
|
721
|
+
if let enc = call.getBool(AppsFlyerConstants.AF_ENCODE) , enc == true{
|
|
722
|
+
AppsFlyerLib
|
|
723
|
+
.shared()
|
|
724
|
+
.setUserEmails(emails, with: EmailCryptTypeSHA256)
|
|
725
|
+
|
|
726
|
+
}else{
|
|
727
|
+
AppsFlyerLib
|
|
728
|
+
.shared()
|
|
729
|
+
.setUserEmails(emails, with: EmailCryptTypeNone)
|
|
730
|
+
|
|
731
|
+
}
|
|
732
|
+
call.resolve(["res": "ok"])
|
|
733
|
+
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
@objc func logLocation(_ call: CAPPluginCall){
|
|
737
|
+
guard let longitude = call.getDouble(AppsFlyerConstants.AF_LONGITUDE) else {
|
|
738
|
+
call.reject("cannot extract the longitude value")
|
|
739
|
+
return
|
|
740
|
+
}
|
|
741
|
+
guard let latitude = call.getDouble(AppsFlyerConstants.AF_LATITUDE) else {
|
|
742
|
+
call.reject("cannot extract the longitude value")
|
|
743
|
+
return
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
AppsFlyerLib
|
|
747
|
+
.shared()
|
|
748
|
+
.logLocation(longitude: longitude, latitude: latitude)
|
|
749
|
+
call.resolve(["res": "ok"])
|
|
750
|
+
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
@objc func setPhoneNumber(_ call: CAPPluginCall){
|
|
754
|
+
guard let phone = call.getString(AppsFlyerConstants.AF_PHONE) else {
|
|
755
|
+
call.reject("cannot extract the phone value")
|
|
756
|
+
return
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
AppsFlyerLib.shared().phoneNumber = phone
|
|
760
|
+
call.resolve(["res": "ok"])
|
|
761
|
+
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
@objc func setPartnerData(_ call: CAPPluginCall){
|
|
765
|
+
guard let data = call.getObject(AppsFlyerConstants.AF_DATA) else {
|
|
766
|
+
call.reject("cannot extract the data value")
|
|
767
|
+
return
|
|
768
|
+
}
|
|
769
|
+
guard let pid = call.getString(AppsFlyerConstants.AF_PARTNER_ID) else {
|
|
770
|
+
call.reject("cannot extract the partnerId value")
|
|
771
|
+
return
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
AppsFlyerLib.shared().setPartnerData(partnerId: pid, partnerInfo: data)
|
|
775
|
+
call.resolve(["res": "ok"])
|
|
776
|
+
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
@objc func logInvite(_ call: CAPPluginCall){
|
|
780
|
+
guard let data = call.getObject(AppsFlyerConstants.AF_EVENT_PARAMETERS) else {
|
|
781
|
+
call.reject("cannot extract the eventParameters value")
|
|
782
|
+
return
|
|
783
|
+
}
|
|
784
|
+
guard let channel = call.getString(AppsFlyerConstants.AF_CHANNEL) else {
|
|
785
|
+
call.reject("cannot extract the channel value")
|
|
786
|
+
return
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
AppsFlyerShareInviteHelper.logInvite(channel, parameters: data)
|
|
790
|
+
call.resolve(["res": "ok"])
|
|
791
|
+
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Returns whether the AppsFlyer SDK has been started in the current session.
|
|
796
|
+
*/
|
|
797
|
+
@objc func isSDKStarted(_ call: CAPPluginCall) {
|
|
798
|
+
call.resolve(["isStarted": hasSDKStarted])
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* Returns whether the AppsFlyer SDK is currently stopped.
|
|
803
|
+
*/
|
|
804
|
+
@objc func isSDKStopped(_ call: CAPPluginCall) {
|
|
805
|
+
call.resolve(["isStopped": AppsFlyerLib.shared().isStopped])
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
@objc func disableAppSetId(_ call: CAPPluginCall){
|
|
809
|
+
call.unavailable()
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
@objc func validateAndLogInAppPurchaseV2(_ call: CAPPluginCall) {
|
|
813
|
+
guard let purchaseDetailsMap = call.getObject(AppsFlyerConstants.AF_PURCHASE_DETAILS) else {
|
|
814
|
+
call.reject("Purchase details are required")
|
|
815
|
+
return
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
let additionalParameters = call.getObject(AppsFlyerConstants.AF_ADDITIONAL_PARAMETERS)
|
|
819
|
+
|
|
820
|
+
// Validate required fields
|
|
821
|
+
guard let purchaseTypeString = purchaseDetailsMap[AppsFlyerConstants.AF_PURCHASE_TYPE] as? String else {
|
|
822
|
+
call.reject("Purchase type is required")
|
|
823
|
+
return
|
|
824
|
+
}
|
|
825
|
+
guard let purchaseType = mapPurchaseType(purchaseTypeString) else {
|
|
826
|
+
call.reject("Unkown purchase type")
|
|
827
|
+
return
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
guard let purchaseToken = purchaseDetailsMap[AppsFlyerConstants.AF_PURCHASE_TOKEN] as? String else {
|
|
831
|
+
call.reject("Purchase token is required")
|
|
832
|
+
return
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
guard let productId = purchaseDetailsMap[AppsFlyerConstants.AF_PRODUCT_ID] as? String else {
|
|
836
|
+
call.reject("Product ID is required")
|
|
837
|
+
return
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Create a new instance of AFSDKPurchaseDetails with the required information
|
|
841
|
+
let purchaseDetails: AFSDKPurchaseDetails = AFSDKPurchaseDetails(
|
|
842
|
+
productId: productId,
|
|
843
|
+
transactionId: purchaseToken,
|
|
844
|
+
purchaseType: purchaseType
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
// For iOS, we use the existing validateAndLog method with the new V2 parameters
|
|
849
|
+
// The purchaseToken serves as the transactionId for iOS
|
|
850
|
+
AppsFlyerLib.shared().validateAndLogInAppPurchase(purchaseDetails: purchaseDetails, purchaseAdditionalDetails: additionalParameters){result, error in
|
|
851
|
+
if result != nil {
|
|
852
|
+
var response: [String: Any] = [:]
|
|
853
|
+
if let resultDict = result as? [String: Any] {
|
|
854
|
+
response = resultDict
|
|
855
|
+
} else {
|
|
856
|
+
response["result"] = result
|
|
857
|
+
}
|
|
858
|
+
call.resolve(response)
|
|
859
|
+
} else if error != nil {
|
|
860
|
+
var errorDict: [String: Any] = [:]
|
|
861
|
+
if let nsError = error as NSError? {
|
|
862
|
+
errorDict["error"] = nsError.localizedDescription
|
|
863
|
+
errorDict["code"] = nsError.code
|
|
864
|
+
errorDict["domain"] = nsError.domain
|
|
865
|
+
// Convert userInfo to JSON-safe values (userInfo may contain non-serializable objects like NSError)
|
|
866
|
+
errorDict["userInfo"] = nsError.userInfo.jsonSafeRepresentation()
|
|
867
|
+
}
|
|
868
|
+
call.reject("Validation failed", errorDict.jsonStringRepresentation ?? "")
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
func mapPurchaseType(_ purchaseTypeString: String) -> AFSDKPurchaseType? {
|
|
874
|
+
switch purchaseTypeString {
|
|
875
|
+
case "subscription":
|
|
876
|
+
return .subscription
|
|
877
|
+
|
|
878
|
+
case "one_time_purchase":
|
|
879
|
+
return .oneTimePurchase
|
|
880
|
+
|
|
881
|
+
default:
|
|
882
|
+
return nil
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
extension AppsFlyerPlugin{
|
|
888
|
+
private func reportBridgeReady(){
|
|
889
|
+
AppsFlyerAttribution.shared.bridgReady = true
|
|
890
|
+
NotificationCenter.default
|
|
891
|
+
.post(name: Notification.Name.appsflyerBridge, object: nil)
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
@objc private func sendLaunch(){
|
|
895
|
+
AppsFlyerLib.shared().start()
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
@objc func handleUrlOpened(notification: NSNotification) {
|
|
899
|
+
guard let object = notification.object as? [String: Any?] else {
|
|
900
|
+
return
|
|
901
|
+
}
|
|
902
|
+
guard let url = object["url"] else {
|
|
903
|
+
afLogger(msg: "handleUrlOpened url is nil")
|
|
904
|
+
return
|
|
905
|
+
}
|
|
906
|
+
guard let options = object["options"] else {
|
|
907
|
+
afLogger(msg: "handleUrlOpened options is nil")
|
|
908
|
+
|
|
909
|
+
return
|
|
910
|
+
}
|
|
911
|
+
afLogger(msg: "handleUrlOpened with \((url as! URL).absoluteString)")
|
|
912
|
+
AppsFlyerAttribution.shared
|
|
913
|
+
.handleOpenUrl(
|
|
914
|
+
open: url as! URL,
|
|
915
|
+
options: options as! [UIApplication.OpenURLOptionsKey: Any]
|
|
916
|
+
)
|
|
917
|
+
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
@objc func handleUniversalLink(notification: NSNotification) {
|
|
921
|
+
guard let object = notification.object as? [String: Any?] else {
|
|
922
|
+
return
|
|
923
|
+
}
|
|
924
|
+
let user = NSUserActivity(activityType: NSUserActivityTypeBrowsingWeb)
|
|
925
|
+
guard let url = object["url"] else {
|
|
926
|
+
afLogger(msg: "handleUrlOpened options is url")
|
|
927
|
+
return
|
|
928
|
+
}
|
|
929
|
+
user.webpageURL = (url as! URL)
|
|
930
|
+
afLogger(
|
|
931
|
+
msg: "handleUniversalLink with \(user.webpageURL?.absoluteString ?? "null")"
|
|
932
|
+
)
|
|
933
|
+
AppsFlyerAttribution.shared.continueUserActivity(userActivity: user)
|
|
934
|
+
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
extension AppsFlyerPlugin : AppsFlyerLibDelegate {
|
|
940
|
+
public func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
|
|
941
|
+
let json : [String: Any] = [
|
|
942
|
+
"callbackName":"onConversionDataSuccess",
|
|
943
|
+
"data":conversionInfo
|
|
944
|
+
]
|
|
945
|
+
self.notifyListeners(AppsFlyerConstants.CONVERSION_CALLBACK, data: json)
|
|
946
|
+
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
public func onConversionDataFail(_ error: Error) {
|
|
950
|
+
let json : [String: Any] = [
|
|
951
|
+
"callbackName":"onConversionDataFail",
|
|
952
|
+
"status":error.localizedDescription
|
|
953
|
+
]
|
|
954
|
+
self.notifyListeners(AppsFlyerConstants.CONVERSION_CALLBACK, data: json)
|
|
955
|
+
}
|
|
956
|
+
public func onAppOpenAttribution(_ attributionData: [AnyHashable : Any]) {
|
|
957
|
+
let json : [String: Any] = [
|
|
958
|
+
"callbackName":"onAppOpenAttribution",
|
|
959
|
+
"data":attributionData
|
|
960
|
+
]
|
|
961
|
+
self.notifyListeners(AppsFlyerConstants.OAOA_CALLBACK, data: json)
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
public func onAppOpenAttributionFailure(_ error: Error) {
|
|
965
|
+
let json : [String: Any] = [
|
|
966
|
+
"callbackName":"onAppOpenAttributionFailure",
|
|
967
|
+
"status":error.localizedDescription
|
|
968
|
+
]
|
|
969
|
+
self.notifyListeners(AppsFlyerConstants.OAOA_CALLBACK, data: json)
|
|
970
|
+
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
// Mark -
|
|
977
|
+
extension AppsFlyerPlugin : DeepLinkDelegate{
|
|
978
|
+
public func didResolveDeepLink(_ result: DeepLinkResult) {
|
|
979
|
+
var json : [String: Any] = [:]
|
|
980
|
+
|
|
981
|
+
switch result.status {
|
|
982
|
+
case .notFound :
|
|
983
|
+
json["status"] = "NOT_FOUND"
|
|
984
|
+
case .failure :
|
|
985
|
+
json["status"] = "FAILURE"
|
|
986
|
+
case .found :
|
|
987
|
+
json["status"] = "FOUND"
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
if result.error != nil {
|
|
991
|
+
json["error"] = result.error!.localizedDescription
|
|
992
|
+
}
|
|
993
|
+
if result.deepLink != nil {
|
|
994
|
+
var deepLinkDic = result.deepLink!.clickEvent
|
|
995
|
+
deepLinkDic["is_deferred"] = result.deepLink!.isDeferred
|
|
996
|
+
json["deepLink"] = deepLinkDic
|
|
997
|
+
}
|
|
998
|
+
self.notifyListeners(AppsFlyerConstants.UDL_CALLBACK, data: json)
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
extension AppsFlyerPlugin{
|
|
1004
|
+
private func afLogger(msg : String){
|
|
1005
|
+
NSLog ("AppsFlyer [Debug][Capacitor]: \(msg)");
|
|
1006
|
+
}
|
|
1007
|
+
}
|