gomarketme-react-native 1.0.5 → 1.0.7

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/README.md ADDED
@@ -0,0 +1,53 @@
1
+ <div align="center">
2
+ <img src="https://static.gomarketme.net/assets/gmm-icon.png" alt="GoMarketMe"/>
3
+ <br>
4
+ <h1>gomarketme-react-native</h1>
5
+ <p>Affiliate Marketing for React Native-Based iOS and Android Apps.</p>
6
+ </div>
7
+
8
+ ## Installation
9
+
10
+ ### Using npm
11
+
12
+ ```bash
13
+ npm install gomarketme-react-native
14
+ ```
15
+
16
+ ### Using yarn
17
+
18
+ ```bash
19
+ yarn add gomarketme-react-native
20
+ ```
21
+
22
+ ### Using pnpm
23
+
24
+ ```bash
25
+ pnpm add gomarketme-react-native
26
+ ```
27
+
28
+
29
+ ## Usage
30
+
31
+ To initialize GoMarketMe, import the `gomarketme` package and create a new instance of `GoMarketMe`:
32
+
33
+ ```tsx
34
+ import GoMarketMe from 'gomarketme-react-native';
35
+
36
+ const App: React.FC = () => {
37
+ const apiKey = 'YOUR_API_KEY_HERE';
38
+
39
+ useEffect(() => {
40
+ const initializeGoMarketMe = async () => {
41
+ await GoMarketMe.initialize(apiKey);
42
+ };
43
+
44
+ initializeGoMarketMe();
45
+ }, []);
46
+ };
47
+ ```
48
+
49
+ Make sure to replace API_KEY with your actual GoMarketMe API key. You can find it on the product onboarding page and under Profile > API Key.
50
+
51
+ ## Support
52
+
53
+ If you encounter any problems or issues, please contact us at [integrations@gomarketme.co](mailto:integrations@gomarketme.co) or visit [https://gomarketme.co](https://gomarketme.co).
package/dist/index.js CHANGED
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -35,15 +58,452 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
35
58
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
59
  }
37
60
  };
61
+ var __importDefault = (this && this.__importDefault) || function (mod) {
62
+ return (mod && mod.__esModule) ? mod : { "default": mod };
63
+ };
38
64
  Object.defineProperty(exports, "__esModule", { value: true });
39
- // src/index.ts
40
65
  var react_native_1 = require("react-native");
