@qonversion/react-native-sdk 10.0.1 → 10.1.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/android/build.gradle +1 -1
- package/android/src/main/java/com/qonversion/reactnativesdk/NoCodesModule.kt +43 -2
- package/android/src/main/java/com/qonversion/reactnativesdk/QonversionModule.kt +27 -0
- package/ios/RNNoCodes.mm +45 -4
- package/ios/RNNoCodesImpl.swift +58 -3
- package/ios/RNQonversion.mm +9 -0
- package/ios/RNQonversionImpl.swift +7 -0
- package/lib/module/NoCodesConfig.js +3 -1
- package/lib/module/NoCodesConfig.js.map +1 -1
- package/lib/module/NoCodesConfigBuilder.js +27 -1
- package/lib/module/NoCodesConfigBuilder.js.map +1 -1
- package/lib/module/dto/PurchaseDelegate.js +4 -0
- package/lib/module/dto/PurchaseDelegate.js.map +1 -0
- package/lib/module/dto/PurchaseResult.js +74 -0
- package/lib/module/dto/PurchaseResult.js.map +1 -0
- package/lib/module/dto/StoreTransaction.js +48 -0
- package/lib/module/dto/StoreTransaction.js.map +1 -0
- package/lib/module/dto/enums.js +38 -0
- package/lib/module/dto/enums.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/internal/Mapper.js +47 -1
- package/lib/module/internal/Mapper.js.map +1 -1
- package/lib/module/internal/NoCodesInternal.js +35 -1
- package/lib/module/internal/NoCodesInternal.js.map +1 -1
- package/lib/module/internal/QonversionInternal.js +25 -1
- package/lib/module/internal/QonversionInternal.js.map +1 -1
- package/lib/module/internal/specs/NativeNoCodesModule.js.map +1 -1
- package/lib/module/internal/specs/NativeQonversionModule.js.map +1 -1
- package/lib/typescript/src/NoCodesApi.d.ts +8 -0
- package/lib/typescript/src/NoCodesApi.d.ts.map +1 -1
- package/lib/typescript/src/NoCodesConfig.d.ts +4 -1
- package/lib/typescript/src/NoCodesConfig.d.ts.map +1 -1
- package/lib/typescript/src/NoCodesConfigBuilder.d.ts +19 -0
- package/lib/typescript/src/NoCodesConfigBuilder.d.ts.map +1 -1
- package/lib/typescript/src/QonversionApi.d.ts +15 -2
- package/lib/typescript/src/QonversionApi.d.ts.map +1 -1
- package/lib/typescript/src/dto/PurchaseDelegate.d.ts +19 -0
- package/lib/typescript/src/dto/PurchaseDelegate.d.ts.map +1 -0
- package/lib/typescript/src/dto/PurchaseResult.d.ts +55 -0
- package/lib/typescript/src/dto/PurchaseResult.d.ts.map +1 -0
- package/lib/typescript/src/dto/StoreTransaction.d.ts +38 -0
- package/lib/typescript/src/dto/StoreTransaction.d.ts.map +1 -0
- package/lib/typescript/src/dto/enums.d.ts +34 -0
- package/lib/typescript/src/dto/enums.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/internal/Mapper.d.ts +24 -1
- package/lib/typescript/src/internal/Mapper.d.ts.map +1 -1
- package/lib/typescript/src/internal/NoCodesInternal.d.ts +6 -0
- package/lib/typescript/src/internal/NoCodesInternal.d.ts.map +1 -1
- package/lib/typescript/src/internal/QonversionInternal.d.ts +3 -1
- package/lib/typescript/src/internal/QonversionInternal.d.ts.map +1 -1
- package/lib/typescript/src/internal/specs/NativeNoCodesModule.d.ts +9 -1
- package/lib/typescript/src/internal/specs/NativeNoCodesModule.d.ts.map +1 -1
- package/lib/typescript/src/internal/specs/NativeQonversionModule.d.ts +7 -1
- package/lib/typescript/src/internal/specs/NativeQonversionModule.d.ts.map +1 -1
- package/package.json +1 -1
- package/qonversion-react-native-sdk.podspec +1 -1
- package/src/NoCodesApi.ts +9 -0
- package/src/NoCodesConfig.ts +8 -1
- package/src/NoCodesConfigBuilder.ts +30 -1
- package/src/QonversionApi.ts +16 -2
- package/src/dto/PurchaseDelegate.ts +21 -0
- package/src/dto/PurchaseResult.ts +88 -0
- package/src/dto/StoreTransaction.ts +61 -0
- package/src/dto/enums.ts +40 -0
- package/src/index.ts +4 -0
- package/src/internal/Mapper.ts +94 -0
- package/src/internal/NoCodesInternal.ts +44 -3
- package/src/internal/QonversionInternal.ts +50 -2
- package/src/internal/specs/NativeNoCodesModule.ts +11 -1
- package/src/internal/specs/NativeQonversionModule.ts +12 -2
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Product from './Product';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Delegate responsible for custom purchase and restore handling.
|
|
5
|
+
* When this delegate is provided, it replaces the default Qonversion SDK purchase flow.
|
|
6
|
+
*/
|
|
7
|
+
export interface PurchaseDelegate {
|
|
8
|
+
/**
|
|
9
|
+
* Handle purchase for the given product.
|
|
10
|
+
* @param product Product to purchase.
|
|
11
|
+
* @returns Promise that completes successfully when purchase finishes, otherwise throws an error.
|
|
12
|
+
*/
|
|
13
|
+
purchase(product: Product): Promise<void>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Handle restore flow.
|
|
17
|
+
* @returns Promise that completes successfully when restore finishes, otherwise throws an error.
|
|
18
|
+
*/
|
|
19
|
+
restore(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import Entitlement from './Entitlement';
|
|
2
|
+
import QonversionError from './QonversionError';
|
|
3
|
+
import StoreTransaction from './StoreTransaction';
|
|
4
|
+
import { PurchaseResultStatus, PurchaseResultSource } from './enums';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents the result of a purchase operation.
|
|
8
|
+
* Contains the status of the purchase, entitlements, and store transaction details.
|
|
9
|
+
*/
|
|
10
|
+
class PurchaseResult {
|
|
11
|
+
/**
|
|
12
|
+
* The status of the purchase operation.
|
|
13
|
+
*/
|
|
14
|
+
status: PurchaseResultStatus;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The user's entitlements after the purchase.
|
|
18
|
+
* May be null if the purchase failed or is pending.
|
|
19
|
+
*/
|
|
20
|
+
entitlements: Map<string, Entitlement> | null;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The error that occurred during the purchase, if any.
|
|
24
|
+
*/
|
|
25
|
+
error: QonversionError | null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Indicates whether the entitlements were generated from a fallback source.
|
|
29
|
+
*/
|
|
30
|
+
isFallbackGenerated: boolean;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The source of the purchase result data.
|
|
34
|
+
*/
|
|
35
|
+
source: PurchaseResultSource;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The store transaction details from the native platform.
|
|
39
|
+
* Contains raw transaction information from Apple App Store or Google Play Store.
|
|
40
|
+
*/
|
|
41
|
+
storeTransaction: StoreTransaction | null;
|
|
42
|
+
|
|
43
|
+
constructor(
|
|
44
|
+
status: PurchaseResultStatus,
|
|
45
|
+
entitlements: Map<string, Entitlement> | null,
|
|
46
|
+
error: QonversionError | null,
|
|
47
|
+
isFallbackGenerated: boolean,
|
|
48
|
+
source: PurchaseResultSource,
|
|
49
|
+
storeTransaction: StoreTransaction | null,
|
|
50
|
+
) {
|
|
51
|
+
this.status = status;
|
|
52
|
+
this.entitlements = entitlements;
|
|
53
|
+
this.error = error;
|
|
54
|
+
this.isFallbackGenerated = isFallbackGenerated;
|
|
55
|
+
this.source = source;
|
|
56
|
+
this.storeTransaction = storeTransaction;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns true if the purchase was successful.
|
|
61
|
+
*/
|
|
62
|
+
get isSuccess(): boolean {
|
|
63
|
+
return this.status === PurchaseResultStatus.SUCCESS;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Returns true if the purchase was canceled by the user.
|
|
68
|
+
*/
|
|
69
|
+
get isCanceled(): boolean {
|
|
70
|
+
return this.status === PurchaseResultStatus.USER_CANCELED;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Returns true if the purchase is pending.
|
|
75
|
+
*/
|
|
76
|
+
get isPending(): boolean {
|
|
77
|
+
return this.status === PurchaseResultStatus.PENDING;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Returns true if an error occurred during the purchase.
|
|
82
|
+
*/
|
|
83
|
+
get isError(): boolean {
|
|
84
|
+
return this.status === PurchaseResultStatus.ERROR;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default PurchaseResult;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a raw store transaction from the native platform.
|
|
3
|
+
* This is the transaction information as received from Apple App Store or Google Play Store.
|
|
4
|
+
*/
|
|
5
|
+
class StoreTransaction {
|
|
6
|
+
/**
|
|
7
|
+
* The unique identifier for this transaction.
|
|
8
|
+
*/
|
|
9
|
+
transactionId?: string;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The original transaction identifier.
|
|
13
|
+
* For subscriptions, this identifies the first transaction in the subscription chain.
|
|
14
|
+
*/
|
|
15
|
+
originalTransactionId?: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The date and time when the transaction occurred.
|
|
19
|
+
*/
|
|
20
|
+
transactionDate?: Date;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The store product identifier associated with this transaction.
|
|
24
|
+
*/
|
|
25
|
+
productId?: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The quantity of items purchased.
|
|
29
|
+
*/
|
|
30
|
+
quantity: number;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* iOS only. The identifier of the promotional offer applied to this purchase.
|
|
34
|
+
*/
|
|
35
|
+
promoOfferId?: string;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Android only. The purchase token from Google Play.
|
|
39
|
+
*/
|
|
40
|
+
purchaseToken?: string;
|
|
41
|
+
|
|
42
|
+
constructor(
|
|
43
|
+
transactionId: string | undefined,
|
|
44
|
+
originalTransactionId: string | undefined,
|
|
45
|
+
transactionTimestamp: number | undefined,
|
|
46
|
+
productId: string | undefined,
|
|
47
|
+
quantity: number | undefined,
|
|
48
|
+
promoOfferId: string | undefined,
|
|
49
|
+
purchaseToken: string | undefined,
|
|
50
|
+
) {
|
|
51
|
+
this.transactionId = transactionId;
|
|
52
|
+
this.originalTransactionId = originalTransactionId;
|
|
53
|
+
this.transactionDate = transactionTimestamp ? new Date(transactionTimestamp) : undefined;
|
|
54
|
+
this.productId = productId;
|
|
55
|
+
this.quantity = quantity ?? 1;
|
|
56
|
+
this.promoOfferId = promoOfferId;
|
|
57
|
+
this.purchaseToken = purchaseToken;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default StoreTransaction;
|
package/src/dto/enums.ts
CHANGED
|
@@ -388,3 +388,43 @@ export enum NoCodesErrorCode {
|
|
|
388
388
|
SCREEN_LOADING_FAILED = "ScreenLoadingFailed", // iOS
|
|
389
389
|
SDK_INITIALIZATION_ERROR = "SDKInitializationError" // iOS
|
|
390
390
|
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Status of the purchase result.
|
|
394
|
+
*/
|
|
395
|
+
export enum PurchaseResultStatus {
|
|
396
|
+
/**
|
|
397
|
+
* The purchase was successful.
|
|
398
|
+
*/
|
|
399
|
+
SUCCESS = "Success",
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* The purchase was canceled by the user.
|
|
403
|
+
*/
|
|
404
|
+
USER_CANCELED = "UserCanceled",
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* The purchase is pending (e.g., waiting for parental approval).
|
|
408
|
+
*/
|
|
409
|
+
PENDING = "Pending",
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* An error occurred during the purchase.
|
|
413
|
+
*/
|
|
414
|
+
ERROR = "Error",
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Source of the purchase result data.
|
|
419
|
+
*/
|
|
420
|
+
export enum PurchaseResultSource {
|
|
421
|
+
/**
|
|
422
|
+
* The result was obtained from the Qonversion API.
|
|
423
|
+
*/
|
|
424
|
+
API = "Api",
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* The result was obtained from the local store.
|
|
428
|
+
*/
|
|
429
|
+
LOCAL = "Local",
|
|
430
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -31,6 +31,8 @@ export { default as SKProductDiscount } from './dto/storeProducts/SKProductDisco
|
|
|
31
31
|
export { default as SKSubscriptionPeriod } from './dto/storeProducts/SKSubscriptionPeriod';
|
|
32
32
|
export { default as PurchaseOptionsBuilder } from './dto/PurchaseOptionsBuilder';
|
|
33
33
|
export { default as PurchaseOptions } from './dto/PurchaseOptionsBuilder';
|
|
34
|
+
export { default as PurchaseResult } from './dto/PurchaseResult';
|
|
35
|
+
export { default as StoreTransaction } from './dto/StoreTransaction';
|
|
34
36
|
|
|
35
37
|
// NoCode exports
|
|
36
38
|
export { default as ScreenPresentationConfig } from './dto/ScreenPresentationConfig';
|
|
@@ -39,4 +41,6 @@ export type { default as NoCodesApi } from './NoCodesApi';
|
|
|
39
41
|
export { default as NoCodesConfig } from './NoCodesConfig';
|
|
40
42
|
export { default as NoCodesConfigBuilder } from './NoCodesConfigBuilder';
|
|
41
43
|
export type { NoCodesListener } from './dto/NoCodesListener';
|
|
44
|
+
export type { PurchaseDelegate } from './dto/PurchaseDelegate';
|
|
42
45
|
export { default as NoCodesAction } from './dto/NoCodesAction';
|
|
46
|
+
export { default as NoCodesError } from './dto/NoCodesError';
|
package/src/internal/Mapper.ts
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
PricingPhaseRecurrenceMode,
|
|
9
9
|
PricingPhaseType,
|
|
10
10
|
ProductType,
|
|
11
|
+
PurchaseResultSource,
|
|
12
|
+
PurchaseResultStatus,
|
|
11
13
|
QonversionErrorCode,
|
|
12
14
|
RemoteConfigurationAssignmentType,
|
|
13
15
|
RemoteConfigurationSourceType,
|
|
@@ -52,6 +54,8 @@ import SKPaymentDiscount from '../dto/storeProducts/SKPaymentDiscount';
|
|
|
52
54
|
import NoCodesAction from '../dto/NoCodesAction';
|
|
53
55
|
import QonversionError from '../dto/QonversionError';
|
|
54
56
|
import NoCodesError from '../dto/NoCodesError';
|
|
57
|
+
import PurchaseResult from '../dto/PurchaseResult';
|
|
58
|
+
import StoreTransaction from '../dto/StoreTransaction';
|
|
55
59
|
|
|
56
60
|
export type QProduct = {
|
|
57
61
|
id: string;
|
|
@@ -298,6 +302,25 @@ export type QNoCodesError = QQonversionError & {
|
|
|
298
302
|
|
|
299
303
|
export type QNoCodeScreenInfo = { screenId: string };
|
|
300
304
|
|
|
305
|
+
export type QStoreTransaction = {
|
|
306
|
+
transactionId?: string | null;
|
|
307
|
+
originalTransactionId?: string | null;
|
|
308
|
+
transactionTimestamp?: number | null;
|
|
309
|
+
productId?: string | null;
|
|
310
|
+
quantity?: number | null;
|
|
311
|
+
promoOfferId?: string | null;
|
|
312
|
+
purchaseToken?: string | null;
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
export type QPurchaseResult = {
|
|
316
|
+
status: string;
|
|
317
|
+
entitlements: Record<string, QEntitlement> | null;
|
|
318
|
+
error: QQonversionError | null | undefined;
|
|
319
|
+
isFallbackGenerated: boolean;
|
|
320
|
+
source: string;
|
|
321
|
+
storeTransaction: QStoreTransaction | null | undefined;
|
|
322
|
+
};
|
|
323
|
+
|
|
301
324
|
const priceMicrosRatio = 1000000;
|
|
302
325
|
|
|
303
326
|
class Mapper {
|
|
@@ -1156,6 +1179,77 @@ class Mapper {
|
|
|
1156
1179
|
|
|
1157
1180
|
return QonversionErrorCode.UNKNOWN;
|
|
1158
1181
|
}
|
|
1182
|
+
|
|
1183
|
+
// region PurchaseResult Mappers
|
|
1184
|
+
|
|
1185
|
+
static convertPurchaseResult(
|
|
1186
|
+
purchaseResult: QPurchaseResult | null | undefined
|
|
1187
|
+
): PurchaseResult | null {
|
|
1188
|
+
if (!purchaseResult) {
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
const status = this.convertPurchaseResultStatus(purchaseResult.status);
|
|
1193
|
+
const entitlements = purchaseResult.entitlements
|
|
1194
|
+
? this.convertEntitlements(purchaseResult.entitlements)
|
|
1195
|
+
: null;
|
|
1196
|
+
const error = purchaseResult.error ? this.convertQonversionError(purchaseResult.error) : undefined;
|
|
1197
|
+
const source = this.convertPurchaseResultSource(purchaseResult.source);
|
|
1198
|
+
const storeTransaction = this.convertStoreTransaction(purchaseResult.storeTransaction);
|
|
1199
|
+
|
|
1200
|
+
return new PurchaseResult(
|
|
1201
|
+
status,
|
|
1202
|
+
entitlements,
|
|
1203
|
+
error ?? null,
|
|
1204
|
+
purchaseResult.isFallbackGenerated ?? false,
|
|
1205
|
+
source,
|
|
1206
|
+
storeTransaction
|
|
1207
|
+
);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
static convertPurchaseResultStatus(status: string | null | undefined): PurchaseResultStatus {
|
|
1211
|
+
switch (status) {
|
|
1212
|
+
case "Success":
|
|
1213
|
+
return PurchaseResultStatus.SUCCESS;
|
|
1214
|
+
case "UserCanceled":
|
|
1215
|
+
return PurchaseResultStatus.USER_CANCELED;
|
|
1216
|
+
case "Pending":
|
|
1217
|
+
return PurchaseResultStatus.PENDING;
|
|
1218
|
+
case "Error":
|
|
1219
|
+
default:
|
|
1220
|
+
return PurchaseResultStatus.ERROR;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
static convertPurchaseResultSource(source: string | null | undefined): PurchaseResultSource {
|
|
1225
|
+
switch (source) {
|
|
1226
|
+
case "Local":
|
|
1227
|
+
return PurchaseResultSource.LOCAL;
|
|
1228
|
+
case "Api":
|
|
1229
|
+
default:
|
|
1230
|
+
return PurchaseResultSource.API;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
static convertStoreTransaction(
|
|
1235
|
+
storeTransaction: QStoreTransaction | null | undefined
|
|
1236
|
+
): StoreTransaction | null {
|
|
1237
|
+
if (!storeTransaction) {
|
|
1238
|
+
return null;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
return new StoreTransaction(
|
|
1242
|
+
storeTransaction.transactionId ?? undefined,
|
|
1243
|
+
storeTransaction.originalTransactionId ?? undefined,
|
|
1244
|
+
storeTransaction.transactionTimestamp ?? undefined,
|
|
1245
|
+
storeTransaction.productId ?? undefined,
|
|
1246
|
+
storeTransaction.quantity ?? undefined,
|
|
1247
|
+
storeTransaction.promoOfferId ?? undefined,
|
|
1248
|
+
storeTransaction.purchaseToken ?? undefined
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// endregion
|
|
1159
1253
|
}
|
|
1160
1254
|
|
|
1161
1255
|
export default Mapper;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type NoCodesApi from "../NoCodesApi";
|
|
2
2
|
import NoCodesConfig from "../NoCodesConfig";
|
|
3
|
-
import Mapper, { type QNoCodeAction, type QNoCodesError, type QNoCodeScreenInfo } from "./Mapper";
|
|
3
|
+
import Mapper, { type QNoCodeAction, type QNoCodesError, type QNoCodeScreenInfo, type QProduct } from "./Mapper";
|
|
4
4
|
import type {NoCodesListener} from '../dto/NoCodesListener';
|
|
5
|
+
import type {PurchaseDelegate} from '../dto/PurchaseDelegate';
|
|
5
6
|
import ScreenPresentationConfig from '../dto/ScreenPresentationConfig';
|
|
6
7
|
import NoCodesError from '../dto/NoCodesError';
|
|
7
8
|
import {NoCodesErrorCode} from '../dto/enums';
|
|
8
9
|
import RNNoCodes, {type NoCodeEvent} from './specs/NativeNoCodesModule';
|
|
9
10
|
import {sdkSource, sdkVersion} from './QonversionInternal';
|
|
11
|
+
import Product from '../dto/Product';
|
|
10
12
|
|
|
11
13
|
const EVENT_SCREEN_SHOWN = "nocodes_screen_shown";
|
|
12
14
|
const EVENT_FINISHED = "nocodes_finished";
|
|
@@ -17,13 +19,18 @@ const EVENT_SCREEN_FAILED_TO_LOAD = "nocodes_screen_failed_to_load";
|
|
|
17
19
|
|
|
18
20
|
export default class NoCodesInternal implements NoCodesApi {
|
|
19
21
|
private noCodesListener: NoCodesListener | null = null;
|
|
22
|
+
private purchaseDelegate: PurchaseDelegate | null = null;
|
|
20
23
|
|
|
21
24
|
constructor(config: NoCodesConfig) {
|
|
22
|
-
RNNoCodes.initialize(config.projectKey, sdkSource, sdkVersion, config.proxyUrl);
|
|
25
|
+
RNNoCodes.initialize(config.projectKey, sdkSource, sdkVersion, config.proxyUrl, config.locale);
|
|
23
26
|
|
|
24
27
|
if (config.noCodesListener) {
|
|
25
28
|
this.setNoCodesListener(config.noCodesListener);
|
|
26
29
|
}
|
|
30
|
+
|
|
31
|
+
if (config.purchaseDelegate) {
|
|
32
|
+
this.setPurchaseDelegate(config.purchaseDelegate);
|
|
33
|
+
}
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
async setScreenPresentationConfig(config: ScreenPresentationConfig, contextKey?: string) {
|
|
@@ -44,7 +51,7 @@ export default class NoCodesInternal implements NoCodesApi {
|
|
|
44
51
|
case EVENT_SCREEN_SHOWN:
|
|
45
52
|
const screenId = (event.payload as QNoCodeScreenInfo)["screenId"] ?? "";
|
|
46
53
|
this.noCodesListener?.onScreenShown(screenId);
|
|
47
|
-
break;
|
|
54
|
+
break;
|
|
48
55
|
case EVENT_ACTION_STARTED:
|
|
49
56
|
const actionStarted = Mapper.convertAction(event.payload as QNoCodeAction);
|
|
50
57
|
this.noCodesListener?.onActionStartedExecuting(actionStarted);
|
|
@@ -75,10 +82,44 @@ export default class NoCodesInternal implements NoCodesApi {
|
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
|
|
85
|
+
private customPurchaseHandler = async (productData: Object) => {
|
|
86
|
+
if (!this.purchaseDelegate) {
|
|
87
|
+
throw new Error('PurchaseDelegate is not set but custom purchase handling initiated');
|
|
88
|
+
}
|
|
89
|
+
const product: Product = Mapper.convertProduct(productData as QProduct);
|
|
90
|
+
this.purchaseDelegate.purchase(product).then(() => {
|
|
91
|
+
RNNoCodes.delegatedPurchaseCompleted();
|
|
92
|
+
}).catch((error: Error) => {
|
|
93
|
+
RNNoCodes.delegatedPurchaseFailed(error.message);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private customRestoreHandler = async () => {
|
|
98
|
+
if (!this.purchaseDelegate) {
|
|
99
|
+
throw new Error('PurchaseDelegate is not set but custom restore handling initiated');
|
|
100
|
+
}
|
|
101
|
+
this.purchaseDelegate.restore().then(() => {
|
|
102
|
+
RNNoCodes.delegatedRestoreCompleted();
|
|
103
|
+
}).catch((error: Error) => {
|
|
104
|
+
RNNoCodes.delegatedRestoreFailed(error.message);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
78
108
|
setNoCodesListener(listener: NoCodesListener) {
|
|
79
109
|
if (this.noCodesListener == null) {
|
|
80
110
|
RNNoCodes.onNoCodeEvent(this.noCodeEventHandler);
|
|
81
111
|
}
|
|
82
112
|
this.noCodesListener = listener;
|
|
83
113
|
}
|
|
114
|
+
|
|
115
|
+
setPurchaseDelegate(delegate: PurchaseDelegate) {
|
|
116
|
+
this.purchaseDelegate = delegate;
|
|
117
|
+
RNNoCodes.onNoCodePurchase(this.customPurchaseHandler);
|
|
118
|
+
RNNoCodes.onNoCodeRestore(this.customRestoreHandler);
|
|
119
|
+
RNNoCodes.setPurchaseDelegate();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
setLocale(locale: string | null) {
|
|
123
|
+
RNNoCodes.setLocale(locale);
|
|
124
|
+
}
|
|
84
125
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {AttributionProvider, QonversionErrorCode, UserPropertyKey} from "../dto/enums";
|
|
2
2
|
import IntroEligibility from "../dto/IntroEligibility";
|
|
3
3
|
import Mapper from "./Mapper";
|
|
4
|
-
import type {QEntitlement, QEligibilityInfo, QProduct} from "./Mapper";
|
|
4
|
+
import type {QEntitlement, QEligibilityInfo, QProduct, QPurchaseResult} from "./Mapper";
|
|
5
5
|
import Offerings from "../dto/Offerings";
|
|
6
6
|
import Entitlement from "../dto/Entitlement";
|
|
7
7
|
import Product from "../dto/Product";
|
|
8
|
+
import PurchaseResult from "../dto/PurchaseResult";
|
|
8
9
|
import {isAndroid, isIos} from "./utils";
|
|
9
10
|
import type {EntitlementsUpdateListener} from '../dto/EntitlementsUpdateListener';
|
|
10
11
|
import type {PromoPurchasesListener} from '../dto/PromoPurchasesListener';
|
|
@@ -23,7 +24,7 @@ import PromotionalOffer from '../dto/PromotionalOffer';
|
|
|
23
24
|
import RNQonversion from './specs/NativeQonversionModule';
|
|
24
25
|
import type { QPromoOfferDetails } from './specs/NativeQonversionModule';
|
|
25
26
|
|
|
26
|
-
export const sdkVersion = "10.0
|
|
27
|
+
export const sdkVersion = "10.1.0";
|
|
27
28
|
export const sdkSource = "rn";
|
|
28
29
|
|
|
29
30
|
export default class QonversionInternal implements QonversionApi {
|
|
@@ -73,6 +74,53 @@ export default class QonversionInternal implements QonversionApi {
|
|
|
73
74
|
return mappedPromoOffer;
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
async purchaseWithResult(product: Product, options: PurchaseOptions | undefined): Promise<PurchaseResult> {
|
|
78
|
+
if (!options) {
|
|
79
|
+
options = new PurchaseOptionsBuilder().build();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const promoOffer: QPromoOfferDetails = {
|
|
83
|
+
productDiscountId: options.promotionalOffer?.productDiscount.identifier,
|
|
84
|
+
keyIdentifier: options.promotionalOffer?.paymentDiscount.keyIdentifier,
|
|
85
|
+
nonce: options.promotionalOffer?.paymentDiscount.nonce,
|
|
86
|
+
signature: options.promotionalOffer?.paymentDiscount.signature,
|
|
87
|
+
timestamp: options.promotionalOffer?.paymentDiscount.timestamp
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
let purchaseResultPromise: Promise<QPurchaseResult | null | undefined>;
|
|
91
|
+
if (isIos()) {
|
|
92
|
+
purchaseResultPromise = RNQonversion.purchaseWithResult(
|
|
93
|
+
product.qonversionId,
|
|
94
|
+
options.quantity,
|
|
95
|
+
options.contextKeys,
|
|
96
|
+
promoOffer,
|
|
97
|
+
undefined,
|
|
98
|
+
false,
|
|
99
|
+
undefined,
|
|
100
|
+
undefined,
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
purchaseResultPromise = RNQonversion.purchaseWithResult(
|
|
104
|
+
product.qonversionId,
|
|
105
|
+
1,
|
|
106
|
+
options.contextKeys,
|
|
107
|
+
undefined,
|
|
108
|
+
options.offerId,
|
|
109
|
+
options.applyOffer,
|
|
110
|
+
options.oldProduct?.qonversionId,
|
|
111
|
+
options.updatePolicy,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const purchaseResult = await purchaseResultPromise;
|
|
115
|
+
const mappedResult = Mapper.convertPurchaseResult(purchaseResult);
|
|
116
|
+
|
|
117
|
+
if (!mappedResult) {
|
|
118
|
+
throw new Error("Failed to parse PurchaseResult");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return mappedResult;
|
|
122
|
+
}
|
|
123
|
+
|
|
76
124
|
async purchaseProduct(product: Product, options: PurchaseOptions | undefined): Promise<Map<string, Entitlement>> {
|
|
77
125
|
try {
|
|
78
126
|
if (!options) {
|
|
@@ -9,12 +9,22 @@ export type NoCodeEvent = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export interface Spec extends TurboModule {
|
|
12
|
-
initialize(projectKey: string, source: string, version: string, proxyUrl?: string): void;
|
|
12
|
+
initialize(projectKey: string, source: string, version: string, proxyUrl?: string, locale?: string): void;
|
|
13
13
|
setScreenPresentationConfig(configData: Object, contextKey?: string): Promise<boolean>;
|
|
14
14
|
showScreen(contextKey: string): Promise<boolean>;
|
|
15
15
|
close(): Promise<boolean>;
|
|
16
|
+
setPurchaseDelegate(): void;
|
|
17
|
+
setLocale(locale: string | null): void;
|
|
18
|
+
|
|
19
|
+
// Methods to notify native code about purchase/restore results
|
|
20
|
+
delegatedPurchaseCompleted(): void;
|
|
21
|
+
delegatedPurchaseFailed(errorMessage: string): void;
|
|
22
|
+
delegatedRestoreCompleted(): void;
|
|
23
|
+
delegatedRestoreFailed(errorMessage: string): void;
|
|
16
24
|
|
|
17
25
|
readonly onNoCodeEvent: EventEmitter<NoCodeEvent>;
|
|
26
|
+
readonly onNoCodePurchase: EventEmitter<Object>; // QProduct
|
|
27
|
+
readonly onNoCodeRestore: EventEmitter<void>;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
export default TurboModuleRegistry.getEnforcing<Spec>('RNNoCodes');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {TurboModule} from 'react-native';
|
|
2
2
|
import {TurboModuleRegistry} from 'react-native';
|
|
3
|
-
import type { QPromotionalOffer, QOfferings, QUser, QUserProperties, QRemoteConfig, QRemoteConfigList } from '../Mapper';
|
|
3
|
+
import type { QPromotionalOffer, QOfferings, QUser, QUserProperties, QRemoteConfig, QRemoteConfigList, QPurchaseResult } from '../Mapper';
|
|
4
4
|
import type { EventEmitter } from 'react-native/Libraries/Types/CodegenTypes';
|
|
5
5
|
|
|
6
6
|
export type QPromoOfferDetails = {
|
|
@@ -34,7 +34,17 @@ export interface Spec extends TurboModule {
|
|
|
34
34
|
applyOffer: boolean, // Android only
|
|
35
35
|
oldProductId: string | null | undefined, // Android only
|
|
36
36
|
updatePolicyKey: string | null | undefined, // Android only
|
|
37
|
-
): Promise<Object | null | undefined>; // Record<string, QEntitlement
|
|
37
|
+
): Promise<Object | null | undefined>; // Record<string, QEntitlement>
|
|
38
|
+
purchaseWithResult(
|
|
39
|
+
productId: string,
|
|
40
|
+
quantity: number, // iOS only
|
|
41
|
+
contextKeys: string[] | null | undefined,
|
|
42
|
+
promoOffer: QPromoOfferDetails | undefined, // iOS only
|
|
43
|
+
offerId: string | null | undefined, // Android only
|
|
44
|
+
applyOffer: boolean, // Android only
|
|
45
|
+
oldProductId: string | null | undefined, // Android only
|
|
46
|
+
updatePolicyKey: string | null | undefined, // Android only
|
|
47
|
+
): Promise<QPurchaseResult | null | undefined>;
|
|
38
48
|
updatePurchase(
|
|
39
49
|
productId: string,
|
|
40
50
|
offerId: string | null | undefined,
|