insert-affiliate-react-native-sdk 1.1.6 → 1.1.8
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 +1 -4
- package/dist/DeepLinkIapProvider.js +69 -80
- package/dist/useDeepLinkIapProvider.d.ts +2 -2
- package/dist/useDeepLinkIapProvider.js +2 -2
- package/package.json +1 -1
- package/readme.md +36 -52
- package/src/DeepLinkIapProvider.tsx +96 -98
- package/src/useDeepLinkIapProvider.tsx +2 -2
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
type T_DEEPLINK_IAP_PROVIDER = {
|
|
3
3
|
children: React.ReactNode;
|
|
4
|
-
iapticAppId: string;
|
|
5
|
-
iapticAppName: string;
|
|
6
|
-
iapticPublicKey: string;
|
|
7
4
|
};
|
|
8
5
|
type CustomPurchase = {
|
|
9
6
|
[key: string]: any;
|
|
@@ -12,7 +9,7 @@ type T_DEEPLINK_IAP_CONTEXT = {
|
|
|
12
9
|
referrerLink: string;
|
|
13
10
|
userId: string;
|
|
14
11
|
returnInsertAffiliateIdentifier: () => Promise<string | null>;
|
|
15
|
-
|
|
12
|
+
validatePurchaseWithIapticAPI: (jsonIapPurchase: CustomPurchase, iapticAppId: string, iapticAppName: string, iapticPublicKey: string) => Promise<boolean>;
|
|
16
13
|
trackEvent: (eventName: string) => Promise<void>;
|
|
17
14
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
18
15
|
setInsertAffiliateIdentifier: (referringLink: string, completion: (shortLink: string | null) => void) => Promise<void>;
|
|
@@ -50,49 +50,34 @@ exports.DeepLinkIapContext = (0, react_1.createContext)({
|
|
|
50
50
|
referrerLink: "",
|
|
51
51
|
userId: "",
|
|
52
52
|
returnInsertAffiliateIdentifier: () => __awaiter(void 0, void 0, void 0, function* () { return ""; }),
|
|
53
|
-
|
|
53
|
+
validatePurchaseWithIapticAPI: (jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey) => __awaiter(void 0, void 0, void 0, function* () { return false; }),
|
|
54
54
|
trackEvent: (eventName) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
55
55
|
setShortCode: (shortCode) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
56
56
|
setInsertAffiliateIdentifier: (referringLink, completion) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
57
57
|
initialize: (code) => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
58
58
|
isInitialized: false
|
|
59
59
|
});
|
|
60
|
-
const DeepLinkIapProvider = ({ children,
|
|
60
|
+
const DeepLinkIapProvider = ({ children, }) => {
|
|
61
61
|
const [referrerLink, setReferrerLink] = (0, react_1.useState)("");
|
|
62
62
|
const [userId, setUserId] = (0, react_1.useState)("");
|
|
63
63
|
const [companyCode, setCompanyCode] = (0, react_1.useState)(null);
|
|
64
64
|
const [isInitialized, setIsInitialized] = (0, react_1.useState)(false);
|
|
65
|
-
|
|
65
|
+
// MARK: Initialize the SDK
|
|
66
|
+
const initialize = (companyCode) => __awaiter(void 0, void 0, void 0, function* () {
|
|
66
67
|
if (isInitialized) {
|
|
67
68
|
console.error("[Insert Affiliate] SDK is already initialized.");
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
|
-
if (
|
|
71
|
-
setCompanyCode(
|
|
71
|
+
if (companyCode && companyCode.trim() !== "") {
|
|
72
|
+
setCompanyCode(companyCode);
|
|
72
73
|
setIsInitialized(true);
|
|
73
|
-
console.log(`[Insert Affiliate] SDK initialized with company code: ${
|
|
74
|
+
console.log(`[Insert Affiliate] SDK initialized with company code: ${companyCode}`);
|
|
74
75
|
}
|
|
75
76
|
else {
|
|
76
77
|
console.warn("[Insert Affiliate] SDK initialized without a company code.");
|
|
77
78
|
setIsInitialized(true);
|
|
78
79
|
}
|
|
79
80
|
});
|
|
80
|
-
const reset = () => {
|
|
81
|
-
setCompanyCode(null);
|
|
82
|
-
setIsInitialized(false);
|
|
83
|
-
console.log("[Insert Affiliate] SDK has been reset.");
|
|
84
|
-
};
|
|
85
|
-
// ASYNC FUNCTIONS
|
|
86
|
-
const saveValueInAsync = (key, value) => __awaiter(void 0, void 0, void 0, function* () {
|
|
87
|
-
yield async_storage_1.default.setItem(key, value);
|
|
88
|
-
});
|
|
89
|
-
const getValueFromAsync = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
|
-
const response = yield async_storage_1.default.getItem(key);
|
|
91
|
-
return response;
|
|
92
|
-
});
|
|
93
|
-
const clearAsyncStorage = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
94
|
-
yield async_storage_1.default.clear();
|
|
95
|
-
});
|
|
96
81
|
// EFFECT TO FETCH USER ID AND REF LINK
|
|
97
82
|
// IF ALREADY EXISTS IN ASYNC STORAGE
|
|
98
83
|
(0, react_1.useEffect)(() => {
|
|
@@ -111,7 +96,42 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
111
96
|
});
|
|
112
97
|
fetchAsyncEssentials();
|
|
113
98
|
}, []);
|
|
114
|
-
|
|
99
|
+
function setUserID() {
|
|
100
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
+
let userId = yield getValueFromAsync(ASYNC_KEYS.USER_ID);
|
|
102
|
+
if (!userId) {
|
|
103
|
+
userId = generateUserID();
|
|
104
|
+
yield saveValueInAsync(ASYNC_KEYS.USER_ID, userId);
|
|
105
|
+
setUserId(userId);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
const generateUserID = () => {
|
|
110
|
+
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
111
|
+
let uniqueId = "";
|
|
112
|
+
for (let i = 0; i < 6; i++) {
|
|
113
|
+
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
114
|
+
uniqueId += characters[randomIndex];
|
|
115
|
+
}
|
|
116
|
+
return uniqueId;
|
|
117
|
+
};
|
|
118
|
+
const reset = () => {
|
|
119
|
+
setCompanyCode(null);
|
|
120
|
+
setIsInitialized(false);
|
|
121
|
+
console.log("[Insert Affiliate] SDK has been reset.");
|
|
122
|
+
};
|
|
123
|
+
// Helper funciton Storage / Retrieval
|
|
124
|
+
const saveValueInAsync = (key, value) => __awaiter(void 0, void 0, void 0, function* () {
|
|
125
|
+
yield async_storage_1.default.setItem(key, value);
|
|
126
|
+
});
|
|
127
|
+
const getValueFromAsync = (key) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
|
+
const response = yield async_storage_1.default.getItem(key);
|
|
129
|
+
return response;
|
|
130
|
+
});
|
|
131
|
+
const clearAsyncStorage = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
132
|
+
yield async_storage_1.default.clear();
|
|
133
|
+
});
|
|
134
|
+
// Helper function to log errors
|
|
115
135
|
const errorLog = (message, type) => {
|
|
116
136
|
switch (type) {
|
|
117
137
|
case "error":
|
|
@@ -125,6 +145,23 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
125
145
|
break;
|
|
126
146
|
}
|
|
127
147
|
};
|
|
148
|
+
// MARK: Short Codes
|
|
149
|
+
const isShortCode = (referringLink) => {
|
|
150
|
+
// Short codes are less than 10 characters
|
|
151
|
+
const isValidCharacters = /^[a-zA-Z0-9]+$/.test(referringLink);
|
|
152
|
+
return isValidCharacters && referringLink.length < 10;
|
|
153
|
+
};
|
|
154
|
+
function setShortCode(shortCode) {
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
setUserID();
|
|
157
|
+
// Validate it is a short code
|
|
158
|
+
const capitalisedShortCode = shortCode.toUpperCase();
|
|
159
|
+
isShortCode(capitalisedShortCode);
|
|
160
|
+
// If all checks pass, set the Insert Affiliate Identifier
|
|
161
|
+
yield storeInsertAffiliateIdentifier({ link: capitalisedShortCode });
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
// MARK: Return Insert Affiliate Identifier
|
|
128
165
|
const returnInsertAffiliateIdentifier = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
129
166
|
try {
|
|
130
167
|
return `${referrerLink}-${userId}`;
|
|
@@ -134,21 +171,7 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
134
171
|
return null;
|
|
135
172
|
}
|
|
136
173
|
});
|
|
137
|
-
//
|
|
138
|
-
const generateUserID = () => {
|
|
139
|
-
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
140
|
-
let uniqueId = "";
|
|
141
|
-
for (let i = 0; i < 6; i++) {
|
|
142
|
-
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
143
|
-
uniqueId += characters[randomIndex];
|
|
144
|
-
}
|
|
145
|
-
return uniqueId;
|
|
146
|
-
};
|
|
147
|
-
// Helper function to determine if a link is a short code
|
|
148
|
-
const isShortCode = (referringLink) => {
|
|
149
|
-
// Example check: short codes are less than 10 characters
|
|
150
|
-
return referringLink.length < 10;
|
|
151
|
-
};
|
|
174
|
+
// MARK: Insert Affiliate Identifier
|
|
152
175
|
const setInsertAffiliateIdentifier = (referringLink, completion) => __awaiter(void 0, void 0, void 0, function* () {
|
|
153
176
|
try {
|
|
154
177
|
setUserID();
|
|
@@ -209,42 +232,6 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
209
232
|
completion(null);
|
|
210
233
|
}
|
|
211
234
|
});
|
|
212
|
-
function setUserID() {
|
|
213
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
214
|
-
let userId = yield getValueFromAsync(ASYNC_KEYS.USER_ID);
|
|
215
|
-
if (!userId) {
|
|
216
|
-
userId = generateUserID();
|
|
217
|
-
yield saveValueInAsync(ASYNC_KEYS.USER_ID, userId);
|
|
218
|
-
setUserId(userId);
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
function setShortCode(shortCode) {
|
|
223
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
224
|
-
setUserID();
|
|
225
|
-
// Capitalise the shortcode
|
|
226
|
-
const capitalisedShortCode = shortCode.toUpperCase();
|
|
227
|
-
// Ensure the short code is exactly 10 characters long
|
|
228
|
-
if (capitalisedShortCode.length !== 10) {
|
|
229
|
-
console.error("[Insert Affiliate] Error: Short code must be exactly 10 characters long.");
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
// Check if the short code contains only letters and numbers
|
|
233
|
-
const isValidShortCode = /^[a-zA-Z0-9]+$/.test(capitalisedShortCode);
|
|
234
|
-
if (!isValidShortCode) {
|
|
235
|
-
console.error("[Insert Affiliate] Error: Short code must contain only letters and numbers.");
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
// If all checks pass, set the Insert Affiliate Identifier
|
|
239
|
-
yield storeInsertAffiliateIdentifier({ link: capitalisedShortCode });
|
|
240
|
-
if (referrerLink) {
|
|
241
|
-
console.log(`[Insert Affiliate] Successfully set affiliate identifier: ${referrerLink}`);
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
console.error("[Insert Affiliate] Failed to set affiliate identifier.");
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
235
|
function storeInsertAffiliateIdentifier(_a) {
|
|
249
236
|
return __awaiter(this, arguments, void 0, function* ({ link }) {
|
|
250
237
|
console.log(`[Insert Affiliate] Storing affiliate identifier: ${link}`);
|
|
@@ -252,7 +239,7 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
252
239
|
setReferrerLink(link);
|
|
253
240
|
});
|
|
254
241
|
}
|
|
255
|
-
const
|
|
242
|
+
const validatePurchaseWithIapticAPI = (jsonIapPurchase, iapticAppId, iapticAppName, iapticPublicKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
256
243
|
try {
|
|
257
244
|
const baseRequestBody = {
|
|
258
245
|
id: iapticAppId,
|
|
@@ -277,9 +264,10 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
277
264
|
};
|
|
278
265
|
}
|
|
279
266
|
const requestBody = Object.assign(Object.assign({}, baseRequestBody), { transaction });
|
|
280
|
-
|
|
267
|
+
let insertAffiliateIdentifier = yield returnInsertAffiliateIdentifier();
|
|
268
|
+
if (insertAffiliateIdentifier) {
|
|
281
269
|
requestBody.additionalData = {
|
|
282
|
-
applicationUsername: `${
|
|
270
|
+
applicationUsername: `${insertAffiliateIdentifier}`,
|
|
283
271
|
};
|
|
284
272
|
}
|
|
285
273
|
// Send validation request to server
|
|
@@ -303,14 +291,15 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
303
291
|
}
|
|
304
292
|
catch (error) {
|
|
305
293
|
if (error instanceof Error) {
|
|
306
|
-
console.error(`
|
|
294
|
+
console.error(`validatePurchaseWithIapticAPI Error: ${error.message}`);
|
|
307
295
|
}
|
|
308
296
|
else {
|
|
309
|
-
console.error(`
|
|
297
|
+
console.error(`validatePurchaseWithIapticAPI Unknown Error: ${JSON.stringify(error)}`);
|
|
310
298
|
}
|
|
311
299
|
return false;
|
|
312
300
|
}
|
|
313
301
|
});
|
|
302
|
+
// MARK: Track Event
|
|
314
303
|
const trackEvent = (eventName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
315
304
|
try {
|
|
316
305
|
if (!referrerLink || !userId) {
|
|
@@ -341,7 +330,7 @@ const DeepLinkIapProvider = ({ children, iapticAppId, iapticAppName, iapticPubli
|
|
|
341
330
|
userId,
|
|
342
331
|
setShortCode,
|
|
343
332
|
returnInsertAffiliateIdentifier,
|
|
344
|
-
|
|
333
|
+
validatePurchaseWithIapticAPI,
|
|
345
334
|
trackEvent,
|
|
346
335
|
setInsertAffiliateIdentifier,
|
|
347
336
|
initialize,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
declare const useDeepLinkIapProvider: () => {
|
|
2
2
|
referrerLink: string;
|
|
3
3
|
userId: string;
|
|
4
|
-
|
|
4
|
+
validatePurchaseWithIapticAPI: (jsonIapPurchase: {
|
|
5
5
|
[key: string]: any;
|
|
6
|
-
}) => Promise<boolean>;
|
|
6
|
+
}, iapticAppId: string, iapticAppName: string, iapticPublicKey: string) => Promise<boolean>;
|
|
7
7
|
returnInsertAffiliateIdentifier: () => Promise<string | null>;
|
|
8
8
|
trackEvent: (eventName: string) => Promise<void>;
|
|
9
9
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const react_1 = require("react");
|
|
4
4
|
const DeepLinkIapProvider_1 = require("./DeepLinkIapProvider");
|
|
5
5
|
const useDeepLinkIapProvider = () => {
|
|
6
|
-
const { referrerLink, userId,
|
|
6
|
+
const { referrerLink, userId, validatePurchaseWithIapticAPI, returnInsertAffiliateIdentifier, trackEvent, setShortCode, setInsertAffiliateIdentifier, initialize, isInitialized } = (0, react_1.useContext)(DeepLinkIapProvider_1.DeepLinkIapContext);
|
|
7
7
|
return {
|
|
8
8
|
referrerLink,
|
|
9
9
|
userId,
|
|
10
|
-
|
|
10
|
+
validatePurchaseWithIapticAPI,
|
|
11
11
|
returnInsertAffiliateIdentifier,
|
|
12
12
|
trackEvent,
|
|
13
13
|
setShortCode,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "insert-affiliate-react-native-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "A package that will give context having implementation of react-native-branch and react-native-iap and iaptic validate api.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/readme.md
CHANGED
|
@@ -10,18 +10,11 @@ The **InsertAffiliateReactNative SDK** is designed for React Native applications
|
|
|
10
10
|
- **Affiliate Identifier Management**: Set and retrieve the affiliate identifier based on user-specific links.
|
|
11
11
|
- **In-App Purchase (IAP) Initialisation**: Easily reinitialise in-app purchases with the option to validate using an affiliate identifier.
|
|
12
12
|
|
|
13
|
-
## Peer Dependencies
|
|
14
|
-
|
|
15
|
-
Before using this package, ensure you have the following dependencies installed:
|
|
16
|
-
|
|
17
|
-
- [react-native-iap](https://www.npmjs.com/package/react-native-iap)
|
|
18
|
-
- [axios](https://www.npmjs.com/package/axios)
|
|
19
|
-
|
|
20
13
|
## Getting Started
|
|
21
14
|
|
|
22
15
|
To get started with the InsertAffiliateReactNative SDK:
|
|
23
16
|
|
|
24
|
-
1. [Install the
|
|
17
|
+
1. [Install the SDK](#installation)
|
|
25
18
|
2. [Initialise the SDK in App.tsx](#basic-usage)
|
|
26
19
|
3. [Set up in-app purchases (Required)](#in-app-purchase-setup-required)
|
|
27
20
|
4. [Set up deep linking (Required)](#deep-link-setup-required)
|
|
@@ -37,7 +30,9 @@ npm install insert-affiliate-react-native-sdk
|
|
|
37
30
|
|
|
38
31
|
## Basic Usage
|
|
39
32
|
|
|
40
|
-
|
|
33
|
+
Follow the steps below to install the SDK. You can use different methods depending on your project setup (e.g., Gradle, Maven, or manual download).
|
|
34
|
+
|
|
35
|
+
#### Step 1: Initialisation in `App.tsx`
|
|
41
36
|
|
|
42
37
|
First, wrap your with our provider and call the `initialise` method early in your app's lifecycle:
|
|
43
38
|
|
|
@@ -47,7 +42,7 @@ const Child = () => {
|
|
|
47
42
|
referrerLink,
|
|
48
43
|
subscriptions,
|
|
49
44
|
iapLoading,
|
|
50
|
-
|
|
45
|
+
validatePurchaseWithIapticAPI,
|
|
51
46
|
userId,
|
|
52
47
|
userPurchase,
|
|
53
48
|
trackEvent,
|
|
@@ -60,23 +55,16 @@ const Child = () => {
|
|
|
60
55
|
}, [initialize, isInitialized]);
|
|
61
56
|
|
|
62
57
|
// ...
|
|
63
|
-
|
|
64
58
|
}
|
|
65
59
|
|
|
66
60
|
const App = () => {
|
|
67
61
|
return (
|
|
68
|
-
<DeepLinkIapProvider
|
|
69
|
-
iapticAppId="{{ your_iaptic_app_id }}"
|
|
70
|
-
iapticAppName="{{ your_iaptic_app_name }}"
|
|
71
|
-
iapticPublicKey="{{ your_iaptic_public_key }}">
|
|
62
|
+
<DeepLinkIapProvider>
|
|
72
63
|
<Child />
|
|
73
64
|
</DeepLinkIapProvider>
|
|
74
65
|
);
|
|
75
66
|
};
|
|
76
67
|
```
|
|
77
|
-
- Replace `{{ your_iaptic_app_id }}` with your **Iaptic App ID**. You can find this [here](https://www.iaptic.com/account).
|
|
78
|
-
- Replace `{{ your_iaptic_app_name }}` with your **Iaptic App Name**. You can find this [here](https://www.iaptic.com/account).
|
|
79
|
-
- Replace `{{ your_iaptic_public_key }}` with your **Iaptic Public Key**. You can find this [here](https://www.iaptic.com/settings).
|
|
80
68
|
- Replace `{{ your_company_code }}` with the unique company code associated with your Insert Affiliate account. You can find this code in your dashboard under [Settings](http://app.insertaffiliate.com/settings).
|
|
81
69
|
|
|
82
70
|
## In-App Purchase Setup [Required]
|
|
@@ -87,7 +75,7 @@ Insert Affiliate requires a Receipt Verification platform to validate in-app pur
|
|
|
87
75
|
### Option 1: Iaptic Integration
|
|
88
76
|
First, complete the [Iaptic account setup](https://www.iaptic.com/signup) and code integration.
|
|
89
77
|
|
|
90
|
-
Then after setting up the in app purchase (IAP) with Iaptic, call Insert Affiliate's
|
|
78
|
+
Then after setting up the in app purchase (IAP) with Iaptic, call Insert Affiliate's ```validatePurchaseWithIapticAPI``` on purchase.
|
|
91
79
|
|
|
92
80
|
```javascript
|
|
93
81
|
import React from 'react';
|
|
@@ -99,7 +87,7 @@ const Child = () => {
|
|
|
99
87
|
const {
|
|
100
88
|
initialize,
|
|
101
89
|
isInitialized,
|
|
102
|
-
|
|
90
|
+
validatePurchaseWithIapticAPI,
|
|
103
91
|
} = useDeepLinkIapProvider();
|
|
104
92
|
|
|
105
93
|
const [iapLoading, setIapLoading] = useState(false);
|
|
@@ -111,44 +99,46 @@ const Child = () => {
|
|
|
111
99
|
|
|
112
100
|
// Initialize the Insert Affiliate SDK at the earliest possible moment
|
|
113
101
|
useEffect(() => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
102
|
+
if (!isInitialized) {
|
|
103
|
+
initialize("{{ your_company_code }}");
|
|
104
|
+
}
|
|
117
105
|
}, [initialize, isInitialized]);
|
|
118
106
|
|
|
119
107
|
|
|
120
108
|
// Validate the purchase with Iaptic through Insert Affiliate's SDK for Affiliate Tracking
|
|
121
109
|
useEffect(() => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
110
|
+
if (currentPurchase) {
|
|
111
|
+
validatePurchaseWithIapticAPI(
|
|
112
|
+
currentPurchase,
|
|
113
|
+
'{{ your_iaptic_app_id }}',
|
|
114
|
+
'{{ your_iaptic_app_name }}',
|
|
115
|
+
'{{ your_iaptic_public_key }}',
|
|
116
|
+
).then((isValid: boolean) => {
|
|
117
|
+
if (isValid) {
|
|
118
|
+
console.log("Purchase validated successfully.");
|
|
119
|
+
} else {
|
|
120
|
+
console.error("Purchase validation failed.");
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
131
124
|
}, [currentPurchase, handlePurchaseValidation]);
|
|
132
125
|
|
|
133
126
|
return (
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
127
|
+
<View>
|
|
128
|
+
<Button
|
|
129
|
+
disabled={iapLoading}
|
|
130
|
+
title={`Click to Buy Subscription`}
|
|
131
|
+
onPress={() => handleBuySubscription("oneMonthSubscriptionTwo")}
|
|
132
|
+
/>
|
|
133
|
+
{iapLoading && <ActivityIndicator size={"small"} color={"black"} />}
|
|
134
|
+
</View>
|
|
142
135
|
);
|
|
143
136
|
};
|
|
144
137
|
|
|
145
138
|
const App = () => {
|
|
146
139
|
return (
|
|
147
140
|
// Wrapped application code from the previous step...
|
|
148
|
-
<DeepLinkIapProvider
|
|
149
|
-
iapticAppId="{{ your_iaptic_app_id }}"
|
|
150
|
-
iapticAppName="{{ your_iaptic_app_name }}"
|
|
151
|
-
iapticPublicKey="{{ your_iaptic_public_key }}">
|
|
141
|
+
<DeepLinkIapProvider>
|
|
152
142
|
<Child />
|
|
153
143
|
</DeepLinkIapProvider>
|
|
154
144
|
);
|
|
@@ -204,7 +194,7 @@ After setting up your Branch integration, add the following code to your ```inde
|
|
|
204
194
|
<!--```-->
|
|
205
195
|
|
|
206
196
|
#### Example with Iaptic
|
|
207
|
-
```
|
|
197
|
+
```javascript
|
|
208
198
|
import branch from 'react-native-branch';
|
|
209
199
|
import { DeepLinkIapProvider, useDeepLinkIapProvider } from 'insert-affiliate-react-native-sdk';
|
|
210
200
|
|
|
@@ -242,13 +232,7 @@ To track an event, use the `trackEvent` function. Make sure to set an affiliate
|
|
|
242
232
|
|
|
243
233
|
```javascript
|
|
244
234
|
const {
|
|
245
|
-
|
|
246
|
-
subscriptions,
|
|
247
|
-
iapLoading,
|
|
248
|
-
handleBuySubscription,
|
|
249
|
-
userId,
|
|
250
|
-
userPurchase,
|
|
251
|
-
trackEvent, // Required for trackEvent
|
|
235
|
+
trackEvent,
|
|
252
236
|
} = useDeepLinkIapProvider();
|
|
253
237
|
|
|
254
238
|
<Button
|
|
@@ -6,9 +6,6 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
|
6
6
|
// TYPES USED IN THIS PROVIDER
|
|
7
7
|
type T_DEEPLINK_IAP_PROVIDER = {
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
-
iapticAppId: string;
|
|
10
|
-
iapticAppName: string;
|
|
11
|
-
iapticPublicKey: string;
|
|
12
9
|
};
|
|
13
10
|
|
|
14
11
|
type CustomPurchase = {
|
|
@@ -19,7 +16,12 @@ type T_DEEPLINK_IAP_CONTEXT = {
|
|
|
19
16
|
referrerLink: string;
|
|
20
17
|
userId: string;
|
|
21
18
|
returnInsertAffiliateIdentifier: () => Promise<string | null>;
|
|
22
|
-
|
|
19
|
+
validatePurchaseWithIapticAPI: (
|
|
20
|
+
jsonIapPurchase: CustomPurchase,
|
|
21
|
+
iapticAppId: string,
|
|
22
|
+
iapticAppName: string,
|
|
23
|
+
iapticPublicKey: string
|
|
24
|
+
) => Promise<boolean>;
|
|
23
25
|
trackEvent: (eventName: string) => Promise<void>;
|
|
24
26
|
setShortCode: (shortCode: string) => Promise<void>;
|
|
25
27
|
setInsertAffiliateIdentifier: (
|
|
@@ -57,7 +59,12 @@ export const DeepLinkIapContext = createContext<T_DEEPLINK_IAP_CONTEXT>({
|
|
|
57
59
|
referrerLink: "",
|
|
58
60
|
userId: "",
|
|
59
61
|
returnInsertAffiliateIdentifier: async () => "",
|
|
60
|
-
|
|
62
|
+
validatePurchaseWithIapticAPI: async (
|
|
63
|
+
jsonIapPurchase: CustomPurchase,
|
|
64
|
+
iapticAppId: string,
|
|
65
|
+
iapticAppName: string,
|
|
66
|
+
iapticPublicKey: string
|
|
67
|
+
) => false,
|
|
61
68
|
trackEvent: async (eventName: string) => {},
|
|
62
69
|
setShortCode: async (shortCode: string) => {},
|
|
63
70
|
setInsertAffiliateIdentifier: async (
|
|
@@ -70,51 +77,27 @@ export const DeepLinkIapContext = createContext<T_DEEPLINK_IAP_CONTEXT>({
|
|
|
70
77
|
|
|
71
78
|
const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
72
79
|
children,
|
|
73
|
-
iapticAppId,
|
|
74
|
-
iapticAppName,
|
|
75
|
-
iapticPublicKey,
|
|
76
80
|
}) => {
|
|
77
81
|
const [referrerLink, setReferrerLink] = useState<string>("");
|
|
78
82
|
const [userId, setUserId] = useState<string>("");
|
|
79
83
|
const [companyCode, setCompanyCode] = useState<string | null>(null);
|
|
80
84
|
const [isInitialized, setIsInitialized] = useState<boolean>(false);
|
|
81
85
|
|
|
82
|
-
|
|
86
|
+
// MARK: Initialize the SDK
|
|
87
|
+
const initialize = async (companyCode: string | null): Promise<void> => {
|
|
83
88
|
if (isInitialized) {
|
|
84
89
|
console.error("[Insert Affiliate] SDK is already initialized.");
|
|
85
90
|
return;
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
if (
|
|
89
|
-
setCompanyCode(
|
|
93
|
+
if (companyCode && companyCode.trim() !== "") {
|
|
94
|
+
setCompanyCode(companyCode);
|
|
90
95
|
setIsInitialized(true);
|
|
91
|
-
console.log(`[Insert Affiliate] SDK initialized with company code: ${
|
|
96
|
+
console.log(`[Insert Affiliate] SDK initialized with company code: ${companyCode}`);
|
|
92
97
|
} else {
|
|
93
98
|
console.warn("[Insert Affiliate] SDK initialized without a company code.");
|
|
94
99
|
setIsInitialized(true);
|
|
95
100
|
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const reset = (): void => {
|
|
99
|
-
setCompanyCode(null);
|
|
100
|
-
setIsInitialized(false);
|
|
101
|
-
console.log("[Insert Affiliate] SDK has been reset.");
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// ASYNC FUNCTIONS
|
|
107
|
-
const saveValueInAsync = async (key: string, value: string) => {
|
|
108
|
-
await AsyncStorage.setItem(key, value);
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const getValueFromAsync = async (key: string) => {
|
|
112
|
-
const response = await AsyncStorage.getItem(key);
|
|
113
|
-
return response;
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const clearAsyncStorage = async () => {
|
|
117
|
-
await AsyncStorage.clear();
|
|
118
101
|
};
|
|
119
102
|
|
|
120
103
|
// EFFECT TO FETCH USER ID AND REF LINK
|
|
@@ -137,7 +120,47 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
137
120
|
fetchAsyncEssentials();
|
|
138
121
|
}, []);
|
|
139
122
|
|
|
140
|
-
|
|
123
|
+
async function setUserID() {
|
|
124
|
+
let userId = await getValueFromAsync(ASYNC_KEYS.USER_ID);
|
|
125
|
+
if (!userId) {
|
|
126
|
+
userId = generateUserID();
|
|
127
|
+
await saveValueInAsync(ASYNC_KEYS.USER_ID, userId);
|
|
128
|
+
setUserId(userId);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const generateUserID = () => {
|
|
133
|
+
const characters =
|
|
134
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
135
|
+
let uniqueId = "";
|
|
136
|
+
for (let i = 0; i < 6; i++) {
|
|
137
|
+
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
138
|
+
uniqueId += characters[randomIndex];
|
|
139
|
+
}
|
|
140
|
+
return uniqueId;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const reset = (): void => {
|
|
144
|
+
setCompanyCode(null);
|
|
145
|
+
setIsInitialized(false);
|
|
146
|
+
console.log("[Insert Affiliate] SDK has been reset.");
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Helper funciton Storage / Retrieval
|
|
150
|
+
const saveValueInAsync = async (key: string, value: string) => {
|
|
151
|
+
await AsyncStorage.setItem(key, value);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const getValueFromAsync = async (key: string) => {
|
|
155
|
+
const response = await AsyncStorage.getItem(key);
|
|
156
|
+
return response;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const clearAsyncStorage = async () => {
|
|
160
|
+
await AsyncStorage.clear();
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// Helper function to log errors
|
|
141
164
|
const errorLog = (message: string, type?: "error" | "warn" | "log") => {
|
|
142
165
|
switch (type) {
|
|
143
166
|
case "error":
|
|
@@ -152,6 +175,26 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
152
175
|
}
|
|
153
176
|
};
|
|
154
177
|
|
|
178
|
+
|
|
179
|
+
// MARK: Short Codes
|
|
180
|
+
const isShortCode = (referringLink: string): boolean => {
|
|
181
|
+
// Short codes are less than 10 characters
|
|
182
|
+
const isValidCharacters = /^[a-zA-Z0-9]+$/.test(referringLink);
|
|
183
|
+
return isValidCharacters && referringLink.length < 10;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
async function setShortCode(shortCode: string): Promise<void> {
|
|
187
|
+
setUserID();
|
|
188
|
+
|
|
189
|
+
// Validate it is a short code
|
|
190
|
+
const capitalisedShortCode = shortCode.toUpperCase();
|
|
191
|
+
isShortCode(capitalisedShortCode);
|
|
192
|
+
|
|
193
|
+
// If all checks pass, set the Insert Affiliate Identifier
|
|
194
|
+
await storeInsertAffiliateIdentifier({ link: capitalisedShortCode });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// MARK: Return Insert Affiliate Identifier
|
|
155
198
|
const returnInsertAffiliateIdentifier = async (): Promise<string | null> => {
|
|
156
199
|
try {
|
|
157
200
|
return `${referrerLink}-${userId}`;
|
|
@@ -160,25 +203,9 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
160
203
|
return null;
|
|
161
204
|
}
|
|
162
205
|
}
|
|
163
|
-
|
|
164
|
-
// GENERATING UNIQUE USER ID
|
|
165
|
-
const generateUserID = () => {
|
|
166
|
-
const characters =
|
|
167
|
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
168
|
-
let uniqueId = "";
|
|
169
|
-
for (let i = 0; i < 6; i++) {
|
|
170
|
-
const randomIndex = Math.floor(Math.random() * characters.length);
|
|
171
|
-
uniqueId += characters[randomIndex];
|
|
172
|
-
}
|
|
173
|
-
return uniqueId;
|
|
174
|
-
};
|
|
175
206
|
|
|
176
|
-
// Helper function to determine if a link is a short code
|
|
177
|
-
const isShortCode = (referringLink: string): boolean => {
|
|
178
|
-
// Example check: short codes are less than 10 characters
|
|
179
|
-
return referringLink.length < 10;
|
|
180
|
-
};
|
|
181
207
|
|
|
208
|
+
// MARK: Insert Affiliate Identifier
|
|
182
209
|
const setInsertAffiliateIdentifier = async (
|
|
183
210
|
referringLink: string,
|
|
184
211
|
completion: (shortLink: string | null) => void
|
|
@@ -249,52 +276,19 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
249
276
|
completion(null);
|
|
250
277
|
}
|
|
251
278
|
};
|
|
252
|
-
|
|
253
|
-
async function setUserID() {
|
|
254
|
-
let userId = await getValueFromAsync(ASYNC_KEYS.USER_ID);
|
|
255
|
-
if (!userId) {
|
|
256
|
-
userId = generateUserID();
|
|
257
|
-
await saveValueInAsync(ASYNC_KEYS.USER_ID, userId);
|
|
258
|
-
setUserId(userId);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
async function setShortCode(shortCode: string): Promise<void> {
|
|
263
|
-
setUserID();
|
|
264
|
-
|
|
265
|
-
// Capitalise the shortcode
|
|
266
|
-
const capitalisedShortCode = shortCode.toUpperCase();
|
|
267
|
-
|
|
268
|
-
// Ensure the short code is exactly 10 characters long
|
|
269
|
-
if (capitalisedShortCode.length !== 10) {
|
|
270
|
-
console.error("[Insert Affiliate] Error: Short code must be exactly 10 characters long.");
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Check if the short code contains only letters and numbers
|
|
275
|
-
const isValidShortCode = /^[a-zA-Z0-9]+$/.test(capitalisedShortCode);
|
|
276
|
-
if (!isValidShortCode) {
|
|
277
|
-
console.error("[Insert Affiliate] Error: Short code must contain only letters and numbers.");
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// If all checks pass, set the Insert Affiliate Identifier
|
|
282
|
-
await storeInsertAffiliateIdentifier({ link: capitalisedShortCode });
|
|
283
|
-
|
|
284
|
-
if (referrerLink) {
|
|
285
|
-
console.log(`[Insert Affiliate] Successfully set affiliate identifier: ${referrerLink}`);
|
|
286
|
-
} else {
|
|
287
|
-
console.error("[Insert Affiliate] Failed to set affiliate identifier.");
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
279
|
+
|
|
291
280
|
async function storeInsertAffiliateIdentifier({ link }: { link: string }) {
|
|
292
281
|
console.log(`[Insert Affiliate] Storing affiliate identifier: ${link}`);
|
|
293
282
|
await saveValueInAsync(ASYNC_KEYS.REFERRER_LINK, link);
|
|
294
283
|
setReferrerLink(link);
|
|
295
284
|
}
|
|
296
285
|
|
|
297
|
-
const
|
|
286
|
+
const validatePurchaseWithIapticAPI = async (
|
|
287
|
+
jsonIapPurchase: CustomPurchase,
|
|
288
|
+
iapticAppId: string,
|
|
289
|
+
iapticAppName: string,
|
|
290
|
+
iapticPublicKey: string
|
|
291
|
+
): Promise<boolean> => {
|
|
298
292
|
try {
|
|
299
293
|
const baseRequestBody: RequestBody = {
|
|
300
294
|
id: iapticAppId,
|
|
@@ -324,10 +318,12 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
324
318
|
...baseRequestBody,
|
|
325
319
|
transaction,
|
|
326
320
|
};
|
|
327
|
-
|
|
328
|
-
|
|
321
|
+
|
|
322
|
+
let insertAffiliateIdentifier = await returnInsertAffiliateIdentifier();
|
|
323
|
+
|
|
324
|
+
if (insertAffiliateIdentifier) {
|
|
329
325
|
requestBody.additionalData = {
|
|
330
|
-
applicationUsername: `${
|
|
326
|
+
applicationUsername: `${insertAffiliateIdentifier}`,
|
|
331
327
|
};
|
|
332
328
|
}
|
|
333
329
|
|
|
@@ -351,15 +347,17 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
351
347
|
}
|
|
352
348
|
} catch (error) {
|
|
353
349
|
if (error instanceof Error) {
|
|
354
|
-
console.error(`
|
|
350
|
+
console.error(`validatePurchaseWithIapticAPI Error: ${error.message}`);
|
|
355
351
|
} else {
|
|
356
|
-
console.error(`
|
|
352
|
+
console.error(`validatePurchaseWithIapticAPI Unknown Error: ${JSON.stringify(error)}`);
|
|
357
353
|
}
|
|
358
354
|
|
|
359
355
|
return false;
|
|
360
356
|
}
|
|
361
357
|
};
|
|
358
|
+
|
|
362
359
|
|
|
360
|
+
// MARK: Track Event
|
|
363
361
|
const trackEvent = async (eventName: string): Promise<void> => {
|
|
364
362
|
try {
|
|
365
363
|
if (!referrerLink || !userId) {
|
|
@@ -402,7 +400,7 @@ const DeepLinkIapProvider: React.FC<T_DEEPLINK_IAP_PROVIDER> = ({
|
|
|
402
400
|
userId,
|
|
403
401
|
setShortCode,
|
|
404
402
|
returnInsertAffiliateIdentifier,
|
|
405
|
-
|
|
403
|
+
validatePurchaseWithIapticAPI,
|
|
406
404
|
trackEvent,
|
|
407
405
|
setInsertAffiliateIdentifier,
|
|
408
406
|
initialize,
|
|
@@ -5,7 +5,7 @@ const useDeepLinkIapProvider = () => {
|
|
|
5
5
|
const {
|
|
6
6
|
referrerLink,
|
|
7
7
|
userId,
|
|
8
|
-
|
|
8
|
+
validatePurchaseWithIapticAPI,
|
|
9
9
|
returnInsertAffiliateIdentifier,
|
|
10
10
|
trackEvent,
|
|
11
11
|
setShortCode,
|
|
@@ -17,7 +17,7 @@ const useDeepLinkIapProvider = () => {
|
|
|
17
17
|
return {
|
|
18
18
|
referrerLink,
|
|
19
19
|
userId,
|
|
20
|
-
|
|
20
|
+
validatePurchaseWithIapticAPI,
|
|
21
21
|
returnInsertAffiliateIdentifier,
|
|
22
22
|
trackEvent,
|
|
23
23
|
setShortCode,
|