41
- var MySDK = react_native_1.NativeModules.MySDK;
42
- var MySDKWrapper = {
43
- someMethod: function (param) { return __awaiter(void 0, void 0, void 0, function () {
44
- return __generator(this, function (_a) {
45
- return [2 /*return*/, MySDK.someMethod(param)];
66
+ var react_native_device_info_1 = __importDefault(require("react-native-device-info"));
67
+ var RNLocalize = __importStar(require("react-native-localize"));
68
+ var async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
69
+ var react_native_iap_1 = __importDefault(require("react-native-iap"));
70
+ var axios_1 = __importDefault(require("axios"));
71
+ var GoMarketMe = /** @class */ (function () {
72
+ function GoMarketMe() {
73
+ this.sdkInitializedKey = 'GOMARKETME_SDK_INITIALIZED';
74
+ this.affiliateCampaignCode = '';
75
+ this.deviceId = '';
76
+ this.sdkInitializationUrl = 'https://api.gomarketme.net/v1/sdk-initialization';
77
+ this.systemInfoUrl = 'https://api.gomarketme.net/v1/mobile/system-info';
78
+ this.eventUrl = 'https://api.gomarketme.net/v1/event';
79
+ }
80
+ GoMarketMe.getInstance = function () {
81
+ if (!GoMarketMe.instance) {
82
+ GoMarketMe.instance = new GoMarketMe();
83
+ }
84
+ return GoMarketMe.instance;
85
+ };
86
+ GoMarketMe.prototype.initialize = function (apiKey) {
87
+ return __awaiter(this, void 0, void 0, function () {
88
+ var isSDKInitialized, systemInfo, e_1;
89
+ return __generator(this, function (_a) {
90
+ switch (_a.label) {
91
+ case 0:
92
+ _a.trys.push([0, 7, , 8]);
93
+ return [4 /*yield*/, this.isSDKInitialized()];
94
+ case 1:
95
+ isSDKInitialized = _a.sent();
96
+ if (!!isSDKInitialized) return [3 /*break*/, 3];
97
+ return [4 /*yield*/, this.postSDKInitialization(apiKey)];
98
+ case 2:
99
+ _a.sent();
100
+ _a.label = 3;
101
+ case 3: return [4 /*yield*/, this.getSystemInfo()];
102
+ case 4:
103
+ systemInfo = _a.sent();
104
+ return [4 /*yield*/, this.postSystemInfo(systemInfo, apiKey)];
105
+ case 5:
106
+ _a.sent();
107
+ return [4 /*yield*/, this.addListener(apiKey)];
108
+ case 6:
109
+ _a.sent();
110
+ return [3 /*break*/, 8];
111
+ case 7:
112
+ e_1 = _a.sent();
113
+ console.error('Error initializing GoMarketMe:', e_1);
114
+ return [3 /*break*/, 8];
115
+ case 8: return [2 /*return*/];
116
+ }
117
+ });
46
118
  });
47
- }); },
48
- };
49
- exports.default = MySDKWrapper;
119
+ };
120
+ GoMarketMe.prototype.addListener = function (apiKey) {
121
+ return __awaiter(this, void 0, void 0, function () {
122
+ var _this = this;
123
+ return __generator(this, function (_a) {
124
+ react_native_iap_1.default.purchaseUpdatedListener(function (purchase) { return __awaiter(_this, void 0, void 0, function () {
125
+ var productIds;
126
+ return __generator(this, function (_a) {
127
+ switch (_a.label) {
128
+ case 0:
129
+ if (!(this.affiliateCampaignCode != '')) return [3 /*break*/, 3];
130
+ return [4 /*yield*/, this.fetchPurchases([purchase], apiKey)];
131
+ case 1:
132
+ productIds = _a.sent();
133
+ return [4 /*yield*/, this.fetchPurchaseProducts(productIds, apiKey)];
134
+ case 2:
135
+ _a.sent();
136
+ _a.label = 3;
137
+ case 3: return [2 /*return*/];
138
+ }
139
+ });
140
+ }); });
141
+ return [2 /*return*/];
142
+ });
143
+ });
144
+ };
145
+ GoMarketMe.prototype.getSystemInfo = function () {
146
+ return __awaiter(this, void 0, void 0, function () {
147
+ var deviceData, _a, _b, devicePixelRatio, windowData;
148
+ var _c;
149
+ return __generator(this, function (_d) {
150
+ switch (_d.label) {
151
+ case 0:
152
+ _b = (_a = react_native_1.Platform).select;
153
+ _c = {};
154
+ return [4 /*yield*/, this.readIosDeviceInfo()];
155
+ case 1:
156
+ _c.ios = _d.sent();
157
+ return [4 /*yield*/, this.readAndroidDeviceInfo()];
158
+ case 2:
159
+ deviceData = _b.apply(_a, [(_c.android = _d.sent(),
160
+ _c)]);
161
+ devicePixelRatio = react_native_1.PixelRatio.get();
162
+ windowData = {
163
+ devicePixelRatio: devicePixelRatio,
164
+ width: react_native_1.Dimensions.get('window').width * devicePixelRatio,
165
+ height: react_native_1.Dimensions.get('window').height * devicePixelRatio,
166
+ };
167
+ return [2 /*return*/, {
168
+ device_info: deviceData,
169
+ window_info: windowData,
170
+ time_zone_code: this.getTimeZoneCode(),
171
+ language_code: this.getLanguageCode(),
172
+ }];
173
+ }
174
+ });
175
+ });
176
+ };
177
+ GoMarketMe.prototype.postSDKInitialization = function (apiKey) {
178
+ return __awaiter(this, void 0, void 0, function () {
179
+ var response, e_2;
180
+ return __generator(this, function (_a) {
181
+ switch (_a.label) {
182
+ case 0:
183
+ _a.trys.push([0, 5, , 6]);
184
+ return [4 /*yield*/, axios_1.default.post(this.sdkInitializationUrl, {}, {
185
+ headers: {
186
+ 'Content-Type': 'application/json',
187
+ 'x-api-key': apiKey,
188
+ },
189
+ })];
190
+ case 1:
191
+ response = _a.sent();
192
+ if (!(response.status === 200)) return [3 /*break*/, 3];
193
+ return [4 /*yield*/, this.markSDKAsInitialized()];
194
+ case 2:
195
+ _a.sent();
196
+ return [3 /*break*/, 4];
197
+ case 3:
198
+ console.error('Failed to mark SDK as Initialized. Status code:', response.status);
199
+ _a.label = 4;
200
+ case 4: return [3 /*break*/, 6];
201
+ case 5:
202
+ e_2 = _a.sent();
203
+ console.error('Error sending SDK information to server:', e_2);
204
+ return [3 /*break*/, 6];
205
+ case 6: return [2 /*return*/];
206
+ }
207
+ });
208
+ });
209
+ };
210
+ GoMarketMe.prototype.postSystemInfo = function (systemInfo, apiKey) {
211
+ return __awaiter(this, void 0, void 0, function () {
212
+ var response, responseData, e_3;
213
+ return __generator(this, function (_a) {
214
+ switch (_a.label) {
215
+ case 0:
216
+ _a.trys.push([0, 2, , 3]);
217
+ return [4 /*yield*/, axios_1.default.post(this.systemInfoUrl, systemInfo, {
218
+ headers: {
219
+ 'Content-Type': 'application/json',
220
+ 'x-api-key': apiKey,
221
+ },
222
+ })];
223
+ case 1:
224
+ response = _a.sent();
225
+ if (response.status === 200) {
226
+ responseData = response.data;
227
+ if (responseData.affiliate_campaign_code) {
228
+ this.affiliateCampaignCode = responseData.affiliate_campaign_code;
229
+ }
230
+ if (responseData.device_id) {
231
+ this.deviceId = responseData.device_id;
232
+ }
233
+ }
234
+ else {
235
+ console.error('Failed to send system info. Status code:', response.status);
236
+ }
237
+ return [3 /*break*/, 3];
238
+ case 2:
239
+ e_3 = _a.sent();
240
+ console.error('Error sending system info to server:', e_3);
241
+ return [3 /*break*/, 3];
242
+ case 3: return [2 /*return*/];
243
+ }
244
+ });
245
+ });
246
+ };
247
+ GoMarketMe.prototype.readAndroidDeviceInfo = function () {
248
+ return __awaiter(this, void 0, void 0, function () {
249
+ var _a;
250
+ return __generator(this, function (_b) {
251
+ switch (_b.label) {
252
+ case 0:
253
+ _a = {};
254
+ return [4 /*yield*/, react_native_device_info_1.default.getAndroidId()];
255
+ case 1:
256
+ _a.deviceId = _b.sent();
257
+ return [4 /*yield*/, react_native_device_info_1.default.getDeviceId()];
258
+ case 2:
259
+ _a._deviceId = _b.sent();
260
+ return [4 /*yield*/, react_native_device_info_1.default.getSystemName()];
261
+ case 3:
262
+ _a.systemName = _b.sent();
263
+ return [4 /*yield*/, react_native_device_info_1.default.getSystemVersion()];
264
+ case 4:
265
+ _a.systemVersion = _b.sent();
266
+ return [4 /*yield*/, react_native_device_info_1.default.getBrand()];
267
+ case 5:
268
+ _a.brand = _b.sent();
269
+ return [4 /*yield*/, react_native_device_info_1.default.getModel()];
270
+ case 6:
271
+ _a.model = _b.sent();
272
+ return [4 /*yield*/, react_native_device_info_1.default.getManufacturer()];
273
+ case 7:
274
+ _a.manufacturer = _b.sent();
275
+ return [4 /*yield*/, react_native_device_info_1.default.isEmulator()];
276
+ case 8:
277
+ _a.isEmulator = _b.sent();
278
+ return [4 /*yield*/, react_native_device_info_1.default.getUniqueId()];
279
+ case 9: return [2 /*return*/, (_a.uniqueId = _b.sent(),
280
+ _a)];
281
+ }
282
+ });
283
+ });
284
+ };
285
+ GoMarketMe.prototype.readIosDeviceInfo = function () {
286
+ return __awaiter(this, void 0, void 0, function () {
287
+ var info;
288
+ var _a;
289
+ return __generator(this, function (_b) {
290
+ switch (_b.label) {
291
+ case 0:
292
+ _a = {};
293
+ return [4 /*yield*/, react_native_device_info_1.default.getUniqueId()];
294
+ case 1:
295
+ _a.deviceId = _b.sent();
296
+ return [4 /*yield*/, react_native_device_info_1.default.getDeviceId()];
297
+ case 2:
298
+ _a._deviceId = _b.sent();
299
+ return [4 /*yield*/, react_native_device_info_1.default.getSystemName()];
300
+ case 3:
301
+ _a.systemName = _b.sent();
302
+ return [4 /*yield*/, react_native_device_info_1.default.getSystemVersion()];
303
+ case 4:
304
+ _a.systemVersion = _b.sent();
305
+ return [4 /*yield*/, react_native_device_info_1.default.getBrand()];
306
+ case 5:
307
+ _a.brand = _b.sent();
308
+ return [4 /*yield*/, react_native_device_info_1.default.getModel()];
309
+ case 6:
310
+ _a.model = _b.sent();
311
+ return [4 /*yield*/, react_native_device_info_1.default.getManufacturer()];
312
+ case 7:
313
+ _a.manufacturer = _b.sent();
314
+ return [4 /*yield*/, react_native_device_info_1.default.isEmulator()];
315
+ case 8:
316
+ _a.isEmulator = _b.sent();
317
+ return [4 /*yield*/, react_native_device_info_1.default.getUniqueId()];
318
+ case 9:
319
+ info = (_a.uniqueId = _b.sent(),
320
+ _a);
321
+ return [2 /*return*/];
322
+ }
323
+ });
324
+ });
325
+ };
326
+ GoMarketMe.prototype.getTimeZoneCode = function () {
327
+ // Convert the time zone to GMT format (e.g., "GMT+2")
328
+ var timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
329
+ var date = new Date();
330
+ var timezoneOffset = date.getTimezoneOffset(); // in minutes
331
+ var absOffset = Math.abs(timezoneOffset);
332
+ var hours = Math.floor(absOffset / 60);
333
+ var minutes = absOffset % 60;
334
+ var sign = timezoneOffset > 0 ? '-' : '+';
335
+ return "GMT".concat(sign).concat(String(hours).padStart(2, '0'), ":").concat(String(minutes).padStart(2, '0')); // Return GMT format
336
+ };
337
+ GoMarketMe.prototype.getLanguageCode = function () {
338
+ var locales = RNLocalize.getLocales();
339
+ return locales.length > 0 ? locales[0].languageTag : 'en-US';
340
+ };
341
+ GoMarketMe.prototype.fetchPurchases = function (purchaseDetailsList, apiKey) {
342
+ return __awaiter(this, void 0, void 0, function () {
343
+ var productIds, _i, purchaseDetailsList_1, purchase;
344
+ return __generator(this, function (_a) {
345
+ switch (_a.label) {
346
+ case 0:
347
+ productIds = [];
348
+ _i = 0, purchaseDetailsList_1 = purchaseDetailsList;
349
+ _a.label = 1;
350
+ case 1:
351
+ if (!(_i < purchaseDetailsList_1.length)) return [3 /*break*/, 4];
352
+ purchase = purchaseDetailsList_1[_i];
353
+ if (!purchase.transactionReceipt) return [3 /*break*/, 3];
354
+ return [4 /*yield*/, this.sendEventToServer(JSON.stringify(this.serializePurchaseDetails(purchase)), 'purchase', apiKey)];
355
+ case 2:
356
+ _a.sent();
357
+ if (purchase.productId && !productIds.includes(purchase.productId)) {
358
+ productIds.push(purchase.productId);
359
+ }
360
+ _a.label = 3;
361
+ case 3:
362
+ _i++;
363
+ return [3 /*break*/, 1];
364
+ case 4: return [2 /*return*/, productIds];
365
+ }
366
+ });
367
+ });
368
+ };
369
+ GoMarketMe.prototype.fetchPurchaseProducts = function (productIds, apiKey) {
370
+ return __awaiter(this, void 0, void 0, function () {
371
+ var products, _i, products_1, product, e_4;
372
+ return __generator(this, function (_a) {
373
+ switch (_a.label) {
374
+ case 0:
375
+ _a.trys.push([0, 9, , 10]);
376
+ return [4 /*yield*/, react_native_iap_1.default.getProducts({ skus: productIds })];
377
+ case 1:
378
+ products = _a.sent();
379
+ if (!(products.length > 0)) return [3 /*break*/, 6];
380
+ _i = 0, products_1 = products;
381
+ _a.label = 2;
382
+ case 2:
383
+ if (!(_i < products_1.length)) return [3 /*break*/, 5];
384
+ product = products_1[_i];
385
+ return [4 /*yield*/, this.sendEventToServer(JSON.stringify(this.serializeProductDetails(product)), 'product', apiKey)];
386
+ case 3:
387
+ _a.sent();
388
+ _a.label = 4;
389
+ case 4:
390
+ _i++;
391
+ return [3 /*break*/, 2];
392
+ case 5: return [3 /*break*/, 8];
393
+ case 6: return [4 /*yield*/, this.sendEventToServer(JSON.stringify({ notFoundIDs: productIds.join(',') }), 'product', apiKey)];
394
+ case 7:
395
+ _a.sent();
396
+ _a.label = 8;
397
+ case 8: return [3 /*break*/, 10];
398
+ case 9:
399
+ e_4 = _a.sent();
400
+ console.error('Error fetching products:', e_4);
401
+ return [3 /*break*/, 10];
402
+ case 10: return [2 /*return*/];
403
+ }
404
+ });
405
+ });
406
+ };
407
+ GoMarketMe.prototype.sendEventToServer = function (body, eventType, apiKey) {
408
+ return __awaiter(this, void 0, void 0, function () {
409
+ var response, e_5;
410
+ return __generator(this, function (_a) {
411
+ switch (_a.label) {
412
+ case 0:
413
+ _a.trys.push([0, 2, , 3]);
414
+ return [4 /*yield*/, axios_1.default.post(this.eventUrl, body, {
415
+ headers: {
416
+ 'Content-Type': 'application/json',
417
+ 'x-affiliate-campaign-code': this.affiliateCampaignCode,
418
+ 'x-device-id': this.deviceId,
419
+ 'x-event-type': eventType,
420
+ 'x-product-type': react_native_1.Platform.OS,
421
+ 'x-source-name': react_native_1.Platform.OS === 'android' ? 'google_play' : 'app_store',
422
+ 'x-api-key': apiKey,
423
+ },
424
+ })];
425
+ case 1:
426
+ response = _a.sent();
427
+ if (response.status === 200) {
428
+ console.log("".concat(eventType, " sent successfully"));
429
+ }
430
+ else {
431
+ console.error("Failed to send ".concat(eventType, ". Status code:"), response.status);
432
+ }
433
+ return [3 /*break*/, 3];
434
+ case 2:
435
+ e_5 = _a.sent();
436
+ console.error("Error sending ".concat(eventType, " to server:"), e_5);
437
+ return [3 /*break*/, 3];
438
+ case 3: return [2 /*return*/];
439
+ }
440
+ });
441
+ });
442
+ };
443
+ GoMarketMe.prototype.serializePurchaseDetails = function (purchase) {
444
+ return {
445
+ productID: purchase.productId,
446
+ purchaseID: purchase.transactionId || '',
447
+ transactionDate: purchase.transactionDate || '',
448
+ status: react_native_1.Platform.select({
449
+ ios: purchase.transactionStateIOS, // Removed non-existent properties
450
+ android: purchase.purchaseStateAndroid,
451
+ }),
452
+ verificationData: {
453
+ localVerificationData: purchase.transactionReceipt,
454
+ },
455
+ };
456
+ };
457
+ GoMarketMe.prototype.serializeProductDetails = function (product) {
458
+ return {
459
+ productID: product.productId,
460
+ productTitle: product.title,
461
+ productDescription: product.description,
462
+ productPrice: product.price,
463
+ productRawPrice: product.price,
464
+ productCurrencyCode: product.currency,
465
+ };
466
+ };
467
+ GoMarketMe.prototype.markSDKAsInitialized = function () {
468
+ return __awaiter(this, void 0, void 0, function () {
469
+ var e_6;
470
+ return __generator(this, function (_a) {
471
+ switch (_a.label) {
472
+ case 0:
473
+ _a.trys.push([0, 2, , 3]);
474
+ return [4 /*yield*/, async_storage_1.default.setItem(this.sdkInitializedKey, 'true')];
475
+ case 1:
476
+ _a.sent();
477
+ return [2 /*return*/, true];
478
+ case 2:
479
+ e_6 = _a.sent();
480
+ console.error('Failed to save SDK initialization:', e_6);
481
+ return [2 /*return*/, false];
482
+ case 3: return [2 /*return*/];
483
+ }
484
+ });
485
+ });
486
+ };
487
+ GoMarketMe.prototype.isSDKInitialized = function () {
488
+ return __awaiter(this, void 0, void 0, function () {
489
+ var value, e_7;
490
+ return __generator(this, function (_a) {
491
+ switch (_a.label) {
492
+ case 0:
493
+ _a.trys.push([0, 2, , 3]);
494
+ return [4 /*yield*/, async_storage_1.default.getItem(this.sdkInitializedKey)];
495
+ case 1:
496
+ value = _a.sent();
497
+ return [2 /*return*/, value === 'true'];
498
+ case 2:
499
+ e_7 = _a.sent();
500
+ console.error('Failed to load SDK initialization:', e_7);
501
+ return [2 /*return*/, false];
502
+ case 3: return [2 /*return*/];
503
+ }
504
+ });
505
+ });
506
+ };
507
+ return GoMarketMe;
508
+ }());
509
+ exports.default = GoMarketMe.getInstance();
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "gomarketme-react-native",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Affiliate Marketing for React Native-Based iOS and Android Apps.",
5
- "main": "index.js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "homepage": "https://gomarketme.co",
7
8
  "keywords": [
8
9
  "react-native",
package/src/index.tsx ADDED
@@ -0,0 +1,256 @@
1
+ import { Platform, Dimensions, PixelRatio } from 'react-native';
2
+ import DeviceInfo from 'react-native-device-info';
3
+ import * as RNLocalize from 'react-native-localize';
4
+ import AsyncStorage from '@react-native-async-storage/async-storage';
5
+ import InAppPurchase, { Purchase, Product } from 'react-native-iap';
6
+ import axios from 'axios';
7
+
8
+ class GoMarketMe {
9
+ private static instance: GoMarketMe;
10
+ private sdkInitializedKey = 'GOMARKETME_SDK_INITIALIZED';
11
+ private affiliateCampaignCode = '';
12
+ private deviceId = '';
13
+ private sdkInitializationUrl = 'https://api.gomarketme.net/v1/sdk-initialization';
14
+ private systemInfoUrl = 'https://api.gomarketme.net/v1/mobile/system-info';
15
+ private eventUrl = 'https://api.gomarketme.net/v1/event';
16
+
17
+ private constructor() {}
18
+
19
+ public static getInstance(): GoMarketMe {
20
+ if (!GoMarketMe.instance) {
21
+ GoMarketMe.instance = new GoMarketMe();
22
+ }
23
+ return GoMarketMe.instance;
24
+ }
25
+
26
+ public async initialize(apiKey: string): Promise<void> {
27
+ try {
28
+ const isSDKInitialized = await this.isSDKInitialized();
29
+ if (!isSDKInitialized) {
30
+ await this.postSDKInitialization(apiKey);
31
+ }
32
+ const systemInfo = await this.getSystemInfo();
33
+ await this.postSystemInfo(systemInfo, apiKey);
34
+ await this.addListener(apiKey);
35
+ } catch (e) {
36
+ console.error('Error initializing GoMarketMe:', e);
37
+ }
38
+ }
39
+
40
+ private async addListener(apiKey: string): Promise<void> {
41
+ InAppPurchase.purchaseUpdatedListener(async (purchase: Purchase) => {
42
+ if (this.affiliateCampaignCode != '') {
43
+ const productIds = await this.fetchPurchases([purchase], apiKey);
44
+ await this.fetchPurchaseProducts(productIds, apiKey);
45
+ }
46
+ });
47
+ }
48
+
49
+ private async getSystemInfo(): Promise<any> {
50
+ const deviceData = Platform.select({
51
+ ios: await this.readIosDeviceInfo(),
52
+ android: await this.readAndroidDeviceInfo(),
53
+ });
54
+
55
+ const devicePixelRatio = PixelRatio.get();
56
+
57
+ const windowData = {
58
+ devicePixelRatio: devicePixelRatio,
59
+ width: Dimensions.get('window').width * devicePixelRatio,
60
+ height: Dimensions.get('window').height * devicePixelRatio,
61
+ };
62
+
63
+ return {
64
+ device_info: deviceData,
65
+ window_info: windowData,
66
+ time_zone_code: this.getTimeZoneCode(),
67
+ language_code: this.getLanguageCode(),
68
+ };
69
+ }
70
+
71
+ private async postSDKInitialization(apiKey: string): Promise<void> {
72
+ try {
73
+ const response = await axios.post(this.sdkInitializationUrl, {}, {
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ 'x-api-key': apiKey,
77
+ },
78
+ });
79
+ if (response.status === 200) {
80
+ await this.markSDKAsInitialized();
81
+ } else {
82
+ console.error('Failed to mark SDK as Initialized. Status code:', response.status);
83
+ }
84
+ } catch (e) {
85
+ console.error('Error sending SDK information to server:', e);
86
+ }
87
+ }
88
+
89
+ private async postSystemInfo(systemInfo: any, apiKey: string): Promise<void> {
90
+ try {
91
+ const response = await axios.post(this.systemInfoUrl, systemInfo, {
92
+ headers: {
93
+ 'Content-Type': 'application/json',
94
+ 'x-api-key': apiKey,
95
+ },
96
+ });
97
+ if (response.status === 200) {
98
+ const responseData = response.data;
99
+ if (responseData.affiliate_campaign_code) {
100
+ this.affiliateCampaignCode = responseData.affiliate_campaign_code;
101
+ }
102
+ if (responseData.device_id) {
103
+ this.deviceId = responseData.device_id;
104
+ }
105
+ } else {
106
+ console.error('Failed to send system info. Status code:', response.status);
107
+ }
108
+ } catch (e) {
109
+ console.error('Error sending system info to server:', e);
110
+ }
111
+ }
112
+
113
+ private async readAndroidDeviceInfo(): Promise<any> {
114
+ return {
115
+ deviceId: await DeviceInfo.getAndroidId(),
116
+ _deviceId: await DeviceInfo.getDeviceId(),
117
+ systemName: await DeviceInfo.getSystemName(),
118
+ systemVersion: await DeviceInfo.getSystemVersion(),
119
+ brand: await DeviceInfo.getBrand(),
120
+ model: await DeviceInfo.getModel(),
121
+ manufacturer: await DeviceInfo.getManufacturer(),
122
+ isEmulator: await DeviceInfo.isEmulator(),
123
+ uniqueId: await DeviceInfo.getUniqueId(),
124
+ };
125
+ }
126
+
127
+ private async readIosDeviceInfo(): Promise<any> {
128
+ var info = {
129
+ deviceId: await DeviceInfo.getUniqueId(),
130
+ _deviceId: await DeviceInfo.getDeviceId(),
131
+ systemName: await DeviceInfo.getSystemName(),
132
+ systemVersion: await DeviceInfo.getSystemVersion(),
133
+ brand: await DeviceInfo.getBrand(),
134
+ model: await DeviceInfo.getModel(),
135
+ manufacturer: await DeviceInfo.getManufacturer(),
136
+ isEmulator: await DeviceInfo.isEmulator(),
137
+ uniqueId: await DeviceInfo.getUniqueId(),
138
+ };
139
+ }
140
+
141
+ private getTimeZoneCode(): string {
142
+ // Convert the time zone to GMT format (e.g., "GMT+2")
143
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
144
+ const date = new Date();
145
+ const timezoneOffset = date.getTimezoneOffset(); // in minutes
146
+ const absOffset = Math.abs(timezoneOffset);
147
+ const hours = Math.floor(absOffset / 60);
148
+ const minutes = absOffset % 60;
149
+ const sign = timezoneOffset > 0 ? '-' : '+';
150
+ return `GMT${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; // Return GMT format
151
+ }
152
+
153
+ private getLanguageCode(): string {
154
+ const locales = RNLocalize.getLocales();
155
+ return locales.length > 0 ? locales[0].languageTag : 'en-US';
156
+ }
157
+
158
+ private async fetchPurchases(purchaseDetailsList: Purchase[], apiKey: string): Promise<string[]> {
159
+ const productIds: string[] = [];
160
+ for (const purchase of purchaseDetailsList) {
161
+ if (purchase.transactionReceipt) {
162
+ await this.sendEventToServer(JSON.stringify(this.serializePurchaseDetails(purchase)), 'purchase', apiKey);
163
+ if (purchase.productId && !productIds.includes(purchase.productId)) {
164
+ productIds.push(purchase.productId);
165
+ }
166
+ }
167
+ }
168
+ return productIds;
169
+ }
170
+
171
+ private async fetchPurchaseProducts(productIds: string[], apiKey: string): Promise<void> {
172
+ try {
173
+ const products = await InAppPurchase.getProducts({skus: productIds});
174
+ if (products.length > 0) {
175
+ for (const product of products) {
176
+ await this.sendEventToServer(JSON.stringify(this.serializeProductDetails(product)), 'product', apiKey);
177
+ }
178
+ } else {
179
+ await this.sendEventToServer(JSON.stringify({ notFoundIDs: productIds.join(',') }), 'product', apiKey);
180
+ }
181
+ } catch (e) {
182
+ console.error('Error fetching products:', e);
183
+ }
184
+ }
185
+
186
+ private async sendEventToServer(body: string, eventType: string, apiKey: string): Promise<void> {
187
+ try {
188
+ const response = await axios.post(this.eventUrl, body, {
189
+ headers: {
190
+ 'Content-Type': 'application/json',
191
+ 'x-affiliate-campaign-code': this.affiliateCampaignCode,
192
+ 'x-device-id': this.deviceId,
193
+ 'x-event-type': eventType,
194
+ 'x-product-type': Platform.OS,
195
+ 'x-source-name': Platform.OS === 'android' ? 'google_play' : 'app_store',
196
+ 'x-api-key': apiKey,
197
+ },
198
+ });
199
+ if (response.status === 200) {
200
+ console.log(`${eventType} sent successfully`);
201
+ } else {
202
+ console.error(`Failed to send ${eventType}. Status code:`, response.status);
203
+ }
204
+ } catch (e) {
205
+ console.error(`Error sending ${eventType} to server:`, e);
206
+ }
207
+ }
208
+
209
+ private serializePurchaseDetails(purchase: Purchase): any {
210
+ return {
211
+ productID: purchase.productId,
212
+ purchaseID: purchase.transactionId || '',
213
+ transactionDate: purchase.transactionDate || '',
214
+ status: Platform.select({
215
+ ios: (purchase as any).transactionStateIOS, // Removed non-existent properties
216
+ android: (purchase as any).purchaseStateAndroid,
217
+ }),
218
+ verificationData: {
219
+ localVerificationData: purchase.transactionReceipt,
220
+ },
221
+ };
222
+ }
223
+
224
+ private serializeProductDetails(product: Product): any {
225
+ return {
226
+ productID: product.productId,
227
+ productTitle: product.title,
228
+ productDescription: product.description,
229
+ productPrice: product.price,
230
+ productRawPrice: product.price,
231
+ productCurrencyCode: product.currency,
232
+ };
233
+ }
234
+
235
+ private async markSDKAsInitialized(): Promise<boolean> {
236
+ try {
237
+ await AsyncStorage.setItem(this.sdkInitializedKey, 'true');
238
+ return true;
239
+ } catch (e) {
240
+ console.error('Failed to save SDK initialization:', e);
241
+ return false;
242
+ }
243
+ }
244
+
245
+ private async isSDKInitialized(): Promise<boolean> {
246
+ try {
247
+ const value = await AsyncStorage.getItem(this.sdkInitializedKey);
248
+ return value === 'true';
249
+ } catch (e) {
250
+ console.error('Failed to load SDK initialization:', e);
251
+ return false;
252
+ }
253
+ }
254
+ }
255
+
256
+ export default GoMarketMe.getInstance();
package/tsconfig.json CHANGED
@@ -1,15 +1,19 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "es5",
3
+ "target": "ES5",
4
4
  "module": "commonjs",
5
5
  "lib": ["es6", "dom"],
6
+ "allowJs": true,
6
7
  "jsx": "react",
8
+ "declaration": true,
7
9
  "strict": true,
8
10
  "esModuleInterop": true,
9
11
  "skipLibCheck": true,
10
12
  "forceConsistentCasingInFileNames": true,
11
- "outDir": "./dist"
13
+ "moduleResolution": "node",
14
+ "outDir": "./dist",
15
+ "rootDir": "./src"
12
16
  },
13
- "include": ["src/**/*"],
14
- "exclude": ["node_modules", "**/*.spec.ts"]
17
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
18
+ "exclude": ["node_modules", "dist", "**/__tests__/*"]
15
19
  }
package/src/index.ts DELETED
@@ -1,16 +0,0 @@
1
- // src/index.ts
2
- import { NativeModules } from 'react-native';
3
-
4
- const { MySDK } = NativeModules;
5
-
6
- interface MySDKInterface {
7
- someMethod(param: string): Promise<string>;
8
- }
9
-
10
- const MySDKWrapper: MySDKInterface = {
11
- someMethod: async (param) => {
12
- return MySDK.someMethod(param);
13
- },
14
- };
15
-
16
- export default MySDKWrapper;