gomarketme-react-native 1.1.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gomarketme-react-native",
3
- "version": "1.1.1",
3
+ "version": "4.0.0",
4
4
  "description": "Affiliate Marketing for React Native-Based iOS and Android Apps.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,16 +18,17 @@
18
18
  "author": "GoMarketMe",
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "@react-native-async-storage/async-storage": "^1.15.6",
22
- "axios": "^0.21.1",
23
- "get-user-locale": "^2.3.2",
24
- "react-native-device-info": "^14.0.0",
25
- "react-native-iap": "^7.0.0"
21
+ "@react-native-async-storage/async-storage": "^2.2.0",
22
+ "axios": "^1.13.2",
23
+ "get-user-locale": "^3.0.0",
24
+ "react-native-device-info": "^14.1.1",
25
+ "react-native-iap": "^14.4.38",
26
+ "react-native-nitro-modules": "^0.31.4"
26
27
  },
27
28
  "devDependencies": {
28
- "@types/node": "^15.12.5",
29
- "@types/react-native": "^0.64.12",
30
- "typescript": "^4.3.5"
29
+ "@types/node": "^24.10.0",
30
+ "@types/react-native": "^0.73.0",
31
+ "typescript": "^5.9.3"
31
32
  },
32
33
  "peerDependencies": {
33
34
  "react": "*",
package/src/index.tsx CHANGED
@@ -1,285 +1,390 @@
1
1
  import { Platform, Dimensions, PixelRatio } from 'react-native';
2
2
  import DeviceInfo from 'react-native-device-info';
3
- import getUserLocale from 'get-user-locale'
3
+ import getUserLocale from 'get-user-locale';
4
4
  import AsyncStorage from '@react-native-async-storage/async-storage';
5
- import InAppPurchase, { Purchase, Product, Subscription } from 'react-native-iap';
6
5
  import axios from 'axios';
7
6
 
7
+ import {
8
+ type Purchase,
9
+ type PurchaseError,
10
+ purchaseUpdatedListener,
11
+ purchaseErrorListener,
12
+ fetchProducts,
13
+ ProductCommon,
14
+ PurchaseCommon,
15
+ getAvailablePurchases,
16
+ } from 'react-native-iap';
17
+
18
+ export class GoMarketMeAffiliateMarketingData {
19
+ campaign: Campaign;
20
+ affiliate: Affiliate;
21
+ saleDistribution: SaleDistribution;
22
+ affiliateCampaignCode: string;
23
+ deviceId: string;
24
+ offerCode?: string;
25
+
26
+ constructor(
27
+ campaign: Campaign,
28
+ affiliate: Affiliate,
29
+ saleDistribution: SaleDistribution,
30
+ affiliateCampaignCode: string,
31
+ deviceId: string,
32
+ offerCode?: string
33
+ ) {
34
+ this.campaign = campaign;
35
+ this.affiliate = affiliate;
36
+ this.saleDistribution = saleDistribution;
37
+ this.affiliateCampaignCode = affiliateCampaignCode;
38
+ this.deviceId = deviceId;
39
+ this.offerCode = offerCode;
40
+ }
41
+
42
+ static fromJson(json: Record<string, any>): GoMarketMeAffiliateMarketingData | null {
43
+ if (!json || Object.keys(json).length === 0) return null;
44
+ return new GoMarketMeAffiliateMarketingData(
45
+ Campaign.fromJson(json.campaign),
46
+ Affiliate.fromJson(json.affiliate),
47
+ SaleDistribution.fromJson(json.sale_distribution),
48
+ json.affiliate_campaign_code || '',
49
+ json.device_id || '',
50
+ json.offer_code
51
+ );
52
+ }
53
+ }
54
+
55
+ export class Campaign {
56
+ id: string;
57
+ name: string;
58
+ status: string;
59
+ type: string;
60
+ publicLinkUrl?: string;
61
+
62
+ constructor(id: string, name: string, status: string, type: string, publicLinkUrl?: string) {
63
+ this.id = id;
64
+ this.name = name;
65
+ this.status = status;
66
+ this.type = type;
67
+ this.publicLinkUrl = publicLinkUrl;
68
+ }
69
+
70
+ static fromJson(json: Record<string, any>): Campaign {
71
+ return new Campaign(
72
+ json?.id || '',
73
+ json?.name || '',
74
+ json?.status || '',
75
+ json?.type || '',
76
+ json?.public_link_url
77
+ );
78
+ }
79
+ }
80
+
81
+ export class Affiliate {
82
+ id: string;
83
+ firstName: string;
84
+ lastName: string;
85
+ countryCode: string;
86
+ instagramAccount: string;
87
+ tiktokAccount: string;
88
+ xAccount: string;
89
+
90
+ constructor(
91
+ id: string,
92
+ firstName: string,
93
+ lastName: string,
94
+ countryCode: string,
95
+ instagramAccount: string,
96
+ tiktokAccount: string,
97
+ xAccount: string
98
+ ) {
99
+ this.id = id;
100
+ this.firstName = firstName;
101
+ this.lastName = lastName;
102
+ this.countryCode = countryCode;
103
+ this.instagramAccount = instagramAccount;
104
+ this.tiktokAccount = tiktokAccount;
105
+ this.xAccount = xAccount;
106
+ }
107
+
108
+ static fromJson(json: Record<string, any>): Affiliate {
109
+ return new Affiliate(
110
+ json?.id || '',
111
+ json?.first_name || '',
112
+ json?.last_name || '',
113
+ json?.country_code || '',
114
+ json?.instagram_account || '',
115
+ json?.tiktok_account || '',
116
+ json?.x_account || ''
117
+ );
118
+ }
119
+ }
120
+
121
+ export class SaleDistribution {
122
+ platformPercentage: string;
123
+ affiliatePercentage: string;
124
+
125
+ constructor(platformPercentage: string, affiliatePercentage: string) {
126
+ this.platformPercentage = platformPercentage;
127
+ this.affiliatePercentage = affiliatePercentage;
128
+ }
129
+
130
+ static fromJson(json: Record<string, any>): SaleDistribution {
131
+ return new SaleDistribution(json?.platform_percentage || '', json?.affiliate_percentage || '');
132
+ }
133
+ }
134
+
8
135
  class GoMarketMe {
9
136
  private static instance: GoMarketMe;
137
+ private sdkType = 'ReactNative';
138
+ private sdkVersion = '4.0.0';
10
139
  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';
140
+ private sdkInitializationUrl =
141
+ 'https://4v9008q1a5.execute-api.us-west-2.amazonaws.com/prod/v1/sdk-initialization';
142
+ private systemInfoUrl =
143
+ 'https://4v9008q1a5.execute-api.us-west-2.amazonaws.com/prod/v1/mobile/system-info';
144
+ private eventUrl = 'https://4v9008q1a5.execute-api.us-west-2.amazonaws.com/prod/v1/event';
145
+ private _affiliateCampaignCode = '';
146
+ private _deviceId = '';
147
+ private _packageName = '';
148
+ private _purchaseUpdateUnsub?: ReturnType<typeof purchaseUpdatedListener>;
149
+ private _purchaseErrorUnsub?: ReturnType<typeof purchaseErrorListener>;
150
+ public affiliateMarketingData?: GoMarketMeAffiliateMarketingData | null;
16
151
 
17
- private constructor() {}
152
+ private constructor() { }
18
153
 
19
154
  public static getInstance(): GoMarketMe {
20
- if (!GoMarketMe.instance) {
21
- GoMarketMe.instance = new GoMarketMe();
22
- }
155
+ if (!GoMarketMe.instance) GoMarketMe.instance = new GoMarketMe();
23
156
  return GoMarketMe.instance;
24
157
  }
25
158
 
26
159
  public async initialize(apiKey: string): Promise<void> {
27
160
  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);
161
+ const isSDKInitialized = await this._isSDKInitialized();
162
+ if (!isSDKInitialized) await this._postSDKInitialization(apiKey);
163
+ this._packageName = DeviceInfo.getBundleId();
164
+ const systemInfo = await this._getSystemInfo();
165
+ this.affiliateMarketingData = await this._postSystemInfo(systemInfo, apiKey);
166
+ await this._addListeners(apiKey);
167
+ this._fetchExistingPurchases(apiKey).catch(e => {
168
+ console.log('Error in background purchase fetch:', e);
169
+ });
35
170
  } catch (e) {
36
- console.error('Error initializing GoMarketMe:', e);
171
+ console.log('Error initializing GoMarketMe:', e);
37
172
  }
38
173
  }
