insert-affiliate-react-native-sdk 1.10.0 → 1.11.1
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/.claude/settings.local.json +8 -2
- package/dist/DeepLinkIapProvider.js +253 -151
- package/docs/deep-linking-appsflyer.md +23 -2
- package/docs/deep-linking-branch.md +23 -2
- package/package.json +1 -1
- package/readme.md +70 -22
- package/src/DeepLinkIapProvider.tsx +225 -91
|
@@ -4,8 +4,14 @@
|
|
|
4
4
|
"WebFetch(domain:github.com)",
|
|
5
5
|
"Bash(npm run build:*)",
|
|
6
6
|
"Bash(npm install:*)",
|
|
7
|
-
"Bash(npm view:*)"
|
|
7
|
+
"Bash(npm view:*)",
|
|
8
|
+
"Bash(find:*)",
|
|
9
|
+
"Bash(adb logcat:*)",
|
|
10
|
+
"Bash(adb shell:*)",
|
|
11
|
+
"Bash(adb shell am start:*)",
|
|
12
|
+
"Bash(git checkout:*)",
|
|
13
|
+
"Bash(git pull:*)"
|
|
8
14
|
],
|
|
9
15
|
"deny": []
|
|
10
16
|
}
|
|
11
|
-
}
|
|
17
|
+
}
|
|
@@ -88,43 +88,63 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
88
88
|
const [OfferCode, setOfferCode] = (0, react_1.useState)(null);
|
|
89
89
|
const [affiliateAttributionActiveTime, setAffiliateAttributionActiveTime] = (0, react_1.useState)(null);
|
|
90
90
|
const insertAffiliateIdentifierChangeCallbackRef = (0, react_1.useRef)(null);
|
|
91
|
+
const isInitializingRef = (0, react_1.useRef)(false);
|
|
92
|
+
// Refs for values that need to be current inside callbacks (to avoid stale closures)
|
|
93
|
+
const companyCodeRef = (0, react_1.useRef)(null);
|
|
94
|
+
const verboseLoggingRef = (0, react_1.useRef)(false);
|
|
95
|
+
// Refs for implementation functions (ref callback pattern for stable + fresh)
|
|
96
|
+
const initializeImplRef = (0, react_1.useRef)(null);
|
|
97
|
+
const setShortCodeImplRef = (0, react_1.useRef)(null);
|
|
98
|
+
const getAffiliateDetailsImplRef = (0, react_1.useRef)(null);
|
|
99
|
+
const returnInsertAffiliateIdentifierImplRef = (0, react_1.useRef)(null);
|
|
100
|
+
const isAffiliateAttributionValidImplRef = (0, react_1.useRef)(null);
|
|
101
|
+
const getAffiliateStoredDateImplRef = (0, react_1.useRef)(null);
|
|
102
|
+
const storeExpectedStoreTransactionImplRef = (0, react_1.useRef)(null);
|
|
103
|
+
const returnUserAccountTokenAndStoreExpectedTransactionImplRef = (0, react_1.useRef)(null);
|
|
104
|
+
const validatePurchaseWithIapticAPIImplRef = (0, react_1.useRef)(null);
|
|
105
|
+
const trackEventImplRef = (0, react_1.useRef)(null);
|
|
106
|
+
const setInsertAffiliateIdentifierImplRef = (0, react_1.useRef)(null);
|
|
107
|
+
const handleInsertLinksImplRef = (0, react_1.useRef)(null);
|
|
91
108
|
// MARK: Initialize the SDK
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (affiliateAttributionActiveTime !== undefined) {
|
|
97
|
-
setAffiliateAttributionActiveTime(affiliateAttributionActiveTime);
|
|
109
|
+
const initializeImpl = (companyCodeParam_1, ...args_1) => __awaiter(void 0, [companyCodeParam_1, ...args_1], void 0, function* (companyCodeParam, verboseLoggingParam = false, insertLinksEnabledParam = false, insertLinksClipboardEnabledParam = false, affiliateAttributionActiveTimeParam) {
|
|
110
|
+
// Prevent multiple concurrent initialization attempts
|
|
111
|
+
if (isInitialized || isInitializingRef.current) {
|
|
112
|
+
return;
|
|
98
113
|
}
|
|
99
|
-
|
|
114
|
+
isInitializingRef.current = true;
|
|
115
|
+
setVerboseLogging(verboseLoggingParam);
|
|
116
|
+
verboseLoggingRef.current = verboseLoggingParam;
|
|
117
|
+
setInsertLinksEnabled(insertLinksEnabledParam);
|
|
118
|
+
setInsertLinksClipboardEnabled(insertLinksClipboardEnabledParam);
|
|
119
|
+
if (affiliateAttributionActiveTimeParam !== undefined) {
|
|
120
|
+
setAffiliateAttributionActiveTime(affiliateAttributionActiveTimeParam);
|
|
121
|
+
}
|
|
122
|
+
if (verboseLoggingParam) {
|
|
100
123
|
console.log('[Insert Affiliate] [VERBOSE] Starting SDK initialization...');
|
|
101
|
-
console.log('[Insert Affiliate] [VERBOSE] Company code provided:',
|
|
124
|
+
console.log('[Insert Affiliate] [VERBOSE] Company code provided:', companyCodeParam ? 'Yes' : 'No');
|
|
102
125
|
console.log('[Insert Affiliate] [VERBOSE] Verbose logging enabled');
|
|
103
126
|
}
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (companyCode && companyCode.trim() !== '') {
|
|
109
|
-
setCompanyCode(companyCode);
|
|
110
|
-
yield saveValueInAsync(ASYNC_KEYS.COMPANY_CODE, companyCode);
|
|
127
|
+
if (companyCodeParam && companyCodeParam.trim() !== '') {
|
|
128
|
+
setCompanyCode(companyCodeParam);
|
|
129
|
+
companyCodeRef.current = companyCodeParam;
|
|
130
|
+
yield saveValueInAsync(ASYNC_KEYS.COMPANY_CODE, companyCodeParam);
|
|
111
131
|
setIsInitialized(true);
|
|
112
|
-
console.log(`[Insert Affiliate] SDK initialized with company code: ${
|
|
113
|
-
if (
|
|
132
|
+
console.log(`[Insert Affiliate] SDK initialized with company code: ${companyCodeParam}`);
|
|
133
|
+
if (verboseLoggingParam) {
|
|
114
134
|
console.log('[Insert Affiliate] [VERBOSE] Company code saved to AsyncStorage');
|
|
115
135
|
console.log('[Insert Affiliate] [VERBOSE] SDK marked as initialized');
|
|
116
136
|
}
|
|
117
137
|
// Report SDK initialization for onboarding verification (fire and forget)
|
|
118
|
-
reportSdkInitIfNeeded(
|
|
138
|
+
reportSdkInitIfNeeded(companyCodeParam, verboseLoggingParam);
|
|
119
139
|
}
|
|
120
140
|
else {
|
|
121
141
|
console.warn('[Insert Affiliate] SDK initialized without a company code.');
|
|
122
142
|
setIsInitialized(true);
|
|
123
|
-
if (
|
|
143
|
+
if (verboseLoggingParam) {
|
|
124
144
|
console.log('[Insert Affiliate] [VERBOSE] No company code provided, SDK initialized in limited mode');
|
|
125
145
|
}
|
|
126
146
|
}
|
|
127
|
-
if (
|
|
147
|
+
if (insertLinksEnabledParam && react_native_1.Platform.OS === 'ios') {
|
|
128
148
|
try {
|
|
129
149
|
const enhancedSystemInfo = yield getEnhancedSystemInfo();
|
|
130
150
|
yield sendSystemInfoToBackend(enhancedSystemInfo);
|
|
@@ -155,6 +175,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
155
175
|
}
|
|
156
176
|
if (companyCodeFromStorage) {
|
|
157
177
|
setCompanyCode(companyCodeFromStorage);
|
|
178
|
+
companyCodeRef.current = companyCodeFromStorage;
|
|
158
179
|
verboseLog('Company code restored from storage');
|
|
159
180
|
}
|
|
160
181
|
if (storedOfferCode) {
|
|
@@ -288,12 +309,6 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
288
309
|
setIsInitialized(false);
|
|
289
310
|
console.log('[Insert Affiliate] SDK has been reset.');
|
|
290
311
|
};
|
|
291
|
-
// MARK: Callback Management
|
|
292
|
-
// Sets a callback that will be triggered whenever storeInsertAffiliateIdentifier is called
|
|
293
|
-
// The callback receives the current affiliate identifier (returnInsertAffiliateIdentifier result)
|
|
294
|
-
const setInsertAffiliateIdentifierChangeCallbackHandler = (callback) => {
|
|
295
|
-
insertAffiliateIdentifierChangeCallbackRef.current = callback;
|
|
296
|
-
};
|
|
297
312
|
// MARK: Deep Link Handling
|
|
298
313
|
// Helper function to parse URLs in React Native compatible way
|
|
299
314
|
const parseURL = (url) => {
|
|
@@ -479,7 +494,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
479
494
|
}
|
|
480
495
|
});
|
|
481
496
|
// Handles Insert Links deep linking - equivalent to iOS handleInsertLinks
|
|
482
|
-
const
|
|
497
|
+
const handleInsertLinksImpl = (url) => __awaiter(void 0, void 0, void 0, function* () {
|
|
483
498
|
try {
|
|
484
499
|
console.log(`[Insert Affiliate] Attempting to handle URL: ${url}`);
|
|
485
500
|
if (!url || typeof url !== 'string') {
|
|
@@ -582,14 +597,47 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
582
597
|
return null;
|
|
583
598
|
}
|
|
584
599
|
};
|
|
600
|
+
// Parse shortcode from query parameter (new format: scheme://insert-affiliate?code=SHORTCODE)
|
|
601
|
+
const parseShortCodeFromQuery = (url) => {
|
|
602
|
+
try {
|
|
603
|
+
const queryIndex = url.indexOf('?');
|
|
604
|
+
if (queryIndex !== -1) {
|
|
605
|
+
const queryString = url.substring(queryIndex + 1);
|
|
606
|
+
const params = queryString.split('&');
|
|
607
|
+
for (const param of params) {
|
|
608
|
+
const [key, value] = param.split('=');
|
|
609
|
+
if (key === 'code' && value) {
|
|
610
|
+
return decodeURIComponent(value);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
verboseLog(`Error parsing short code from query: ${error}`);
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
};
|
|
585
621
|
const parseShortCodeFromURLString = (url) => {
|
|
586
622
|
try {
|
|
587
|
-
//
|
|
623
|
+
// First try to extract from query parameter (new format: scheme://insert-affiliate?code=SHORTCODE)
|
|
624
|
+
const queryCode = parseShortCodeFromQuery(url);
|
|
625
|
+
if (queryCode) {
|
|
626
|
+
console.log(`[Insert Affiliate] Found short code in query parameter: ${queryCode}`);
|
|
627
|
+
return queryCode;
|
|
628
|
+
}
|
|
629
|
+
// Fall back to path format (legacy: scheme://SHORTCODE)
|
|
588
630
|
const match = url.match(/^[^:]+:\/\/(.+)$/);
|
|
589
631
|
if (match) {
|
|
590
|
-
|
|
632
|
+
let shortCode = match[1];
|
|
591
633
|
// Remove leading slash if present
|
|
592
|
-
|
|
634
|
+
shortCode = shortCode.startsWith('/') ? shortCode.substring(1) : shortCode;
|
|
635
|
+
// If the path is 'insert-affiliate' (from new format without code param), return null
|
|
636
|
+
if (shortCode === 'insert-affiliate' || shortCode.startsWith('insert-affiliate?')) {
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
console.log(`[Insert Affiliate] Found short code in URL path (legacy format): ${shortCode}`);
|
|
640
|
+
return shortCode;
|
|
593
641
|
}
|
|
594
642
|
return null;
|
|
595
643
|
}
|
|
@@ -609,26 +657,27 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
609
657
|
const clearAsyncStorage = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
610
658
|
yield async_storage_1.default.clear();
|
|
611
659
|
});
|
|
612
|
-
// Helper function to get company code from
|
|
660
|
+
// Helper function to get company code from ref or storage (uses ref to avoid stale closures)
|
|
613
661
|
const getActiveCompanyCode = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
614
662
|
verboseLog('Getting active company code...');
|
|
615
|
-
let activeCompanyCode =
|
|
616
|
-
verboseLog(`Company code in
|
|
663
|
+
let activeCompanyCode = companyCodeRef.current;
|
|
664
|
+
verboseLog(`Company code in ref: ${activeCompanyCode || 'empty'}`);
|
|
617
665
|
if (!activeCompanyCode || (activeCompanyCode.trim() === '' && activeCompanyCode !== null)) {
|
|
618
|
-
verboseLog('Company code not in
|
|
666
|
+
verboseLog('Company code not in ref, checking AsyncStorage...');
|
|
619
667
|
activeCompanyCode = yield getValueFromAsync(ASYNC_KEYS.COMPANY_CODE);
|
|
620
668
|
verboseLog(`Company code in AsyncStorage: ${activeCompanyCode || 'empty'}`);
|
|
621
669
|
if (activeCompanyCode) {
|
|
622
|
-
// Update state for future use
|
|
670
|
+
// Update ref and state for future use
|
|
671
|
+
companyCodeRef.current = activeCompanyCode;
|
|
623
672
|
setCompanyCode(activeCompanyCode);
|
|
624
|
-
verboseLog('Updated React state with company code from storage');
|
|
673
|
+
verboseLog('Updated ref and React state with company code from storage');
|
|
625
674
|
}
|
|
626
675
|
}
|
|
627
676
|
return activeCompanyCode;
|
|
628
677
|
});
|
|
629
|
-
// Helper function for verbose logging
|
|
678
|
+
// Helper function for verbose logging (uses ref to avoid stale closures)
|
|
630
679
|
const verboseLog = (message) => {
|
|
631
|
-
if (
|
|
680
|
+
if (verboseLoggingRef.current) {
|
|
632
681
|
console.log(`[Insert Affiliate] [VERBOSE] ${message}`);
|
|
633
682
|
}
|
|
634
683
|
};
|
|
@@ -1156,7 +1205,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1156
1205
|
return false;
|
|
1157
1206
|
}
|
|
1158
1207
|
});
|
|
1159
|
-
const
|
|
1208
|
+
const getAffiliateDetailsImpl = (affiliateCode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1160
1209
|
try {
|
|
1161
1210
|
const activeCompanyCode = yield getActiveCompanyCode();
|
|
1162
1211
|
if (!activeCompanyCode) {
|
|
@@ -1195,27 +1244,25 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1195
1244
|
return null;
|
|
1196
1245
|
}
|
|
1197
1246
|
});
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
});
|
|
1218
|
-
}
|
|
1247
|
+
const setShortCodeImpl = (shortCode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1248
|
+
console.log('[Insert Affiliate] Setting short code.');
|
|
1249
|
+
yield generateThenSetUserID();
|
|
1250
|
+
// Validate it is a short code
|
|
1251
|
+
const capitalisedShortCode = shortCode.toUpperCase();
|
|
1252
|
+
isShortCode(capitalisedShortCode);
|
|
1253
|
+
// Check if the affiliate exists before storing
|
|
1254
|
+
const exists = yield checkAffiliateExists(capitalisedShortCode);
|
|
1255
|
+
if (exists) {
|
|
1256
|
+
// If affiliate exists, set the Insert Affiliate Identifier
|
|
1257
|
+
yield storeInsertAffiliateIdentifier({ link: capitalisedShortCode, source: 'short_code_manual' });
|
|
1258
|
+
console.log(`[Insert Affiliate] Short code ${capitalisedShortCode} validated and stored successfully.`);
|
|
1259
|
+
return true;
|
|
1260
|
+
}
|
|
1261
|
+
else {
|
|
1262
|
+
console.warn(`[Insert Affiliate] Short code ${capitalisedShortCode} does not exist. Not storing.`);
|
|
1263
|
+
return false;
|
|
1264
|
+
}
|
|
1265
|
+
});
|
|
1219
1266
|
function getOrCreateUserAccountToken() {
|
|
1220
1267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1221
1268
|
let userAccountToken = yield getValueFromAsync(ASYNC_KEYS.USER_ACCOUNT_TOKEN);
|
|
@@ -1227,9 +1274,9 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1227
1274
|
});
|
|
1228
1275
|
}
|
|
1229
1276
|
;
|
|
1230
|
-
const
|
|
1277
|
+
const returnUserAccountTokenAndStoreExpectedTransactionImpl = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1231
1278
|
try {
|
|
1232
|
-
const shortCode = yield
|
|
1279
|
+
const shortCode = yield returnInsertAffiliateIdentifierImpl();
|
|
1233
1280
|
if (!shortCode) {
|
|
1234
1281
|
console.log('[Insert Affiliate] No affiliate stored - not saving expected transaction.');
|
|
1235
1282
|
return null;
|
|
@@ -1241,7 +1288,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1241
1288
|
return null;
|
|
1242
1289
|
}
|
|
1243
1290
|
else {
|
|
1244
|
-
yield
|
|
1291
|
+
yield storeExpectedStoreTransactionImpl(userAccountToken);
|
|
1245
1292
|
return userAccountToken;
|
|
1246
1293
|
}
|
|
1247
1294
|
}
|
|
@@ -1261,12 +1308,12 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1261
1308
|
;
|
|
1262
1309
|
});
|
|
1263
1310
|
// MARK: Return Insert Affiliate Identifier
|
|
1264
|
-
const
|
|
1311
|
+
const returnInsertAffiliateIdentifierImpl = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (ignoreTimeout = false) {
|
|
1265
1312
|
try {
|
|
1266
1313
|
verboseLog(`Getting insert affiliate identifier (ignoreTimeout: ${ignoreTimeout})...`);
|
|
1267
1314
|
// If timeout is enabled and we're not ignoring it, check validity first
|
|
1268
1315
|
if (!ignoreTimeout && affiliateAttributionActiveTime) {
|
|
1269
|
-
const isValid = yield
|
|
1316
|
+
const isValid = yield isAffiliateAttributionValidImpl();
|
|
1270
1317
|
if (!isValid) {
|
|
1271
1318
|
verboseLog('Attribution has expired, returning null');
|
|
1272
1319
|
return null;
|
|
@@ -1306,14 +1353,14 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1306
1353
|
});
|
|
1307
1354
|
// MARK: Attribution Timeout Functions
|
|
1308
1355
|
// Check if the current affiliate attribution is still valid based on timeout
|
|
1309
|
-
const
|
|
1356
|
+
const isAffiliateAttributionValidImpl = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1310
1357
|
try {
|
|
1311
1358
|
// If no timeout is set, attribution is always valid
|
|
1312
1359
|
if (!affiliateAttributionActiveTime) {
|
|
1313
1360
|
verboseLog('No attribution timeout set, attribution is valid');
|
|
1314
1361
|
return true;
|
|
1315
1362
|
}
|
|
1316
|
-
const storedDate = yield
|
|
1363
|
+
const storedDate = yield getAffiliateStoredDateImpl();
|
|
1317
1364
|
if (!storedDate) {
|
|
1318
1365
|
verboseLog('No stored date found, attribution is invalid');
|
|
1319
1366
|
return false;
|
|
@@ -1330,7 +1377,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1330
1377
|
}
|
|
1331
1378
|
});
|
|
1332
1379
|
// Get the date when the affiliate identifier was stored
|
|
1333
|
-
const
|
|
1380
|
+
const getAffiliateStoredDateImpl = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1334
1381
|
try {
|
|
1335
1382
|
const storedDateString = yield getValueFromAsync(ASYNC_KEYS.AFFILIATE_STORED_DATE);
|
|
1336
1383
|
if (!storedDateString) {
|
|
@@ -1347,84 +1394,81 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1347
1394
|
}
|
|
1348
1395
|
});
|
|
1349
1396
|
// MARK: Insert Affiliate Identifier
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
return;
|
|
1373
|
-
}
|
|
1374
|
-
// Check if referring link is already a short code, if so save it and stop here.
|
|
1375
|
-
verboseLog('Checking if referring link is already a short code...');
|
|
1376
|
-
if (isShortCode(referringLink)) {
|
|
1377
|
-
console.log('[Insert Affiliate] Referring link is already a short code.');
|
|
1378
|
-
verboseLog('Link is already a short code, storing directly');
|
|
1379
|
-
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1380
|
-
return `${referringLink}-${customerID}`;
|
|
1381
|
-
}
|
|
1382
|
-
verboseLog('Link is not a short code, will convert via API');
|
|
1383
|
-
// If the code is not already a short code, encode it raedy to send to our endpoint to return the short code. Save it before making the call in case something goes wrong
|
|
1384
|
-
// Encode the referring link
|
|
1385
|
-
verboseLog('Encoding referring link for API call...');
|
|
1386
|
-
const encodedAffiliateLink = encodeURIComponent(referringLink);
|
|
1387
|
-
if (!encodedAffiliateLink) {
|
|
1388
|
-
console.error('[Insert Affiliate] Failed to encode affiliate link.');
|
|
1389
|
-
verboseLog('Failed to encode link, storing original');
|
|
1390
|
-
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1391
|
-
return `${referringLink}-${customerID}`;
|
|
1392
|
-
}
|
|
1393
|
-
// Create the request URL
|
|
1394
|
-
const urlString = `https://api.insertaffiliate.com/V1/convert-deep-link-to-short-link?companyId=${activeCompanyCode}&deepLinkUrl=${encodedAffiliateLink}`;
|
|
1395
|
-
console.log('[Insert Affiliate] urlString .', urlString);
|
|
1396
|
-
verboseLog('Making API request to convert deep link to short code...');
|
|
1397
|
-
const response = yield axios_1.default.get(urlString, {
|
|
1398
|
-
headers: {
|
|
1399
|
-
'Content-Type': 'application/json',
|
|
1400
|
-
},
|
|
1401
|
-
});
|
|
1402
|
-
verboseLog(`API response status: ${response.status}`);
|
|
1403
|
-
// Call to the backend for the short code and save the resolse in valid
|
|
1404
|
-
if (response.status === 200 && response.data.shortLink) {
|
|
1405
|
-
const shortLink = response.data.shortLink;
|
|
1406
|
-
console.log('[Insert Affiliate] Short link received:', shortLink);
|
|
1407
|
-
verboseLog(`Successfully converted to short link: ${shortLink}`);
|
|
1408
|
-
verboseLog('Storing short link to AsyncStorage...');
|
|
1409
|
-
yield storeInsertAffiliateIdentifier({ link: shortLink, source: 'referring_link' });
|
|
1410
|
-
verboseLog('Short link stored successfully');
|
|
1411
|
-
return `${shortLink}-${customerID}`;
|
|
1412
|
-
}
|
|
1413
|
-
else {
|
|
1414
|
-
console.warn('[Insert Affiliate] Unexpected response format.');
|
|
1415
|
-
verboseLog(`Unexpected API response. Status: ${response.status}, Data: ${JSON.stringify(response.data)}`);
|
|
1416
|
-
verboseLog('Storing original link as fallback');
|
|
1417
|
-
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1418
|
-
return `${referringLink}-${customerID}`;
|
|
1419
|
-
}
|
|
1397
|
+
const setInsertAffiliateIdentifierImpl = (referringLink) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1398
|
+
console.log('[Insert Affiliate] Setting affiliate identifier.');
|
|
1399
|
+
verboseLog(`Input referringLink: ${referringLink}`);
|
|
1400
|
+
try {
|
|
1401
|
+
verboseLog('Generating or retrieving user ID...');
|
|
1402
|
+
const customerID = yield generateThenSetUserID();
|
|
1403
|
+
console.log('[Insert Affiliate] Completed generateThenSetUserID within setInsertAffiliateIdentifier.');
|
|
1404
|
+
verboseLog(`Customer ID: ${customerID}`);
|
|
1405
|
+
if (!referringLink) {
|
|
1406
|
+
console.warn('[Insert Affiliate] Referring link is invalid.');
|
|
1407
|
+
verboseLog('Referring link is empty or invalid, storing as-is');
|
|
1408
|
+
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1409
|
+
return `${referringLink}-${customerID}`;
|
|
1410
|
+
}
|
|
1411
|
+
// Get company code from state or storage
|
|
1412
|
+
verboseLog('Getting company code...');
|
|
1413
|
+
const activeCompanyCode = yield getActiveCompanyCode();
|
|
1414
|
+
verboseLog(`Active company code: ${activeCompanyCode || 'Not found'}`);
|
|
1415
|
+
if (!activeCompanyCode) {
|
|
1416
|
+
console.error('[Insert Affiliate] Company code is not set. Please initialize the SDK with a valid company code.');
|
|
1417
|
+
verboseLog('Company code missing, cannot proceed with API call');
|
|
1418
|
+
return;
|
|
1420
1419
|
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1420
|
+
// Check if referring link is already a short code, if so save it and stop here.
|
|
1421
|
+
verboseLog('Checking if referring link is already a short code...');
|
|
1422
|
+
if (isShortCode(referringLink)) {
|
|
1423
|
+
console.log('[Insert Affiliate] Referring link is already a short code.');
|
|
1424
|
+
verboseLog('Link is already a short code, storing directly');
|
|
1425
|
+
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1426
|
+
return `${referringLink}-${customerID}`;
|
|
1427
|
+
}
|
|
1428
|
+
verboseLog('Link is not a short code, will convert via API');
|
|
1429
|
+
// If the code is not already a short code, encode it raedy to send to our endpoint to return the short code. Save it before making the call in case something goes wrong
|
|
1430
|
+
// Encode the referring link
|
|
1431
|
+
verboseLog('Encoding referring link for API call...');
|
|
1432
|
+
const encodedAffiliateLink = encodeURIComponent(referringLink);
|
|
1433
|
+
if (!encodedAffiliateLink) {
|
|
1434
|
+
console.error('[Insert Affiliate] Failed to encode affiliate link.');
|
|
1435
|
+
verboseLog('Failed to encode link, storing original');
|
|
1436
|
+
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1437
|
+
return `${referringLink}-${customerID}`;
|
|
1438
|
+
}
|
|
1439
|
+
// Create the request URL
|
|
1440
|
+
const urlString = `https://api.insertaffiliate.com/V1/convert-deep-link-to-short-link?companyId=${activeCompanyCode}&deepLinkUrl=${encodedAffiliateLink}`;
|
|
1441
|
+
console.log('[Insert Affiliate] urlString .', urlString);
|
|
1442
|
+
verboseLog('Making API request to convert deep link to short code...');
|
|
1443
|
+
const response = yield axios_1.default.get(urlString, {
|
|
1444
|
+
headers: {
|
|
1445
|
+
'Content-Type': 'application/json',
|
|
1446
|
+
},
|
|
1447
|
+
});
|
|
1448
|
+
verboseLog(`API response status: ${response.status}`);
|
|
1449
|
+
// Call to the backend for the short code and save the resolse in valid
|
|
1450
|
+
if (response.status === 200 && response.data.shortLink) {
|
|
1451
|
+
const shortLink = response.data.shortLink;
|
|
1452
|
+
console.log('[Insert Affiliate] Short link received:', shortLink);
|
|
1453
|
+
verboseLog(`Successfully converted to short link: ${shortLink}`);
|
|
1454
|
+
verboseLog('Storing short link to AsyncStorage...');
|
|
1455
|
+
yield storeInsertAffiliateIdentifier({ link: shortLink, source: 'referring_link' });
|
|
1456
|
+
verboseLog('Short link stored successfully');
|
|
1457
|
+
return `${shortLink}-${customerID}`;
|
|
1424
1458
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1459
|
+
else {
|
|
1460
|
+
console.warn('[Insert Affiliate] Unexpected response format.');
|
|
1461
|
+
verboseLog(`Unexpected API response. Status: ${response.status}, Data: ${JSON.stringify(response.data)}`);
|
|
1462
|
+
verboseLog('Storing original link as fallback');
|
|
1463
|
+
yield storeInsertAffiliateIdentifier({ link: referringLink, source: 'referring_link' });
|
|
1464
|
+
return `${referringLink}-${customerID}`;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
catch (error) {
|
|
1468
|
+
console.error('[Insert Affiliate] Error:', error);
|
|
1469
|
+
verboseLog(`Error in setInsertAffiliateIdentifier: ${error}`);
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1428
1472
|
function storeInsertAffiliateIdentifier(_a) {
|
|
1429
1473
|
return __awaiter(this, arguments, void 0, function* ({ link, source }) {
|
|
1430
1474
|
console.log(`[Insert Affiliate] Storing affiliate identifier: ${link} (source: ${source})`);
|
|
@@ -1448,18 +1492,18 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1448
1492
|
yield retrieveAndStoreOfferCode(link);
|
|
1449
1493
|
// Trigger callback with the current affiliate identifier
|
|
1450
1494
|
if (insertAffiliateIdentifierChangeCallbackRef.current) {
|
|
1451
|
-
const currentIdentifier = yield
|
|
1495
|
+
const currentIdentifier = yield returnInsertAffiliateIdentifierImpl();
|
|
1452
1496
|
verboseLog(`Triggering callback with identifier: ${currentIdentifier}`);
|
|
1453
1497
|
insertAffiliateIdentifierChangeCallbackRef.current(currentIdentifier);
|
|
1454
1498
|
}
|
|
1455
1499
|
// Report this new affiliate association to the backend (fire and forget)
|
|
1456
|
-
const fullIdentifier = yield
|
|
1500
|
+
const fullIdentifier = yield returnInsertAffiliateIdentifierImpl();
|
|
1457
1501
|
if (fullIdentifier) {
|
|
1458
1502
|
reportAffiliateAssociationIfNeeded(fullIdentifier, source);
|
|
1459
1503
|
}
|
|
1460
1504
|
});
|
|
1461
1505
|
}
|
|
1462
|
-
const
|
|
1506
|
+
const validatePurchaseWithIapticAPIImpl = (jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1463
1507
|
var _a;
|
|
1464
1508
|
try {
|
|
1465
1509
|
// Check for E_IAP_NOT_AVAILABLE error in development environment
|
|
@@ -1498,7 +1542,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1498
1542
|
};
|
|
1499
1543
|
}
|
|
1500
1544
|
const requestBody = Object.assign(Object.assign({}, baseRequestBody), { transaction });
|
|
1501
|
-
let insertAffiliateIdentifier = yield
|
|
1545
|
+
let insertAffiliateIdentifier = yield returnInsertAffiliateIdentifierImpl();
|
|
1502
1546
|
if (insertAffiliateIdentifier) {
|
|
1503
1547
|
requestBody.additionalData = {
|
|
1504
1548
|
applicationUsername: `${insertAffiliateIdentifier}`,
|
|
@@ -1545,7 +1589,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1545
1589
|
return false;
|
|
1546
1590
|
}
|
|
1547
1591
|
});
|
|
1548
|
-
const
|
|
1592
|
+
const storeExpectedStoreTransactionImpl = (purchaseToken) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1549
1593
|
verboseLog(`Storing expected store transaction with token: ${purchaseToken}`);
|
|
1550
1594
|
const activeCompanyCode = yield getActiveCompanyCode();
|
|
1551
1595
|
if (!activeCompanyCode) {
|
|
@@ -1553,7 +1597,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1553
1597
|
verboseLog("Cannot store transaction: no company code available");
|
|
1554
1598
|
return;
|
|
1555
1599
|
}
|
|
1556
|
-
const shortCode = yield
|
|
1600
|
+
const shortCode = yield returnInsertAffiliateIdentifierImpl();
|
|
1557
1601
|
if (!shortCode) {
|
|
1558
1602
|
console.error("[Insert Affiliate] No affiliate identifier found. Please set one before tracking events.");
|
|
1559
1603
|
verboseLog("Cannot store transaction: no affiliate identifier available");
|
|
@@ -1594,7 +1638,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1594
1638
|
}
|
|
1595
1639
|
});
|
|
1596
1640
|
// MARK: Track Event
|
|
1597
|
-
const
|
|
1641
|
+
const trackEventImpl = (eventName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1598
1642
|
try {
|
|
1599
1643
|
verboseLog(`Tracking event: ${eventName}`);
|
|
1600
1644
|
const activeCompanyCode = yield getActiveCompanyCode();
|
|
@@ -1715,6 +1759,64 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
1715
1759
|
// Remove special characters, keep only alphanumeric
|
|
1716
1760
|
return removeSpecialCharacters(offerCode);
|
|
1717
1761
|
};
|
|
1762
|
+
// ============================================================================
|
|
1763
|
+
// REF CALLBACK PATTERN: Update refs on every render for fresh closures
|
|
1764
|
+
// ============================================================================
|
|
1765
|
+
initializeImplRef.current = initializeImpl;
|
|
1766
|
+
setShortCodeImplRef.current = setShortCodeImpl;
|
|
1767
|
+
getAffiliateDetailsImplRef.current = getAffiliateDetailsImpl;
|
|
1768
|
+
returnInsertAffiliateIdentifierImplRef.current = returnInsertAffiliateIdentifierImpl;
|
|
1769
|
+
isAffiliateAttributionValidImplRef.current = isAffiliateAttributionValidImpl;
|
|
1770
|
+
getAffiliateStoredDateImplRef.current = getAffiliateStoredDateImpl;
|
|
1771
|
+
storeExpectedStoreTransactionImplRef.current = storeExpectedStoreTransactionImpl;
|
|
1772
|
+
returnUserAccountTokenAndStoreExpectedTransactionImplRef.current = returnUserAccountTokenAndStoreExpectedTransactionImpl;
|
|
1773
|
+
validatePurchaseWithIapticAPIImplRef.current = validatePurchaseWithIapticAPIImpl;
|
|
1774
|
+
trackEventImplRef.current = trackEventImpl;
|
|
1775
|
+
setInsertAffiliateIdentifierImplRef.current = setInsertAffiliateIdentifierImpl;
|
|
1776
|
+
handleInsertLinksImplRef.current = handleInsertLinksImpl;
|
|
1777
|
+
// ============================================================================
|
|
1778
|
+
// STABLE WRAPPERS: useCallback with [] deps that delegate to refs
|
|
1779
|
+
// These provide stable function references that always call current implementations
|
|
1780
|
+
// ============================================================================
|
|
1781
|
+
const initialize = (0, react_1.useCallback)((code, verboseLogging, insertLinksEnabled, insertLinksClipboardEnabled, affiliateAttributionActiveTime) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1782
|
+
return initializeImplRef.current(code, verboseLogging, insertLinksEnabled, insertLinksClipboardEnabled, affiliateAttributionActiveTime);
|
|
1783
|
+
}), []);
|
|
1784
|
+
const setShortCode = (0, react_1.useCallback)((shortCode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1785
|
+
return setShortCodeImplRef.current(shortCode);
|
|
1786
|
+
}), []);
|
|
1787
|
+
const getAffiliateDetails = (0, react_1.useCallback)((affiliateCode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1788
|
+
return getAffiliateDetailsImplRef.current(affiliateCode);
|
|
1789
|
+
}), []);
|
|
1790
|
+
const returnInsertAffiliateIdentifier = (0, react_1.useCallback)((ignoreTimeout) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1791
|
+
return returnInsertAffiliateIdentifierImplRef.current(ignoreTimeout);
|
|
1792
|
+
}), []);
|
|
1793
|
+
const isAffiliateAttributionValid = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
1794
|
+
return isAffiliateAttributionValidImplRef.current();
|
|
1795
|
+
}), []);
|
|
1796
|
+
const getAffiliateStoredDate = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
1797
|
+
return getAffiliateStoredDateImplRef.current();
|
|
1798
|
+
}), []);
|
|
1799
|
+
const storeExpectedStoreTransaction = (0, react_1.useCallback)((purchaseToken) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1800
|
+
return storeExpectedStoreTransactionImplRef.current(purchaseToken);
|
|
1801
|
+
}), []);
|
|
1802
|
+
const returnUserAccountTokenAndStoreExpectedTransaction = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
1803
|
+
return returnUserAccountTokenAndStoreExpectedTransactionImplRef.current();
|
|
1804
|
+
}), []);
|
|
1805
|
+
const validatePurchaseWithIapticAPI = (0, react_1.useCallback)((jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1806
|
+
return validatePurchaseWithIapticAPIImplRef.current(jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey);
|
|
1807
|
+
}), []);
|
|
1808
|
+
const trackEvent = (0, react_1.useCallback)((eventName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1809
|
+
return trackEventImplRef.current(eventName);
|
|
1810
|
+
}), []);
|
|
1811
|
+
const setInsertAffiliateIdentifier = (0, react_1.useCallback)((referringLink) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1812
|
+
return setInsertAffiliateIdentifierImplRef.current(referringLink);
|
|
1813
|
+
}), []);
|
|
1814
|
+
const setInsertAffiliateIdentifierChangeCallbackHandler = (0, react_1.useCallback)((callback) => {
|
|
1815
|
+
insertAffiliateIdentifierChangeCallbackRef.current = callback;
|
|
1816
|
+
}, []);
|
|
1817
|
+
const handleInsertLinks = (0, react_1.useCallback)((url) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1818
|
+
return handleInsertLinksImplRef.current(url);
|
|
1819
|
+
}), []);
|
|
1718
1820
|
return (react_1.default.createElement(exports.DeepLinkIapContext.Provider, { value: {
|
|
1719
1821
|
referrerLink,
|
|
1720
1822
|
userId,
|