insert-affiliate-react-native-sdk 1.3.5 → 1.4.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/dist/DeepLinkIapProvider.d.ts +2 -2
- package/dist/DeepLinkIapProvider.js +80 -61
- package/dist/useDeepLinkIapProvider.d.ts +1 -1
- package/package.json +1 -1
- package/readme.md +2 -3
- package/src/DeepLinkIapProvider.tsx +105 -77
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
2
|
type T_DEEPLINK_IAP_PROVIDER = {
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
};
|
|
@@ -12,7 +12,7 @@ type T_DEEPLINK_IAP_CONTEXT = {
|
|
|
12
12
|
validatePurchaseWithIapticAPI: (jsonIapPurchase: CustomPurchase, iapticAppId: string, iapticAppName: string, iapticPublicKey: string) => Promise<boolean>;
|
|
13
13
|
trackEvent: (eventName: string) => Promise<void>;
|
|
14
14
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
15
|
-
setInsertAffiliateIdentifier: (referringLink: string) => Promise<void>;
|
|
15
|
+
setInsertAffiliateIdentifier: (referringLink: string) => Promise<void | string>;
|
|
16
16
|
initialize: (code: string | null) => Promise<void>;
|
|
17
17
|
isInitialized: boolean;
|
|
18
18
|
};
|
|
@@ -15,13 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
36
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
37
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -41,42 +51,42 @@ const react_native_1 = require("react-native");
|
|
|
41
51
|
const axios_1 = __importDefault(require("axios"));
|
|
42
52
|
const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
|
|
43
53
|
const ASYNC_KEYS = {
|
|
44
|
-
REFERRER_LINK:
|
|
45
|
-
USER_PURCHASE:
|
|
46
|
-
USER_ID:
|
|
47
|
-
COMPANY_CODE:
|
|
54
|
+
REFERRER_LINK: '@app_referrer_link',
|
|
55
|
+
USER_PURCHASE: '@app_user_purchase',
|
|
56
|
+
USER_ID: '@app_user_id',
|
|
57
|
+
COMPANY_CODE: '@app_company_code',
|
|
48
58
|
};
|
|
49
59
|
// STARTING CONTEXT IMPLEMENTATION
|
|
50
60
|
exports.DeepLinkIapContext = (0, react_1.createContext)({
|
|
51
|
-
referrerLink:
|
|
52
|
-
userId:
|
|
53
|
-
returnInsertAffiliateIdentifier: () => __awaiter(void 0, void 0, void 0, function* () { return
|
|
61
|
+
referrerLink: '',
|
|
62
|
+
userId: '',
|
|
63
|
+
returnInsertAffiliateIdentifier: () => __awaiter(void 0, void 0, void 0, function* () { return ''; }),
|
|
54
64
|
validatePurchaseWithIapticAPI: (jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey) => __awaiter(void 0, void 0, void 0, function* () { return false; }),
|
|
55
65
|
trackEvent: (eventName) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
56
66
|
setShortCode: (shortCode) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
57
67
|
setInsertAffiliateIdentifier: (referringLink) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
58
68
|
initialize: (code) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
59
|
-
isInitialized: false
|
|
69
|
+
isInitialized: false,
|
|
60
70
|
});
|
|
61
71
|
const DeepLinkIapProvider = ({ children, }) => {
|
|
62
|
-
const [referrerLink, setReferrerLink] = (0, react_1.useState)(
|
|
63
|
-
const [userId, setUserId] = (0, react_1.useState)(
|
|
72
|
+
const [referrerLink, setReferrerLink] = (0, react_1.useState)('');
|
|
73
|
+
const [userId, setUserId] = (0, react_1.useState)('');
|
|
64
74
|
const [companyCode, setCompanyCode] = (0, react_1.useState)(null);
|
|
65
75
|
const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
|
|
66
76
|
// MARK: Initialize the SDK
|
|
67
77
|
const initialize = (companyCode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
68
78
|
if (isInitialized) {
|
|
69
|
-
console.error(
|
|
79
|
+
console.error('[Insert Affiliate] SDK is already initialized.');
|
|
70
80
|
return;
|
|
71
81
|
}
|
|
72
|
-
if (companyCode && companyCode.trim() !==
|
|
82
|
+
if (companyCode && companyCode.trim() !== '') {
|
|
73
83
|
setCompanyCode(companyCode);
|
|
74
84
|
yield saveValueInAsync(ASYNC_KEYS.COMPANY_CODE, companyCode);
|
|
75
85
|
setIsInitialized(true);
|
|
76
86
|
console.log(`[Insert Affiliate] SDK initialized with company code: ${companyCode}`);
|
|
77
87
|
}
|
|
78
88
|
else {
|
|
79
|
-
console.warn(
|
|
89
|
+
console.warn('[Insert Affiliate] SDK initialized without a company code.');
|
|
80
90
|
setIsInitialized(true);
|
|
81
91
|
}
|
|
82
92
|
});
|
|
@@ -103,14 +113,18 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
103
113
|
let userId = yield getValueFromAsync(ASYNC_KEYS.USER_ID);
|
|
104
114
|
if (!userId) {
|
|
105
115
|
userId = generateUserID();
|
|
116
|
+
setUserId(userId);
|
|
106
117
|
yield saveValueInAsync(ASYNC_KEYS.USER_ID, userId);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
107
120
|
setUserId(userId);
|
|
108
121
|
}
|
|
122
|
+
return userId;
|
|
109
123
|
});
|
|
110
124
|
}
|
|
111
125
|
const generateUserID = () => {
|
|
112
|
-
const characters =
|
|
113
|
-
let uniqueId =
|
|
126
|
+
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
127
|
+
let uniqueId = '';
|
|
114
128
|
for (let i = 0; i < 6; i++) {
|
|
115
129
|
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
116
130
|
uniqueId += characters[randomIndex];
|
|
@@ -120,7 +134,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
120
134
|
const reset = () => {
|
|
121
135
|
setCompanyCode(null);
|
|
122
136
|
setIsInitialized(false);
|
|
123
|
-
console.log(
|
|
137
|
+
console.log('[Insert Affiliate] SDK has been reset.');
|
|
124
138
|
};
|
|
125
139
|
// Helper funciton Storage / Retrieval
|
|
126
140
|
const saveValueInAsync = (key, value) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -136,10 +150,10 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
136
150
|
// Helper function to log errors
|
|
137
151
|
const errorLog = (message, type) => {
|
|
138
152
|
switch (type) {
|
|
139
|
-
case
|
|
153
|
+
case 'error':
|
|
140
154
|
console.error(`ENCOUNTER ERROR ~ ${message}`);
|
|
141
155
|
break;
|
|
142
|
-
case
|
|
156
|
+
case 'warn':
|
|
143
157
|
console.warn(`ENCOUNTER WARNING ~ ${message}`);
|
|
144
158
|
break;
|
|
145
159
|
default:
|
|
@@ -155,8 +169,8 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
155
169
|
};
|
|
156
170
|
function setShortCode(shortCode) {
|
|
157
171
|
return __awaiter(this, void 0, void 0, function* () {
|
|
158
|
-
console.log(
|
|
159
|
-
generateThenSetUserID();
|
|
172
|
+
console.log('[Insert Affiliate] Setting short code.');
|
|
173
|
+
yield generateThenSetUserID();
|
|
160
174
|
// Validate it is a short code
|
|
161
175
|
const capitalisedShortCode = shortCode.toUpperCase();
|
|
162
176
|
isShortCode(capitalisedShortCode);
|
|
@@ -177,60 +191,65 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
177
191
|
// MARK: Insert Affiliate Identifier
|
|
178
192
|
function setInsertAffiliateIdentifier(referringLink) {
|
|
179
193
|
return __awaiter(this, void 0, void 0, function* () {
|
|
180
|
-
console.log(
|
|
194
|
+
console.log('[Insert Affiliate] Setting affiliate identifier.');
|
|
181
195
|
try {
|
|
182
|
-
yield generateThenSetUserID();
|
|
183
|
-
console.log(
|
|
196
|
+
const customerID = yield generateThenSetUserID();
|
|
197
|
+
console.log('[Insert Affiliate] Completed generateThenSetUserID within setInsertAffiliateIdentifier.');
|
|
184
198
|
if (!referringLink) {
|
|
185
|
-
console.warn(
|
|
199
|
+
console.warn('[Insert Affiliate] Referring link is invalid.');
|
|
200
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
186
201
|
yield storeInsertAffiliateIdentifier({ link: referringLink });
|
|
187
|
-
return
|
|
202
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
188
203
|
}
|
|
189
|
-
if (!companyCode || companyCode.trim() ===
|
|
204
|
+
if (!companyCode || (companyCode.trim() === '' && companyCode !== null)) {
|
|
190
205
|
let companyCodeFromStorage = yield getValueFromAsync(ASYNC_KEYS.COMPANY_CODE);
|
|
191
206
|
if (companyCodeFromStorage !== null) {
|
|
192
207
|
setCompanyCode(companyCodeFromStorage);
|
|
193
208
|
}
|
|
194
209
|
else {
|
|
195
|
-
console.error(
|
|
210
|
+
console.error('[Insert Affiliate] Company code is not set. Please initialize the SDK with a valid company code.');
|
|
196
211
|
return;
|
|
197
212
|
}
|
|
198
213
|
}
|
|
199
214
|
// Check if referring link is already a short code, if so save it and stop here.
|
|
200
215
|
if (isShortCode(referringLink)) {
|
|
201
|
-
console.log(
|
|
216
|
+
console.log('[Insert Affiliate] Referring link is already a short code.');
|
|
217
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
202
218
|
yield storeInsertAffiliateIdentifier({ link: referringLink });
|
|
203
|
-
return
|
|
219
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
204
220
|
}
|
|
205
221
|
// 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
|
|
206
222
|
// Encode the referring link
|
|
207
223
|
const encodedAffiliateLink = encodeURIComponent(referringLink);
|
|
208
224
|
if (!encodedAffiliateLink) {
|
|
209
|
-
console.error(
|
|
225
|
+
console.error('[Insert Affiliate] Failed to encode affiliate link.');
|
|
226
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
210
227
|
yield storeInsertAffiliateIdentifier({ link: referringLink });
|
|
211
|
-
return
|
|
228
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
212
229
|
}
|
|
213
230
|
// Create the request URL
|
|
214
231
|
const urlString = `https://api.insertaffiliate.com/V1/convert-deep-link-to-short-link?companyId=${companyCode}&deepLinkUrl=${encodedAffiliateLink}`;
|
|
215
|
-
console.log(
|
|
232
|
+
console.log('[Insert Affiliate] urlString .', urlString);
|
|
216
233
|
const response = yield axios_1.default.get(urlString, {
|
|
217
234
|
headers: {
|
|
218
|
-
|
|
235
|
+
'Content-Type': 'application/json',
|
|
219
236
|
},
|
|
220
237
|
});
|
|
221
238
|
// Call to the backend for the short code and save the resolse in valid
|
|
222
239
|
if (response.status === 200 && response.data.shortLink) {
|
|
223
240
|
const shortLink = response.data.shortLink;
|
|
224
|
-
console.log(
|
|
225
|
-
|
|
241
|
+
console.log('[Insert Affiliate] Short link received:', shortLink);
|
|
242
|
+
return `${shortLink}-${customerID}`;
|
|
226
243
|
}
|
|
227
244
|
else {
|
|
228
|
-
console.warn(
|
|
245
|
+
console.warn('[Insert Affiliate] Unexpected response format.');
|
|
246
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
229
247
|
yield storeInsertAffiliateIdentifier({ link: referringLink });
|
|
248
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
230
249
|
}
|
|
231
250
|
}
|
|
232
251
|
catch (error) {
|
|
233
|
-
console.error(
|
|
252
|
+
console.error('[Insert Affiliate] Error:', error);
|
|
234
253
|
}
|
|
235
254
|
});
|
|
236
255
|
}
|
|
@@ -238,29 +257,29 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
238
257
|
function storeInsertAffiliateIdentifier(_a) {
|
|
239
258
|
return __awaiter(this, arguments, void 0, function* ({ link }) {
|
|
240
259
|
console.log(`[Insert Affiliate] Storing affiliate identifier: ${link}`);
|
|
241
|
-
yield saveValueInAsync(ASYNC_KEYS.REFERRER_LINK, link);
|
|
242
260
|
setReferrerLink(link);
|
|
261
|
+
yield saveValueInAsync(ASYNC_KEYS.REFERRER_LINK, link);
|
|
243
262
|
});
|
|
244
263
|
}
|
|
245
264
|
const validatePurchaseWithIapticAPI = (jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
246
265
|
try {
|
|
247
266
|
const baseRequestBody = {
|
|
248
267
|
id: iapticAppId,
|
|
249
|
-
type:
|
|
268
|
+
type: 'application',
|
|
250
269
|
};
|
|
251
270
|
let transaction;
|
|
252
|
-
if (react_native_1.Platform.OS ===
|
|
271
|
+
if (react_native_1.Platform.OS === 'ios') {
|
|
253
272
|
transaction = {
|
|
254
273
|
id: iapticAppId,
|
|
255
|
-
type:
|
|
274
|
+
type: 'ios-appstore',
|
|
256
275
|
appStoreReceipt: jsonIapPurchase.transactionReceipt,
|
|
257
276
|
};
|
|
258
277
|
}
|
|
259
278
|
else {
|
|
260
|
-
const receiptJson = JSON.parse(atob(jsonIapPurchase.transactionReceipt ||
|
|
279
|
+
const receiptJson = JSON.parse(atob(jsonIapPurchase.transactionReceipt || ''));
|
|
261
280
|
transaction = {
|
|
262
281
|
id: receiptJson.orderId, // Extracted orderId
|
|
263
|
-
type:
|
|
282
|
+
type: 'android-playstore',
|
|
264
283
|
purchaseToken: receiptJson.purchaseToken, // Extracted purchase token
|
|
265
284
|
receipt: jsonIapPurchase.transactionReceipt, // Full receipt (Base64)
|
|
266
285
|
signature: receiptJson.signature, // Receipt signature
|
|
@@ -276,19 +295,19 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
276
295
|
// Send validation request to server
|
|
277
296
|
const response = yield (0, axios_1.default)({
|
|
278
297
|
url: `https://validator.iaptic.com/v1/validate`,
|
|
279
|
-
method:
|
|
298
|
+
method: 'POST',
|
|
280
299
|
headers: {
|
|
281
300
|
Authorization: `Basic ${btoa(`${iapticAppName}:${iapticPublicKey}`)}`,
|
|
282
|
-
|
|
301
|
+
'Content-Type': 'application/json',
|
|
283
302
|
},
|
|
284
303
|
data: requestBody,
|
|
285
304
|
});
|
|
286
305
|
if (response.status === 200) {
|
|
287
|
-
console.log(
|
|
306
|
+
console.log('Validation successful:', response.data);
|
|
288
307
|
return true;
|
|
289
308
|
}
|
|
290
309
|
else {
|
|
291
|
-
console.error(
|
|
310
|
+
console.error('Validation failed:', response.data);
|
|
292
311
|
return false;
|
|
293
312
|
}
|
|
294
313
|
}
|
|
@@ -302,29 +321,29 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
302
321
|
return false;
|
|
303
322
|
}
|
|
304
323
|
});
|
|
305
|
-
// MARK: Track Event
|
|
324
|
+
// MARK: Track Event
|
|
306
325
|
const trackEvent = (eventName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
307
326
|
try {
|
|
308
327
|
if (!referrerLink || !userId) {
|
|
309
|
-
console.warn(
|
|
328
|
+
console.warn('[Insert Affiliate] No affiliate identifier found. Please set one before tracking events.');
|
|
310
329
|
return Promise.resolve();
|
|
311
330
|
}
|
|
312
331
|
const payload = {
|
|
313
332
|
eventName,
|
|
314
333
|
deepLinkParam: `${referrerLink}/${userId}`,
|
|
315
334
|
};
|
|
316
|
-
const response = yield axios_1.default.post(
|
|
317
|
-
headers: {
|
|
335
|
+
const response = yield axios_1.default.post('https://api.insertaffiliate.com/v1/trackEvent', payload, {
|
|
336
|
+
headers: { 'Content-Type': 'application/json' },
|
|
318
337
|
});
|
|
319
338
|
if (response.status === 200) {
|
|
320
|
-
console.log(
|
|
339
|
+
console.log('[Insert Affiliate] Event tracked successfully');
|
|
321
340
|
}
|
|
322
341
|
else {
|
|
323
342
|
console.error(`[Insert Affiliate] Failed to track event with status code: ${response.status}`);
|
|
324
343
|
}
|
|
325
344
|
}
|
|
326
345
|
catch (error) {
|
|
327
|
-
console.error(
|
|
346
|
+
console.error('[Insert Affiliate] Error tracking event:', error);
|
|
328
347
|
return Promise.reject(error);
|
|
329
348
|
}
|
|
330
349
|
});
|
|
@@ -337,7 +356,7 @@ const DeepLinkIapProvider = ({ children, }) => {
|
|
|
337
356
|
trackEvent,
|
|
338
357
|
setInsertAffiliateIdentifier,
|
|
339
358
|
initialize,
|
|
340
|
-
isInitialized
|
|
359
|
+
isInitialized,
|
|
341
360
|
} }, children));
|
|
342
361
|
};
|
|
343
362
|
exports.default = DeepLinkIapProvider;
|
|
@@ -7,7 +7,7 @@ declare const useDeepLinkIapProvider: () => {
|
|
|
7
7
|
returnInsertAffiliateIdentifier: () => Promise<string | null>;
|
|
8
8
|
trackEvent: (eventName: string) => Promise<void>;
|
|
9
9
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
10
|
-
setInsertAffiliateIdentifier: (referringLink: string) => Promise<void>;
|
|
10
|
+
setInsertAffiliateIdentifier: (referringLink: string) => Promise<void | string>;
|
|
11
11
|
initialize: (code: string | null) => Promise<void>;
|
|
12
12
|
isInitialized: boolean;
|
|
13
13
|
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -226,7 +226,7 @@ After setting up your Branch integration, add the following code to your ```App.
|
|
|
226
226
|
import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
227
227
|
|
|
228
228
|
//...
|
|
229
|
-
const {setInsertAffiliateIdentifier
|
|
229
|
+
const {setInsertAffiliateIdentifier} = useDeepLinkIapProvider();
|
|
230
230
|
|
|
231
231
|
useEffect(() => {
|
|
232
232
|
if (!isInitialized) return;
|
|
@@ -244,9 +244,8 @@ import { useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
|
244
244
|
const referringLink = params['~referring_link'];
|
|
245
245
|
if (referringLink) {
|
|
246
246
|
try {
|
|
247
|
-
|
|
247
|
+
let insertAffiliateIdentifier = await setInsertAffiliateIdentifier(referringLink);
|
|
248
248
|
|
|
249
|
-
let insertAffiliateIdentifier = await returnInsertAffiliateIdentifier();
|
|
250
249
|
if (insertAffiliateIdentifier) {
|
|
251
250
|
const { customerInfo, created } = await Purchases.logIn(insertAffiliateIdentifier);
|
|
252
251
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React, { createContext, useEffect, useState } from
|
|
2
|
-
import { Platform } from
|
|
3
|
-
import axios from
|
|
4
|
-
import AsyncStorage from
|
|
1
|
+
import React, { createContext, useEffect, useState } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
5
5
|
|
|
6
6
|
// TYPES USED IN THIS PROVIDER
|
|
7
7
|
type T_DEEPLINK_IAP_PROVIDER = {
|
|
@@ -24,7 +24,9 @@ type T_DEEPLINK_IAP_CONTEXT = {
|
|
|
24
24
|
) => Promise<boolean>;
|
|
25
25
|
trackEvent: (eventName: string) => Promise<void>;
|
|
26
26
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
27
|
-
setInsertAffiliateIdentifier: (
|
|
27
|
+
setInsertAffiliateIdentifier: (
|
|
28
|
+
referringLink: string
|
|
29
|
+
) => Promise<void | string>;
|
|
28
30
|
initialize: (code: string | null) => Promise<void>;
|
|
29
31
|
isInitialized: boolean;
|
|
30
32
|
};
|
|
@@ -46,17 +48,17 @@ type RequestBody = {
|
|
|
46
48
|
};
|
|
47
49
|
|
|
48
50
|
const ASYNC_KEYS = {
|
|
49
|
-
REFERRER_LINK:
|
|
50
|
-
USER_PURCHASE:
|
|
51
|
-
USER_ID:
|
|
52
|
-
COMPANY_CODE:
|
|
51
|
+
REFERRER_LINK: '@app_referrer_link',
|
|
52
|
+
USER_PURCHASE: '@app_user_purchase',
|
|
53
|
+
USER_ID: '@app_user_id',
|
|
54
|
+
COMPANY_CODE: '@app_company_code',
|
|
53
55
|
};
|
|
54
56
|
|
|
55
57
|
// STARTING CONTEXT IMPLEMENTATION
|
|
56
58
|
export const DeepLinkIapContext = createContext<T_DEEPLINK_IAP_CONTEXT>({
|
|
57
|
-
referrerLink:
|
|
58
|
-
userId:
|
|
59
|
-
returnInsertAffiliateIdentifier: async () =>
|
|
59
|
+
referrerLink: '',
|
|
60
|
+
userId: '',
|
|
61
|
+
returnInsertAffiliateIdentifier: async () => '',
|
|
60
62
|
validatePurchaseWithIapticAPI: async (
|
|
61
63
|
jsonIapPurchase: CustomPurchase,
|
|
62
64
|
iapticAppId: string,
|
|
@@ -67,31 +69,35 @@ export const DeepLinkIapContext = createContext<T_DEEPLINK_IAP_CONTEXT>({
|
|
|
67
69
|
setShortCode: async (shortCode: string) => {},
|
|
68
70
|
setInsertAffiliateIdentifier: async (referringLink: string) => {},
|
|
69
71
|
initialize: async (code: string | null) => {},
|
|
70
|
-
isInitialized: false
|
|
72
|
+
isInitialized: false,
|
|
71
73
|
});
|
|
72
74
|
|
|
73
75
|
const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
74
76
|
children,
|
|
75
77
|
}) => {
|
|
76
|
-
const [referrerLink, setReferrerLink] = useState<string>(
|
|
77
|
-
const [userId, setUserId] = useState<string>(
|
|
78
|
+
const [referrerLink, setReferrerLink] = useState<string>('');
|
|
79
|
+
const [userId, setUserId] = useState<string>('');
|
|
78
80
|
const [companyCode, setCompanyCode] = useState<string | null>(null);
|
|
79
81
|
const [isInitialized, setIsInitialized] = useState<boolean>(false);
|
|
80
82
|
|
|
81
83
|
// MARK: Initialize the SDK
|
|
82
84
|
const initialize = async (companyCode: string | null): Promise<void> => {
|
|
83
85
|
if (isInitialized) {
|
|
84
|
-
console.error(
|
|
86
|
+
console.error('[Insert Affiliate] SDK is already initialized.');
|
|
85
87
|
return;
|
|
86
88
|
}
|
|
87
|
-
|
|
88
|
-
if (companyCode && companyCode.trim() !==
|
|
89
|
+
|
|
90
|
+
if (companyCode && companyCode.trim() !== '') {
|
|
89
91
|
setCompanyCode(companyCode);
|
|
90
92
|
await saveValueInAsync(ASYNC_KEYS.COMPANY_CODE, companyCode);
|
|
91
93
|
setIsInitialized(true);
|
|
92
|
-
console.log(
|
|
94
|
+
console.log(
|
|
95
|
+
`[Insert Affiliate] SDK initialized with company code: ${companyCode}`
|
|
96
|
+
);
|
|
93
97
|
} else {
|
|
94
|
-
console.warn(
|
|
98
|
+
console.warn(
|
|
99
|
+
'[Insert Affiliate] SDK initialized without a company code.'
|
|
100
|
+
);
|
|
95
101
|
setIsInitialized(true);
|
|
96
102
|
}
|
|
97
103
|
};
|
|
@@ -120,15 +126,19 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
120
126
|
let userId = await getValueFromAsync(ASYNC_KEYS.USER_ID);
|
|
121
127
|
if (!userId) {
|
|
122
128
|
userId = generateUserID();
|
|
129
|
+
setUserId(userId);
|
|
123
130
|
await saveValueInAsync(ASYNC_KEYS.USER_ID, userId);
|
|
131
|
+
} else {
|
|
124
132
|
setUserId(userId);
|
|
125
133
|
}
|
|
134
|
+
|
|
135
|
+
return userId;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
138
|
const generateUserID = () => {
|
|
129
139
|
const characters =
|
|
130
|
-
|
|
131
|
-
let uniqueId =
|
|
140
|
+
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
141
|
+
let uniqueId = '';
|
|
132
142
|
for (let i = 0; i < 6; i++) {
|
|
133
143
|
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
134
144
|
uniqueId += characters[randomIndex];
|
|
@@ -139,7 +149,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
139
149
|
const reset = (): void => {
|
|
140
150
|
setCompanyCode(null);
|
|
141
151
|
setIsInitialized(false);
|
|
142
|
-
console.log(
|
|
152
|
+
console.log('[Insert Affiliate] SDK has been reset.');
|
|
143
153
|
};
|
|
144
154
|
|
|
145
155
|
// Helper funciton Storage / Retrieval
|
|
@@ -157,12 +167,12 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
157
167
|
};
|
|
158
168
|
|
|
159
169
|
// Helper function to log errors
|
|
160
|
-
const errorLog = (message: string, type?:
|
|
170
|
+
const errorLog = (message: string, type?: 'error' | 'warn' | 'log') => {
|
|
161
171
|
switch (type) {
|
|
162
|
-
case
|
|
172
|
+
case 'error':
|
|
163
173
|
console.error(`ENCOUNTER ERROR ~ ${message}`);
|
|
164
174
|
break;
|
|
165
|
-
case
|
|
175
|
+
case 'warn':
|
|
166
176
|
console.warn(`ENCOUNTER WARNING ~ ${message}`);
|
|
167
177
|
break;
|
|
168
178
|
default:
|
|
@@ -171,7 +181,6 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
171
181
|
}
|
|
172
182
|
};
|
|
173
183
|
|
|
174
|
-
|
|
175
184
|
// MARK: Short Codes
|
|
176
185
|
const isShortCode = (referringLink: string): boolean => {
|
|
177
186
|
// Short codes are less than 10 characters
|
|
@@ -180,8 +189,8 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
180
189
|
};
|
|
181
190
|
|
|
182
191
|
async function setShortCode(shortCode: string): Promise<void> {
|
|
183
|
-
console.log(
|
|
184
|
-
generateThenSetUserID();
|
|
192
|
+
console.log('[Insert Affiliate] Setting short code.');
|
|
193
|
+
await generateThenSetUserID();
|
|
185
194
|
|
|
186
195
|
// Validate it is a short code
|
|
187
196
|
const capitalisedShortCode = shortCode.toUpperCase();
|
|
@@ -194,85 +203,99 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
194
203
|
// MARK: Return Insert Affiliate Identifier
|
|
195
204
|
const returnInsertAffiliateIdentifier = async (): Promise<string | null> => {
|
|
196
205
|
try {
|
|
206
|
+
|
|
197
207
|
return `${referrerLink}-${userId}`;
|
|
198
208
|
} catch (error) {
|
|
199
209
|
errorLog(`ERROR ~ returnInsertAffiliateIdentifier: ${error}`);
|
|
200
210
|
return null;
|
|
201
211
|
}
|
|
202
|
-
}
|
|
203
|
-
|
|
212
|
+
};
|
|
204
213
|
|
|
205
214
|
// MARK: Insert Affiliate Identifier
|
|
206
215
|
|
|
207
|
-
async function setInsertAffiliateIdentifier(
|
|
208
|
-
|
|
216
|
+
async function setInsertAffiliateIdentifier(
|
|
217
|
+
referringLink: string
|
|
218
|
+
): Promise<void | string> {
|
|
219
|
+
console.log('[Insert Affiliate] Setting affiliate identifier.');
|
|
209
220
|
|
|
210
221
|
try {
|
|
211
|
-
await generateThenSetUserID();
|
|
212
|
-
console.log(
|
|
222
|
+
const customerID = await generateThenSetUserID();
|
|
223
|
+
console.log(
|
|
224
|
+
'[Insert Affiliate] Completed generateThenSetUserID within setInsertAffiliateIdentifier.'
|
|
225
|
+
);
|
|
213
226
|
|
|
214
227
|
if (!referringLink) {
|
|
215
|
-
console.warn(
|
|
228
|
+
console.warn('[Insert Affiliate] Referring link is invalid.');
|
|
229
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
216
230
|
await storeInsertAffiliateIdentifier({ link: referringLink });
|
|
217
|
-
return
|
|
231
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
218
232
|
}
|
|
219
|
-
|
|
220
|
-
if (!companyCode || companyCode.trim() ===
|
|
221
|
-
let companyCodeFromStorage = await getValueFromAsync(
|
|
233
|
+
|
|
234
|
+
if (!companyCode || (companyCode.trim() === '' && companyCode !== null)) {
|
|
235
|
+
let companyCodeFromStorage = await getValueFromAsync(
|
|
236
|
+
ASYNC_KEYS.COMPANY_CODE
|
|
237
|
+
);
|
|
222
238
|
|
|
223
239
|
if (companyCodeFromStorage !== null) {
|
|
224
240
|
setCompanyCode(companyCodeFromStorage);
|
|
225
241
|
} else {
|
|
226
242
|
console.error(
|
|
227
|
-
|
|
243
|
+
'[Insert Affiliate] Company code is not set. Please initialize the SDK with a valid company code.'
|
|
228
244
|
);
|
|
229
245
|
return;
|
|
230
246
|
}
|
|
231
247
|
}
|
|
232
|
-
|
|
248
|
+
|
|
233
249
|
// Check if referring link is already a short code, if so save it and stop here.
|
|
234
250
|
if (isShortCode(referringLink)) {
|
|
235
|
-
console.log(
|
|
251
|
+
console.log(
|
|
252
|
+
'[Insert Affiliate] Referring link is already a short code.'
|
|
253
|
+
);
|
|
254
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
236
255
|
await storeInsertAffiliateIdentifier({ link: referringLink });
|
|
237
|
-
return
|
|
256
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
238
257
|
}
|
|
239
|
-
|
|
258
|
+
|
|
240
259
|
// 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
|
|
241
260
|
// Encode the referring link
|
|
242
261
|
const encodedAffiliateLink = encodeURIComponent(referringLink);
|
|
243
262
|
if (!encodedAffiliateLink) {
|
|
244
|
-
console.error(
|
|
263
|
+
console.error('[Insert Affiliate] Failed to encode affiliate link.');
|
|
264
|
+
|
|
265
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
245
266
|
await storeInsertAffiliateIdentifier({ link: referringLink });
|
|
246
|
-
return
|
|
267
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
247
268
|
}
|
|
248
|
-
|
|
269
|
+
|
|
249
270
|
// Create the request URL
|
|
250
271
|
const urlString = `https://api.insertaffiliate.com/V1/convert-deep-link-to-short-link?companyId=${companyCode}&deepLinkUrl=${encodedAffiliateLink}`;
|
|
251
|
-
console.log(
|
|
272
|
+
console.log('[Insert Affiliate] urlString .', urlString);
|
|
252
273
|
const response = await axios.get(urlString, {
|
|
253
274
|
headers: {
|
|
254
|
-
|
|
275
|
+
'Content-Type': 'application/json',
|
|
255
276
|
},
|
|
256
277
|
});
|
|
257
|
-
|
|
278
|
+
|
|
258
279
|
// Call to the backend for the short code and save the resolse in valid
|
|
259
280
|
if (response.status === 200 && response.data.shortLink) {
|
|
260
281
|
const shortLink = response.data.shortLink;
|
|
261
|
-
console.log(
|
|
262
|
-
|
|
282
|
+
console.log('[Insert Affiliate] Short link received:', shortLink);
|
|
283
|
+
return `${shortLink}-${customerID}`;
|
|
263
284
|
} else {
|
|
264
|
-
console.warn(
|
|
285
|
+
console.warn('[Insert Affiliate] Unexpected response format.');
|
|
286
|
+
let heldReferrerLinkBeforeAsyncStateUpdate = referrerLink;
|
|
265
287
|
await storeInsertAffiliateIdentifier({ link: referringLink });
|
|
288
|
+
return `${heldReferrerLinkBeforeAsyncStateUpdate}-${customerID}`;
|
|
266
289
|
}
|
|
267
290
|
} catch (error) {
|
|
268
|
-
console.error(
|
|
291
|
+
console.error('[Insert Affiliate] Error:', error);
|
|
269
292
|
}
|
|
270
293
|
};
|
|
271
294
|
|
|
272
295
|
async function storeInsertAffiliateIdentifier({ link }: { link: string }) {
|
|
273
296
|
console.log(`[Insert Affiliate] Storing affiliate identifier: ${link}`);
|
|
274
|
-
await saveValueInAsync(ASYNC_KEYS.REFERRER_LINK, link);
|
|
275
297
|
setReferrerLink(link);
|
|
298
|
+
await saveValueInAsync(ASYNC_KEYS.REFERRER_LINK, link);
|
|
276
299
|
}
|
|
277
300
|
|
|
278
301
|
const validatePurchaseWithIapticAPI = async (
|
|
@@ -284,22 +307,24 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
284
307
|
try {
|
|
285
308
|
const baseRequestBody: RequestBody = {
|
|
286
309
|
id: iapticAppId,
|
|
287
|
-
type:
|
|
310
|
+
type: 'application',
|
|
288
311
|
};
|
|
289
|
-
|
|
312
|
+
|
|
290
313
|
let transaction;
|
|
291
314
|
|
|
292
|
-
if (Platform.OS ===
|
|
315
|
+
if (Platform.OS === 'ios') {
|
|
293
316
|
transaction = {
|
|
294
317
|
id: iapticAppId,
|
|
295
|
-
type:
|
|
318
|
+
type: 'ios-appstore',
|
|
296
319
|
appStoreReceipt: jsonIapPurchase.transactionReceipt,
|
|
297
320
|
};
|
|
298
321
|
} else {
|
|
299
|
-
const receiptJson = JSON.parse(
|
|
322
|
+
const receiptJson = JSON.parse(
|
|
323
|
+
atob(jsonIapPurchase.transactionReceipt || '')
|
|
324
|
+
);
|
|
300
325
|
transaction = {
|
|
301
326
|
id: receiptJson.orderId, // Extracted orderId
|
|
302
|
-
type:
|
|
327
|
+
type: 'android-playstore',
|
|
303
328
|
purchaseToken: receiptJson.purchaseToken, // Extracted purchase token
|
|
304
329
|
receipt: jsonIapPurchase.transactionReceipt, // Full receipt (Base64)
|
|
305
330
|
signature: receiptJson.signature, // Receipt signature
|
|
@@ -318,43 +343,46 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
318
343
|
applicationUsername: `${insertAffiliateIdentifier}`,
|
|
319
344
|
};
|
|
320
345
|
}
|
|
321
|
-
|
|
346
|
+
|
|
322
347
|
// Send validation request to server
|
|
323
348
|
const response = await axios({
|
|
324
349
|
url: `https://validator.iaptic.com/v1/validate`,
|
|
325
|
-
method:
|
|
350
|
+
method: 'POST',
|
|
326
351
|
headers: {
|
|
327
352
|
Authorization: `Basic ${btoa(`${iapticAppName}:${iapticPublicKey}`)}`,
|
|
328
|
-
|
|
353
|
+
'Content-Type': 'application/json',
|
|
329
354
|
},
|
|
330
355
|
data: requestBody,
|
|
331
356
|
});
|
|
332
|
-
|
|
357
|
+
|
|
333
358
|
if (response.status === 200) {
|
|
334
|
-
console.log(
|
|
359
|
+
console.log('Validation successful:', response.data);
|
|
335
360
|
return true;
|
|
336
361
|
} else {
|
|
337
|
-
console.error(
|
|
362
|
+
console.error('Validation failed:', response.data);
|
|
338
363
|
return false;
|
|
339
364
|
}
|
|
340
365
|
} catch (error) {
|
|
341
366
|
if (error instanceof Error) {
|
|
342
367
|
console.error(`validatePurchaseWithIapticAPI Error: ${error.message}`);
|
|
343
368
|
} else {
|
|
344
|
-
console.error(
|
|
369
|
+
console.error(
|
|
370
|
+
`validatePurchaseWithIapticAPI Unknown Error: ${JSON.stringify(
|
|
371
|
+
error
|
|
372
|
+
)}`
|
|
373
|
+
);
|
|
345
374
|
}
|
|
346
375
|
|
|
347
376
|
return false;
|
|
348
377
|
}
|
|
349
378
|
};
|
|
350
|
-
|
|
351
379
|
|
|
352
|
-
// MARK: Track Event
|
|
380
|
+
// MARK: Track Event
|
|
353
381
|
const trackEvent = async (eventName: string): Promise<void> => {
|
|
354
382
|
try {
|
|
355
383
|
if (!referrerLink || !userId) {
|
|
356
384
|
console.warn(
|
|
357
|
-
|
|
385
|
+
'[Insert Affiliate] No affiliate identifier found. Please set one before tracking events.'
|
|
358
386
|
);
|
|
359
387
|
return Promise.resolve();
|
|
360
388
|
}
|
|
@@ -365,22 +393,22 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
365
393
|
};
|
|
366
394
|
|
|
367
395
|
const response = await axios.post(
|
|
368
|
-
|
|
396
|
+
'https://api.insertaffiliate.com/v1/trackEvent',
|
|
369
397
|
payload,
|
|
370
398
|
{
|
|
371
|
-
headers: {
|
|
399
|
+
headers: { 'Content-Type': 'application/json' },
|
|
372
400
|
}
|
|
373
401
|
);
|
|
374
402
|
|
|
375
403
|
if (response.status === 200) {
|
|
376
|
-
console.log(
|
|
404
|
+
console.log('[Insert Affiliate] Event tracked successfully');
|
|
377
405
|
} else {
|
|
378
406
|
console.error(
|
|
379
407
|
`[Insert Affiliate] Failed to track event with status code: ${response.status}`
|
|
380
408
|
);
|
|
381
409
|
}
|
|
382
410
|
} catch (error) {
|
|
383
|
-
console.error(
|
|
411
|
+
console.error('[Insert Affiliate] Error tracking event:', error);
|
|
384
412
|
return Promise.reject(error);
|
|
385
413
|
}
|
|
386
414
|
};
|
|
@@ -396,7 +424,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
396
424
|
trackEvent,
|
|
397
425
|
setInsertAffiliateIdentifier,
|
|
398
426
|
initialize,
|
|
399
|
-
isInitialized
|
|
427
|
+
isInitialized,
|
|
400
428
|
}}
|
|
401
429
|
>
|
|
402
430
|
{children}
|