39
174
 
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
- });
175
+ public removeListeners(): void {
176
+ try {
177
+ this._purchaseUpdateUnsub?.remove?.();
178
+ this._purchaseErrorUnsub?.remove?.();
179
+ } catch (e) {
180
+ console.log('Error removing listeners:', e);
181
+ }
47
182
  }
48
183
 
49
- private async getSystemInfo(): Promise<any> {
50
- const deviceData = Platform.select({
51
- ios: await this.readIosDeviceInfo(),
52
- android: await this.readAndroidDeviceInfo(),
53
- });
54
-
184
+ private async _addListeners(apiKey: string): Promise<void> {
185
+ if (!this._purchaseUpdateUnsub) {
186
+ this._purchaseUpdateUnsub = purchaseUpdatedListener(async (purchase: Purchase) => {
187
+ try {
188
+ await this._fetchConsolidatedPurchases([purchase], apiKey);
189
+ } catch (e) {
190
+ console.log('purchaseUpdated error:', e);
191
+ }
192
+ });
193
+ }
194
+
195
+ if (!this._purchaseErrorUnsub) {
196
+ this._purchaseErrorUnsub = purchaseErrorListener((error: PurchaseError) => {
197
+ console.log('purchaseErrorListener:', error);
198
+ });
199
+ }
200
+ }
201
+
202
+ private async _getSystemInfo(): Promise<any> {
203
+ const deviceData =
204
+ Platform.OS === 'ios'
205
+ ? await this._readIosDeviceInfo()
206
+ : await this._readAndroidDeviceInfo();
207
+
208
+ this._deviceId = deviceData['deviceId'] || '';
209
+
55
210
  const devicePixelRatio = PixelRatio.get();
56
211
  const dimension = Dimensions.get('window');
57
-
58
- const windowData = {
59
- devicePixelRatio: devicePixelRatio,
60
- width: dimension.width * devicePixelRatio,
61
- height: dimension.height * devicePixelRatio,
62
- };
63
-
212
+
64
213
  return {
65
214
  device_info: deviceData,
66
- window_info: windowData,
67
- time_zone: this.getTimeZone(),
68
- language_code: this.getLanguageCode(),
215
+ window_info: {
216
+ devicePixelRatio,
217
+ width: dimension.width * devicePixelRatio,
218
+ height: dimension.height * devicePixelRatio,
219
+ },
220
+ time_zone: Intl.DateTimeFormat().resolvedOptions().timeZone,
221
+ language_code: getUserLocale(),
222
+ sdk_type: this.sdkType,
223
+ sdk_version: this.sdkVersion,
224
+ package_name: this._packageName,
225
+ is_production: await this._isProduction()
69
226
  };
70
227
  }
71
228
 
72
- private async postSDKInitialization(apiKey: string): Promise<void> {
229
+ private async _postSDKInitialization(apiKey: string): Promise<void> {
73
230
  try {
74
- const response = await axios.post(this.sdkInitializationUrl, {}, {
75
- headers: {
76
- 'Content-Type': 'application/json',
77
- 'x-api-key': apiKey,
78
- },
231
+ const res = await axios.post(this.sdkInitializationUrl, {}, {
232
+ headers: { 'x-api-key': apiKey },
79
233
  });
80
- if (response.status === 200) {
81
- await this.markSDKAsInitialized();
82
- } else {
83
- console.error('Failed to mark SDK as Initialized. Status code:', response.status);
84
- }
234
+ if (res.status === 200) await this._markSDKAsInitialized();
85
235
  } catch (e) {
86
- console.error('Error sending SDK information to server:', e);
236
+ console.log('Error posting SDK initialization:', e);
87
237
  }
88
238
  }
89
239
 
90
- private async postSystemInfo(systemInfo: any, apiKey: string): Promise<void> {
240
+ private async _postSystemInfo(data: any, apiKey: string) {
91
241
  try {
92
- const response = await axios.post(this.systemInfoUrl, systemInfo, {
93
- headers: {
94
- 'Content-Type': 'application/json',
95
- 'x-api-key': apiKey,
96
- },
242
+ const res = await axios.post(this.systemInfoUrl, data, {
243
+ headers: { 'x-api-key': apiKey },
97
244
  });
98
- if (response.status === 200) {
99
- const responseData = response.data;
100
- if (responseData.affiliate_campaign_code) {
101
- this.affiliateCampaignCode = responseData.affiliate_campaign_code;
102
- }
103
- if (responseData.device_id) {
104
- this.deviceId = responseData.device_id;
105
- }
106
-
107
- } else {
108
- console.error('Failed to send system info. Status code:', response.status);
245
+ if (res.status === 200) {
246
+ const obj = GoMarketMeAffiliateMarketingData.fromJson(res.data);
247
+ if (obj) this._affiliateCampaignCode = obj.affiliateCampaignCode;
248
+ return obj;
109
249
  }
110
250
  } catch (e) {
111
- console.error('Error sending system info to server:', e);
251
+ console.log('Error posting system info:', e);
112
252
  }
253
+ return null;
113
254
  }
114
255
 
115
- private async readAndroidDeviceInfo(): Promise<any> {
116
-
117
- let androidId = await DeviceInfo.getAndroidId();
118
- let uniqueId = await DeviceInfo.getUniqueId();
119
- let deviceId = await DeviceInfo.getDeviceId(); // model
120
- let systemName = await DeviceInfo.getSystemName();
121
- let systemVersion = await DeviceInfo.getSystemVersion()
122
- let brand = await DeviceInfo.getBrand();
123
- let model = await DeviceInfo.getModel();
124
- let manufacturer = await DeviceInfo.getManufacturer();
125
- let isEmulator = await DeviceInfo.isEmulator();
126
-
256
+ private async _readAndroidDeviceInfo() {
127
257
  return {
128
- deviceId: androidId,
129
- _deviceId: deviceId,
130
- _uniqueId: uniqueId,
131
- systemName: systemName,
132
- systemVersion: systemVersion,
133
- brand: brand,
134
- model: model,
135
- manufacturer: manufacturer,
136
- isEmulator: isEmulator
258
+ deviceId: await DeviceInfo.getAndroidId(),
259
+ brand: await DeviceInfo.getBrand(),
260
+ model: await DeviceInfo.getModel(),
261
+ manufacturer: await DeviceInfo.getManufacturer(),
262
+ systemName: await DeviceInfo.getSystemName(),
263
+ systemVersion: await DeviceInfo.getSystemVersion(),
137
264
  };
138
265
  }
139
266
 
140
- private async readIosDeviceInfo(): Promise<any> {
141
-
142
- let uniqueId = await DeviceInfo.getUniqueId();
143
- let deviceId = await DeviceInfo.getDeviceId(); // model
144
- let systemName = await DeviceInfo.getSystemName();
145
- let systemVersion = await DeviceInfo.getSystemVersion()
146
- let brand = await DeviceInfo.getBrand();
147
- let model = await DeviceInfo.getModel();
148
- let manufacturer = await DeviceInfo.getManufacturer();
149
- let isEmulator = await DeviceInfo.isEmulator();
150
-
267
+ private async _readIosDeviceInfo() {
151
268
  return {
152
- deviceId: uniqueId,
153
- _deviceId: deviceId,
154
- systemName: systemName,
155
- systemVersion: systemVersion,
156
- brand: brand,
157
- model: model,
158
- manufacturer: manufacturer,
159
- isEmulator: isEmulator
269
+ deviceId: await DeviceInfo.getUniqueId(),
270
+ brand: await DeviceInfo.getBrand(),
271
+ model: await DeviceInfo.getModel(),
272
+ manufacturer: await DeviceInfo.getManufacturer(),
273
+ systemName: await DeviceInfo.getSystemName(),
274
+ systemVersion: await DeviceInfo.getSystemVersion(),
160
275
  };
161
276
  }
162
277
 
163
- private getTimeZone = (): string => {
164
- return Intl.DateTimeFormat().resolvedOptions().timeZone;
165
- };
166
-
167
- private getLanguageCode(): string {
168
- return getUserLocale();
169
- }
278
+ private async _fetchConsolidatedPurchases(purchases: Purchase[], apiKey: string) {
279
+ for (const purchase of purchases) {
280
+ const receipt = purchase.purchaseToken;
281
+ if (!receipt) continue;
170
282
 
171
- private async fetchPurchases(purchaseDetailsList: Purchase[], apiKey: string): Promise<string[]> {
172
- const productIds: string[] = [];
173
- for (const purchase of purchaseDetailsList) {
174
- if (purchase.transactionReceipt) {
175
- await this.sendEventToServer(JSON.stringify(this.serializePurchaseDetails(purchase)), 'purchase', apiKey);
176
- if (purchase.productId && !productIds.includes(purchase.productId)) {
177
- productIds.push(purchase.productId);
178
- }
179
- }
180
- }
181
- return productIds;
182
- }
283
+ const data: any = this._serializePurchaseDetails(purchase);
284
+ data.products = [];
183
285
 
184
- private async fetchPurchaseProducts(productIds: string[], apiKey: string): Promise<void> {
185
- try {
186
- const products = await InAppPurchase.getProducts(productIds);
187
- if (products.length > 0) {
188
- for (const product of products) {
189
- await this.sendEventToServer(JSON.stringify(this.serializeProductDetails(product)), 'product', apiKey);
190
- }
191
- } else {
192
- const products = await InAppPurchase.getSubscriptions(productIds);
193
- if (products.length > 0) {
194
- for (const product of products) {
195
- await this.sendEventToServer(JSON.stringify(this.serializeSubscriptionDetails(product)), 'product', apiKey);
286
+ const pid = data.productID || '';
287
+ if (pid) {
288
+ try {
289
+ const products = await fetchProducts({ skus: [pid] });
290
+ if (products && products.length) {
291
+ for (const p of products) {
292
+ data.products.push(this._serializeProductDetails(p));
293
+ }
196
294
  }
197
- } else {
198
- await this.sendEventToServer(JSON.stringify({ notFoundIDs: productIds.join(',') }), 'product', apiKey);
295
+ } catch (e) {
296
+ console.warn('Error fetching products:', e);
199
297
  }
200
298
  }
201
- } catch (e) {
202
- console.error('Error fetching products:', e);
299
+
300
+ await this._sendEventToServer(JSON.stringify(data), 'purchase_product', apiKey);
203
301
  }
204
302
  }
205
303
 
206
- private async sendEventToServer(body: string, eventType: string, apiKey: string): Promise<void> {
304
+ private async _sendEventToServer(body: string, eventType: string, apiKey: string) {
207
305
  try {
208
- const response = await axios.post(this.eventUrl, body, {
306
+ await axios.post(this.eventUrl, body, {
209
307
  headers: {
210
- 'Content-Type': 'application/json',
211
- 'x-affiliate-campaign-code': this.affiliateCampaignCode,
212
- 'x-device-id': this.deviceId,
308
+ 'x-affiliate-campaign-code': this._affiliateCampaignCode,
309
+ 'x-device-id': this._deviceId,
213
310
  'x-event-type': eventType,
214
311
  'x-product-type': Platform.OS,
215
312
  'x-source-name': Platform.OS === 'android' ? 'google_play' : 'app_store',
216
313
  'x-api-key': apiKey,
217
314
  },
218
315
  });
219
- if (response.status === 200) {
220
- console.log(`${eventType} sent successfully`);
221
- } else {
222
- console.error(`Failed to send ${eventType}. Status code:`, response.status);
223
- }
316
+ console.log(`${eventType} sent successfully`);
224
317
  } catch (e) {
225
- console.error(`Error sending ${eventType} to server:`, e);
318
+ console.log(`Error sending ${eventType}:`, e);
226
319
  }
227
320
  }
228
321
 
229
- private serializePurchaseDetails(purchase: Purchase): any {
322
+ private _serializePurchaseDetails(purchase: PurchaseCommon) {
230
323
  return {
324
+ packageName: this._packageName,
231
325
  productID: purchase.productId,
232
- purchaseID: purchase.transactionId || '',
233
- transactionDate: purchase.transactionDate || '',
234
- status: Platform.select({
235
- ios: (purchase as any).transactionStateIOS, // Removed non-existent properties
236
- android: (purchase as any).purchaseStateAndroid,
237
- }),
326
+ purchaseID: purchase.id,
327
+ transactionDate: purchase.transactionDate,
238
328
  verificationData: {
239
- localVerificationData: purchase.transactionReceipt,
329
+ localVerificationData: purchase.purchaseToken,
330
+ source: Platform.OS === 'android' ? 'google_play' : 'app_store',
240
331
  },
241
332
  };
242
333
  }
243
334
 
244
- private serializeProductDetails(product: Product): any {
335
+ private _serializeProductDetails(product: ProductCommon) {
245
336
  return {
246
- productID: product.productId,
337
+ packageName: this._packageName,
338
+ productID: product.id,
247
339
  productTitle: product.title,
248
340
  productDescription: product.description,
249
- productPrice: product.price,
250
- productRawPrice: product.price,
341
+ productPrice: product.displayPrice,
342
+ productRawPrice: product.price || '',
251
343
  productCurrencyCode: product.currency,
252
344
  };
253
345
  }
254
346
 
255
- private serializeSubscriptionDetails(subscription: Subscription): any {
256
- return {
257
- productID: subscription.productId,
258
- productTitle: subscription.title,
259
- productDescription: subscription.description,
260
- productPrice: subscription.price,
261
- productRawPrice: subscription.price,
262
- productCurrencyCode: subscription.currency,
263
- };
347
+ private async _markSDKAsInitialized() {
348
+ await AsyncStorage.setItem(this.sdkInitializedKey, 'true');
349
+ }
350
+
351
+ private async _isSDKInitialized() {
352
+ const val = await AsyncStorage.getItem(this.sdkInitializedKey);
353
+ return val === 'true';
264
354
  }
265
355
 
266
- private async markSDKAsInitialized(): Promise<boolean> {
356
+ private async _isProduction(): Promise<boolean> {
357
+ if (__DEV__) return false;
358
+
267
359
  try {
268
- await AsyncStorage.setItem(this.sdkInitializedKey, 'true');
269
- return true;
270
- } catch (e) {
271
- console.error('Failed to save SDK initialization:', e);
360
+ const installer = await DeviceInfo.getInstallerPackageName();
361
+
362
+ if (
363
+ installer === 'com.android.vending' ||
364
+ installer === 'com.amazon.venezia'
365
+ ) {
366
+ return true;
367
+ }
368
+
369
+ if (installer == null && !__DEV__) {
370
+ return true;
371
+ }
372
+
373
+ return false;
374
+ } catch (error) {
375
+ console.warn('Error determining production status:', error);
272
376
  return false;
273
377
  }
274
378
  }
275
379
 
276
- private async isSDKInitialized(): Promise<boolean> {
380
+ private async _fetchExistingPurchases(apiKey: string): Promise<void> {
277
381
  try {
278
- const value = await AsyncStorage.getItem(this.sdkInitializedKey);
279
- return value === 'true';
382
+ const purchases = await getAvailablePurchases();
383
+ if (purchases && purchases.length > 0) {
384
+ await this._fetchConsolidatedPurchases(purchases, apiKey);
385
+ }
280
386
  } catch (e) {
281
- console.error('Failed to load SDK initialization:', e);
282
- return false;
387
+ console.log('Error fetching existing purchases on app open:', e);
283
388
  }
284
389
  }
285
390
  }