mobilyflow-react-native-sdk 0.0.1
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/LICENSE +20 -0
- package/MobilyflowReactNativeSdk.podspec +52 -0
- package/README.md +33 -0
- package/android/build.gradle +114 -0
- package/android/generated/java/com/mobilyflowreactnativesdk/NativeMobilyflowReactNativeSdkSpec.java +89 -0
- package/android/generated/jni/CMakeLists.txt +36 -0
- package/android/generated/jni/RNMobilyflowReactNativeSdkSpec-generated.cpp +104 -0
- package/android/generated/jni/RNMobilyflowReactNativeSdkSpec.h +31 -0
- package/android/generated/jni/react/renderer/components/RNMobilyflowReactNativeSdkSpec/RNMobilyflowReactNativeSdkSpecJSI-generated.cpp +124 -0
- package/android/generated/jni/react/renderer/components/RNMobilyflowReactNativeSdkSpec/RNMobilyflowReactNativeSdkSpecJSI.h +287 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/mobilyflowreactnativesdk/MobilyflowReactNativeSdkModule.kt +183 -0
- package/android/src/main/java/com/mobilyflowreactnativesdk/MobilyflowReactNativeSdkPackage.kt +32 -0
- package/android/src/main/java/com/mobilyflowreactnativesdk/ParserUtils.kt +149 -0
- package/ios/MobilyflowReactNativeSdk.h +7 -0
- package/ios/MobilyflowReactNativeSdk.mm +204 -0
- package/ios/Utils/ParserMobilyPurchaseSDKOptions.h +21 -0
- package/ios/Utils/ParserMobilyPurchaseSDKOptions.mm +25 -0
- package/ios/Utils/Utils.h +18 -0
- package/ios/Utils/Utils.m +22 -0
- package/ios/generated/RNMobilyflowReactNativeSdkSpec/RNMobilyflowReactNativeSdkSpec-generated.mm +134 -0
- package/ios/generated/RNMobilyflowReactNativeSdkSpec/RNMobilyflowReactNativeSdkSpec.h +161 -0
- package/ios/generated/RNMobilyflowReactNativeSdkSpecJSI-generated.cpp +124 -0
- package/ios/generated/RNMobilyflowReactNativeSdkSpecJSI.h +287 -0
- package/package.json +183 -0
- package/react-native.config.js +12 -0
- package/src/NativeMobilyflowReactNativeSdk.ts +46 -0
- package/src/entities/mobily-customer-entitlement.ts +37 -0
- package/src/entities/mobily-one-time-product.ts +11 -0
- package/src/entities/mobily-product.ts +34 -0
- package/src/entities/mobily-subscription-group.ts +20 -0
- package/src/entities/mobily-subscription-offer.ts +16 -0
- package/src/entities/mobily-subscription-product.ts +14 -0
- package/src/enums/mobily-environment.ts +5 -0
- package/src/enums/period-unit.ts +5 -0
- package/src/enums/platform.ts +4 -0
- package/src/enums/product-status.ts +5 -0
- package/src/enums/product-type.ts +4 -0
- package/src/enums/webhook-status.ts +5 -0
- package/src/errors/mobily-error.ts +18 -0
- package/src/errors/mobily-purchase-error.ts +30 -0
- package/src/errors/mobily-transfer-ownership-error.ts +20 -0
- package/src/index.tsx +153 -0
- package/src/utils/object-transformer.ts +60 -0
@@ -0,0 +1,287 @@
|
|
1
|
+
/**
|
2
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
3
|
+
*
|
4
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
5
|
+
* once the code is regenerated.
|
6
|
+
*
|
7
|
+
* @generated by codegen project: GenerateModuleH.js
|
8
|
+
*/
|
9
|
+
|
10
|
+
#pragma once
|
11
|
+
|
12
|
+
#include <ReactCommon/TurboModule.h>
|
13
|
+
#include <react/bridging/Bridging.h>
|
14
|
+
|
15
|
+
namespace facebook::react {
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
#pragma mark - NativeMobilyflowReactNativeSdkMobilyPurchaseSDKOptions
|
20
|
+
|
21
|
+
template <typename P0, typename P1, typename P2>
|
22
|
+
struct NativeMobilyflowReactNativeSdkMobilyPurchaseSDKOptions {
|
23
|
+
P0 languages;
|
24
|
+
P1 debug;
|
25
|
+
P2 apiURL;
|
26
|
+
bool operator==(const NativeMobilyflowReactNativeSdkMobilyPurchaseSDKOptions &other) const {
|
27
|
+
return languages == other.languages && debug == other.debug && apiURL == other.apiURL;
|
28
|
+
}
|
29
|
+
};
|
30
|
+
|
31
|
+
template <typename T>
|
32
|
+
struct NativeMobilyflowReactNativeSdkMobilyPurchaseSDKOptionsBridging {
|
33
|
+
static T types;
|
34
|
+
|
35
|
+
static T fromJs(
|
36
|
+
jsi::Runtime &rt,
|
37
|
+
const jsi::Object &value,
|
38
|
+
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
39
|
+
T result{
|
40
|
+
bridging::fromJs<decltype(types.languages)>(rt, value.getProperty(rt, "languages"), jsInvoker),
|
41
|
+
bridging::fromJs<decltype(types.debug)>(rt, value.getProperty(rt, "debug"), jsInvoker),
|
42
|
+
bridging::fromJs<decltype(types.apiURL)>(rt, value.getProperty(rt, "apiURL"), jsInvoker)};
|
43
|
+
return result;
|
44
|
+
}
|
45
|
+
|
46
|
+
#ifdef DEBUG
|
47
|
+
static jsi::Array languagesToJs(jsi::Runtime &rt, decltype(types.languages) value) {
|
48
|
+
return bridging::toJs(rt, value);
|
49
|
+
}
|
50
|
+
|
51
|
+
static bool debugToJs(jsi::Runtime &rt, decltype(types.debug) value) {
|
52
|
+
return bridging::toJs(rt, value);
|
53
|
+
}
|
54
|
+
|
55
|
+
static jsi::String apiURLToJs(jsi::Runtime &rt, decltype(types.apiURL) value) {
|
56
|
+
return bridging::toJs(rt, value);
|
57
|
+
}
|
58
|
+
#endif
|
59
|
+
|
60
|
+
static jsi::Object toJs(
|
61
|
+
jsi::Runtime &rt,
|
62
|
+
const T &value,
|
63
|
+
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
64
|
+
auto result = facebook::jsi::Object(rt);
|
65
|
+
if (value.languages) {
|
66
|
+
result.setProperty(rt, "languages", bridging::toJs(rt, value.languages.value(), jsInvoker));
|
67
|
+
}
|
68
|
+
if (value.debug) {
|
69
|
+
result.setProperty(rt, "debug", bridging::toJs(rt, value.debug.value(), jsInvoker));
|
70
|
+
}
|
71
|
+
if (value.apiURL) {
|
72
|
+
result.setProperty(rt, "apiURL", bridging::toJs(rt, value.apiURL.value(), jsInvoker));
|
73
|
+
}
|
74
|
+
return result;
|
75
|
+
}
|
76
|
+
};
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
#pragma mark - NativeMobilyflowReactNativeSdkPurchaseOptions
|
81
|
+
|
82
|
+
template <typename P0, typename P1>
|
83
|
+
struct NativeMobilyflowReactNativeSdkPurchaseOptions {
|
84
|
+
P0 offerId;
|
85
|
+
P1 quantity;
|
86
|
+
bool operator==(const NativeMobilyflowReactNativeSdkPurchaseOptions &other) const {
|
87
|
+
return offerId == other.offerId && quantity == other.quantity;
|
88
|
+
}
|
89
|
+
};
|
90
|
+
|
91
|
+
template <typename T>
|
92
|
+
struct NativeMobilyflowReactNativeSdkPurchaseOptionsBridging {
|
93
|
+
static T types;
|
94
|
+
|
95
|
+
static T fromJs(
|
96
|
+
jsi::Runtime &rt,
|
97
|
+
const jsi::Object &value,
|
98
|
+
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
99
|
+
T result{
|
100
|
+
bridging::fromJs<decltype(types.offerId)>(rt, value.getProperty(rt, "offerId"), jsInvoker),
|
101
|
+
bridging::fromJs<decltype(types.quantity)>(rt, value.getProperty(rt, "quantity"), jsInvoker)};
|
102
|
+
return result;
|
103
|
+
}
|
104
|
+
|
105
|
+
#ifdef DEBUG
|
106
|
+
static jsi::String offerIdToJs(jsi::Runtime &rt, decltype(types.offerId) value) {
|
107
|
+
return bridging::toJs(rt, value);
|
108
|
+
}
|
109
|
+
|
110
|
+
static double quantityToJs(jsi::Runtime &rt, decltype(types.quantity) value) {
|
111
|
+
return bridging::toJs(rt, value);
|
112
|
+
}
|
113
|
+
#endif
|
114
|
+
|
115
|
+
static jsi::Object toJs(
|
116
|
+
jsi::Runtime &rt,
|
117
|
+
const T &value,
|
118
|
+
const std::shared_ptr<CallInvoker> &jsInvoker) {
|
119
|
+
auto result = facebook::jsi::Object(rt);
|
120
|
+
result.setProperty(rt, "offerId", bridging::toJs(rt, value.offerId, jsInvoker));
|
121
|
+
result.setProperty(rt, "quantity", bridging::toJs(rt, value.quantity, jsInvoker));
|
122
|
+
return result;
|
123
|
+
}
|
124
|
+
};
|
125
|
+
|
126
|
+
class JSI_EXPORT NativeMobilyflowReactNativeSdkCxxSpecJSI : public TurboModule {
|
127
|
+
protected:
|
128
|
+
NativeMobilyflowReactNativeSdkCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
|
129
|
+
|
130
|
+
public:
|
131
|
+
virtual jsi::String instantiate(jsi::Runtime &rt, jsi::String appId, jsi::String apiKey, double environment, std::optional<jsi::Object> options) = 0;
|
132
|
+
virtual void close(jsi::Runtime &rt, jsi::String uuid) = 0;
|
133
|
+
virtual jsi::Value login(jsi::Runtime &rt, jsi::String uuid, jsi::String externalId) = 0;
|
134
|
+
virtual jsi::Value getProducts(jsi::Runtime &rt, jsi::String uuid, std::optional<jsi::Array> identifiers) = 0;
|
135
|
+
virtual jsi::Value getSubscriptionGroups(jsi::Runtime &rt, jsi::String uuid, std::optional<jsi::Array> identifiers) = 0;
|
136
|
+
virtual jsi::Value getEntitlementForSubscription(jsi::Runtime &rt, jsi::String uuid, jsi::String subscriptionGroupId) = 0;
|
137
|
+
virtual jsi::Value getEntitlement(jsi::Runtime &rt, jsi::String uuid, jsi::String productId) = 0;
|
138
|
+
virtual jsi::Value getEntitlements(jsi::Runtime &rt, jsi::String uuid, jsi::Array productIds) = 0;
|
139
|
+
virtual jsi::Value requestTransferOwnership(jsi::Runtime &rt, jsi::String uuid) = 0;
|
140
|
+
virtual jsi::Value openManageSubscription(jsi::Runtime &rt, jsi::String uuid) = 0;
|
141
|
+
virtual jsi::Value purchaseProduct(jsi::Runtime &rt, jsi::String uuid, jsi::String productId, std::optional<jsi::Object> options) = 0;
|
142
|
+
virtual void sendDiagnotic(jsi::Runtime &rt, jsi::String uuid) = 0;
|
143
|
+
virtual jsi::Value getStoreCountry(jsi::Runtime &rt, jsi::String uuid) = 0;
|
144
|
+
|
145
|
+
};
|
146
|
+
|
147
|
+
template <typename T>
|
148
|
+
class JSI_EXPORT NativeMobilyflowReactNativeSdkCxxSpec : public TurboModule {
|
149
|
+
public:
|
150
|
+
jsi::Value create(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
|
151
|
+
return delegate_.create(rt, propName);
|
152
|
+
}
|
153
|
+
|
154
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override {
|
155
|
+
return delegate_.getPropertyNames(runtime);
|
156
|
+
}
|
157
|
+
|
158
|
+
static constexpr std::string_view kModuleName = "MobilyflowReactNativeSdk";
|
159
|
+
|
160
|
+
protected:
|
161
|
+
NativeMobilyflowReactNativeSdkCxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
|
162
|
+
: TurboModule(std::string{NativeMobilyflowReactNativeSdkCxxSpec::kModuleName}, jsInvoker),
|
163
|
+
delegate_(reinterpret_cast<T*>(this), jsInvoker) {}
|
164
|
+
|
165
|
+
|
166
|
+
private:
|
167
|
+
class Delegate : public NativeMobilyflowReactNativeSdkCxxSpecJSI {
|
168
|
+
public:
|
169
|
+
Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
|
170
|
+
NativeMobilyflowReactNativeSdkCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {
|
171
|
+
|
172
|
+
}
|
173
|
+
|
174
|
+
jsi::String instantiate(jsi::Runtime &rt, jsi::String appId, jsi::String apiKey, double environment, std::optional<jsi::Object> options) override {
|
175
|
+
static_assert(
|
176
|
+
bridging::getParameterCount(&T::instantiate) == 5,
|
177
|
+
"Expected instantiate(...) to have 5 parameters");
|
178
|
+
|
179
|
+
return bridging::callFromJs<jsi::String>(
|
180
|
+
rt, &T::instantiate, jsInvoker_, instance_, std::move(appId), std::move(apiKey), std::move(environment), std::move(options));
|
181
|
+
}
|
182
|
+
void close(jsi::Runtime &rt, jsi::String uuid) override {
|
183
|
+
static_assert(
|
184
|
+
bridging::getParameterCount(&T::close) == 2,
|
185
|
+
"Expected close(...) to have 2 parameters");
|
186
|
+
|
187
|
+
return bridging::callFromJs<void>(
|
188
|
+
rt, &T::close, jsInvoker_, instance_, std::move(uuid));
|
189
|
+
}
|
190
|
+
jsi::Value login(jsi::Runtime &rt, jsi::String uuid, jsi::String externalId) override {
|
191
|
+
static_assert(
|
192
|
+
bridging::getParameterCount(&T::login) == 3,
|
193
|
+
"Expected login(...) to have 3 parameters");
|
194
|
+
|
195
|
+
return bridging::callFromJs<jsi::Value>(
|
196
|
+
rt, &T::login, jsInvoker_, instance_, std::move(uuid), std::move(externalId));
|
197
|
+
}
|
198
|
+
jsi::Value getProducts(jsi::Runtime &rt, jsi::String uuid, std::optional<jsi::Array> identifiers) override {
|
199
|
+
static_assert(
|
200
|
+
bridging::getParameterCount(&T::getProducts) == 3,
|
201
|
+
"Expected getProducts(...) to have 3 parameters");
|
202
|
+
|
203
|
+
return bridging::callFromJs<jsi::Value>(
|
204
|
+
rt, &T::getProducts, jsInvoker_, instance_, std::move(uuid), std::move(identifiers));
|
205
|
+
}
|
206
|
+
jsi::Value getSubscriptionGroups(jsi::Runtime &rt, jsi::String uuid, std::optional<jsi::Array> identifiers) override {
|
207
|
+
static_assert(
|
208
|
+
bridging::getParameterCount(&T::getSubscriptionGroups) == 3,
|
209
|
+
"Expected getSubscriptionGroups(...) to have 3 parameters");
|
210
|
+
|
211
|
+
return bridging::callFromJs<jsi::Value>(
|
212
|
+
rt, &T::getSubscriptionGroups, jsInvoker_, instance_, std::move(uuid), std::move(identifiers));
|
213
|
+
}
|
214
|
+
jsi::Value getEntitlementForSubscription(jsi::Runtime &rt, jsi::String uuid, jsi::String subscriptionGroupId) override {
|
215
|
+
static_assert(
|
216
|
+
bridging::getParameterCount(&T::getEntitlementForSubscription) == 3,
|
217
|
+
"Expected getEntitlementForSubscription(...) to have 3 parameters");
|
218
|
+
|
219
|
+
return bridging::callFromJs<jsi::Value>(
|
220
|
+
rt, &T::getEntitlementForSubscription, jsInvoker_, instance_, std::move(uuid), std::move(subscriptionGroupId));
|
221
|
+
}
|
222
|
+
jsi::Value getEntitlement(jsi::Runtime &rt, jsi::String uuid, jsi::String productId) override {
|
223
|
+
static_assert(
|
224
|
+
bridging::getParameterCount(&T::getEntitlement) == 3,
|
225
|
+
"Expected getEntitlement(...) to have 3 parameters");
|
226
|
+
|
227
|
+
return bridging::callFromJs<jsi::Value>(
|
228
|
+
rt, &T::getEntitlement, jsInvoker_, instance_, std::move(uuid), std::move(productId));
|
229
|
+
}
|
230
|
+
jsi::Value getEntitlements(jsi::Runtime &rt, jsi::String uuid, jsi::Array productIds) override {
|
231
|
+
static_assert(
|
232
|
+
bridging::getParameterCount(&T::getEntitlements) == 3,
|
233
|
+
"Expected getEntitlements(...) to have 3 parameters");
|
234
|
+
|
235
|
+
return bridging::callFromJs<jsi::Value>(
|
236
|
+
rt, &T::getEntitlements, jsInvoker_, instance_, std::move(uuid), std::move(productIds));
|
237
|
+
}
|
238
|
+
jsi::Value requestTransferOwnership(jsi::Runtime &rt, jsi::String uuid) override {
|
239
|
+
static_assert(
|
240
|
+
bridging::getParameterCount(&T::requestTransferOwnership) == 2,
|
241
|
+
"Expected requestTransferOwnership(...) to have 2 parameters");
|
242
|
+
|
243
|
+
return bridging::callFromJs<jsi::Value>(
|
244
|
+
rt, &T::requestTransferOwnership, jsInvoker_, instance_, std::move(uuid));
|
245
|
+
}
|
246
|
+
jsi::Value openManageSubscription(jsi::Runtime &rt, jsi::String uuid) override {
|
247
|
+
static_assert(
|
248
|
+
bridging::getParameterCount(&T::openManageSubscription) == 2,
|
249
|
+
"Expected openManageSubscription(...) to have 2 parameters");
|
250
|
+
|
251
|
+
return bridging::callFromJs<jsi::Value>(
|
252
|
+
rt, &T::openManageSubscription, jsInvoker_, instance_, std::move(uuid));
|
253
|
+
}
|
254
|
+
jsi::Value purchaseProduct(jsi::Runtime &rt, jsi::String uuid, jsi::String productId, std::optional<jsi::Object> options) override {
|
255
|
+
static_assert(
|
256
|
+
bridging::getParameterCount(&T::purchaseProduct) == 4,
|
257
|
+
"Expected purchaseProduct(...) to have 4 parameters");
|
258
|
+
|
259
|
+
return bridging::callFromJs<jsi::Value>(
|
260
|
+
rt, &T::purchaseProduct, jsInvoker_, instance_, std::move(uuid), std::move(productId), std::move(options));
|
261
|
+
}
|
262
|
+
void sendDiagnotic(jsi::Runtime &rt, jsi::String uuid) override {
|
263
|
+
static_assert(
|
264
|
+
bridging::getParameterCount(&T::sendDiagnotic) == 2,
|
265
|
+
"Expected sendDiagnotic(...) to have 2 parameters");
|
266
|
+
|
267
|
+
return bridging::callFromJs<void>(
|
268
|
+
rt, &T::sendDiagnotic, jsInvoker_, instance_, std::move(uuid));
|
269
|
+
}
|
270
|
+
jsi::Value getStoreCountry(jsi::Runtime &rt, jsi::String uuid) override {
|
271
|
+
static_assert(
|
272
|
+
bridging::getParameterCount(&T::getStoreCountry) == 2,
|
273
|
+
"Expected getStoreCountry(...) to have 2 parameters");
|
274
|
+
|
275
|
+
return bridging::callFromJs<jsi::Value>(
|
276
|
+
rt, &T::getStoreCountry, jsInvoker_, instance_, std::move(uuid));
|
277
|
+
}
|
278
|
+
|
279
|
+
private:
|
280
|
+
friend class NativeMobilyflowReactNativeSdkCxxSpec;
|
281
|
+
T *instance_;
|
282
|
+
};
|
283
|
+
|
284
|
+
Delegate delegate_;
|
285
|
+
};
|
286
|
+
|
287
|
+
} // namespace facebook::react
|
@@ -0,0 +1,183 @@
|
|
1
|
+
package com.mobilyflowreactnativesdk
|
2
|
+
|
3
|
+
import android.util.Log
|
4
|
+
import com.facebook.react.bridge.Promise
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
8
|
+
import com.facebook.react.module.annotations.ReactModule
|
9
|
+
import com.mobilyflow.mobilypurchasesdk.Enums.MobilyEnvironment
|
10
|
+
import com.mobilyflow.mobilypurchasesdk.Exceptions.MobilyException
|
11
|
+
import com.mobilyflow.mobilypurchasesdk.Exceptions.MobilyPurchaseException
|
12
|
+
import com.mobilyflow.mobilypurchasesdk.Exceptions.MobilyTransferOwnershipException
|
13
|
+
import com.mobilyflow.mobilypurchasesdk.MobilyPurchaseSDK
|
14
|
+
import com.mobilyflow.mobilypurchasesdk.MobilyPurchaseSDKOptions
|
15
|
+
import com.mobilyflow.mobilypurchasesdk.Models.PurchaseOptions
|
16
|
+
import java.util.UUID
|
17
|
+
|
18
|
+
@ReactModule(name = MobilyflowReactNativeSdkModule.NAME)
|
19
|
+
class MobilyflowReactNativeSdkModule(reactContext: ReactApplicationContext) : NativeMobilyflowReactNativeSdkSpec(reactContext) {
|
20
|
+
private val _sdkInstances = mutableMapOf<String, MobilyPurchaseSDK>()
|
21
|
+
|
22
|
+
private fun throwError(error: Exception, promise: Promise) {
|
23
|
+
when (error) {
|
24
|
+
is MobilyException -> promise.reject(error.type.ordinal.toString(), error.message, error)
|
25
|
+
is MobilyPurchaseException -> promise.reject(error.type.ordinal.toString(), error.message, error)
|
26
|
+
is MobilyTransferOwnershipException -> promise.reject(error.type.ordinal.toString(), error.message, error)
|
27
|
+
else -> promise.reject("-1", error.message, error)
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
override fun getName(): String {
|
32
|
+
return NAME
|
33
|
+
}
|
34
|
+
|
35
|
+
override fun instantiate(appId: String, apiKey: String, environment: Double, options: ReadableMap?): String {
|
36
|
+
val uuid = UUID.randomUUID().toString()
|
37
|
+
|
38
|
+
var realOptions: MobilyPurchaseSDKOptions? = null
|
39
|
+
if (options != null) {
|
40
|
+
realOptions = MobilyPurchaseSDKOptions(
|
41
|
+
options.getArray("languages").toStringArray(),
|
42
|
+
options.optBoolean("debug"),
|
43
|
+
options.getString("apiURL")
|
44
|
+
)
|
45
|
+
}
|
46
|
+
|
47
|
+
val realEnvironment = MobilyEnvironment.entries.find { x -> x.value == environment.toInt() }
|
48
|
+
val sdk = MobilyPurchaseSDK(reactApplicationContext, appId, apiKey, realEnvironment!!, realOptions)
|
49
|
+
_sdkInstances[uuid] = sdk
|
50
|
+
|
51
|
+
return uuid
|
52
|
+
}
|
53
|
+
|
54
|
+
override fun close(uuid: String) {
|
55
|
+
_sdkInstances[uuid]!!.close()
|
56
|
+
}
|
57
|
+
|
58
|
+
override fun login(uuid: String, externalId: String, promise: Promise) {
|
59
|
+
try {
|
60
|
+
_sdkInstances[uuid]!!.login(externalId)
|
61
|
+
promise.resolve(1)
|
62
|
+
} catch (error: Exception) {
|
63
|
+
throwError(error, promise)
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
override fun getProducts(uuid: String, identifiers: ReadableArray?, promise: Promise) {
|
68
|
+
try {
|
69
|
+
val products = _sdkInstances[uuid]!!.getProducts(identifiers.toStringArray(), false)
|
70
|
+
promise.resolve(products.toReadableArray())
|
71
|
+
} catch (error: Exception) {
|
72
|
+
throwError(error, promise)
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
override fun getSubscriptionGroups(uuid: String, identifiers: ReadableArray?, promise: Promise) {
|
77
|
+
try {
|
78
|
+
val groups = _sdkInstances[uuid]!!.getSubscriptionGroups(identifiers.toStringArray(), false)
|
79
|
+
promise.resolve(groups.toReadableArray())
|
80
|
+
} catch (error: Exception) {
|
81
|
+
throwError(error, promise)
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
override fun getEntitlementForSubscription(uuid: String, subscriptionGroupId: String, promise: Promise) {
|
86
|
+
try {
|
87
|
+
val entitlement = _sdkInstances[uuid]!!.getEntitlementForSubscription(subscriptionGroupId)
|
88
|
+
promise.resolve(entitlement.toReadableMap())
|
89
|
+
} catch (error: Exception) {
|
90
|
+
throwError(error, promise)
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
override fun getEntitlement(uuid: String, productId: String, promise: Promise) {
|
95
|
+
try {
|
96
|
+
val entitlement = _sdkInstances[uuid]!!.getEntitlement(productId)
|
97
|
+
promise.resolve(entitlement.toReadableMap())
|
98
|
+
} catch (error: Exception) {
|
99
|
+
throwError(error, promise)
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
override fun getEntitlements(uuid: String, productIds: ReadableArray, promise: Promise) {
|
104
|
+
try {
|
105
|
+
val entitlements = _sdkInstances[uuid]!!.getEntitlements(productIds.toStringArray()!!)
|
106
|
+
promise.resolve(entitlements.toReadableArray())
|
107
|
+
} catch (error: Exception) {
|
108
|
+
throwError(error, promise)
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
override fun requestTransferOwnership(uuid: String, promise: Promise) {
|
113
|
+
try {
|
114
|
+
val status = _sdkInstances[uuid]!!.requestTransferOwnership()
|
115
|
+
promise.resolve(status.value)
|
116
|
+
} catch (error: Exception) {
|
117
|
+
throwError(error, promise)
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
override fun openManageSubscription(uuid: String, promise: Promise) {
|
122
|
+
try {
|
123
|
+
_sdkInstances[uuid]!!.openManageSubscription()
|
124
|
+
promise.resolve(0)
|
125
|
+
} catch (error: Exception) {
|
126
|
+
throwError(error, promise)
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
override fun purchaseProduct(uuid: String, productId: String, options: ReadableMap?, promise: Promise) {
|
131
|
+
try {
|
132
|
+
if (reactApplicationContext.currentActivity == null) {
|
133
|
+
throw MobilyException(MobilyException.Type.UNKNOWN_ERROR)
|
134
|
+
}
|
135
|
+
|
136
|
+
val sdk = _sdkInstances[uuid]!!
|
137
|
+
|
138
|
+
val purchaseOptions = PurchaseOptions()
|
139
|
+
val offerId = options?.getString("offerId")
|
140
|
+
|
141
|
+
val product = sdk.getProducts(null, false).find { x -> x.id == productId }
|
142
|
+
if (product == null) {
|
143
|
+
throw MobilyPurchaseException(MobilyPurchaseException.Type.PRODUCT_UNAVAILABLE)
|
144
|
+
}
|
145
|
+
|
146
|
+
if (offerId != null) {
|
147
|
+
if (product.subscriptionProduct!!.baseOffer.id == offerId) {
|
148
|
+
purchaseOptions.setOffer(product.subscriptionProduct!!.baseOffer)
|
149
|
+
} else if (product.subscriptionProduct!!.freeTrial?.id == offerId) {
|
150
|
+
purchaseOptions.setOffer(product.subscriptionProduct!!.freeTrial)
|
151
|
+
} else {
|
152
|
+
val offer = product.subscriptionProduct!!.promotionalOffers.find { x -> x.id == offerId }
|
153
|
+
if (offer != null) {
|
154
|
+
purchaseOptions.setOffer(offer)
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
sdk.purchaseProduct(reactApplicationContext.currentActivity!!, product, purchaseOptions)
|
160
|
+
} catch (error: Exception) {
|
161
|
+
throwError(error, promise)
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
override fun sendDiagnotic(uuid: String) {
|
166
|
+
_sdkInstances[uuid]!!.sendDiagnostic()
|
167
|
+
}
|
168
|
+
|
169
|
+
override fun getStoreCountry(uuid: String, promise: Promise) {
|
170
|
+
/*try {
|
171
|
+
val status = _sdkInstances[uuid]!!.getS()
|
172
|
+
promise.resolve(status.value)
|
173
|
+
} catch (error: Exception) {
|
174
|
+
throwError(error, promise)
|
175
|
+
}*/
|
176
|
+
// TODO
|
177
|
+
return promise.resolve("FRA")
|
178
|
+
}
|
179
|
+
|
180
|
+
companion object {
|
181
|
+
const val NAME = "MobilyflowReactNativeSdk"
|
182
|
+
}
|
183
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
package com.mobilyflowreactnativesdk
|
2
|
+
|
3
|
+
import com.facebook.react.BaseReactPackage
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
8
|
+
|
9
|
+
class MobilyflowReactNativeSdkPackage : BaseReactPackage() {
|
10
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
11
|
+
return if (name == MobilyflowReactNativeSdkModule.NAME) {
|
12
|
+
MobilyflowReactNativeSdkModule(reactContext)
|
13
|
+
} else {
|
14
|
+
null
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
19
|
+
return ReactModuleInfoProvider {
|
20
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
21
|
+
moduleInfos[MobilyflowReactNativeSdkModule.NAME] = ReactModuleInfo(
|
22
|
+
MobilyflowReactNativeSdkModule.NAME,
|
23
|
+
MobilyflowReactNativeSdkModule.NAME,
|
24
|
+
false, // canOverrideExistingModule
|
25
|
+
false, // needsEagerInit
|
26
|
+
false, // isCxxModule
|
27
|
+
true // isTurboModule
|
28
|
+
)
|
29
|
+
moduleInfos
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
package com.mobilyflowreactnativesdk
|
2
|
+
|
3
|
+
import com.facebook.react.bridge.Arguments
|
4
|
+
import com.facebook.react.bridge.ReadableArray
|
5
|
+
import com.facebook.react.bridge.ReadableMap
|
6
|
+
import com.facebook.react.bridge.WritableArray
|
7
|
+
import com.facebook.react.bridge.WritableMap
|
8
|
+
import kotlinx.datetime.LocalDateTime
|
9
|
+
import kotlinx.datetime.format
|
10
|
+
import org.json.JSONArray
|
11
|
+
import org.json.JSONObject
|
12
|
+
import kotlin.reflect.full.isSubclassOf
|
13
|
+
import kotlin.reflect.full.memberProperties
|
14
|
+
|
15
|
+
/**
|
16
|
+
* Take a value and return String, Int, Double, Boolean, ReadableArray or ReadableMap
|
17
|
+
*/
|
18
|
+
private fun getJsonRawValue(value: Any?): Any? {
|
19
|
+
when (value) {
|
20
|
+
null -> return null
|
21
|
+
is String -> return value
|
22
|
+
is Int -> return value
|
23
|
+
is Double -> return value
|
24
|
+
is Boolean -> return value
|
25
|
+
is ReadableArray -> return value
|
26
|
+
is ReadableMap -> return value
|
27
|
+
is LocalDateTime -> return value.format(LocalDateTime.Formats.ISO) + 'Z'
|
28
|
+
is Map<*, *> -> return value.toReadableMap()
|
29
|
+
is JSONObject -> return value.toReadableMap()
|
30
|
+
is Collection<*> -> return value.toReadableArray()
|
31
|
+
is JSONArray -> return value.toReadableArray()
|
32
|
+
else -> {
|
33
|
+
if (value::class.isSubclassOf(Enum::class)) {
|
34
|
+
val enumValue = value::class.memberProperties.find { x -> x.name == "value" }
|
35
|
+
if (enumValue != null) {
|
36
|
+
val rawValue = enumValue.call(value)
|
37
|
+
return getJsonRawValue(rawValue)
|
38
|
+
} else {
|
39
|
+
return value.toString()
|
40
|
+
}
|
41
|
+
} else {
|
42
|
+
return value.toReadableMap()
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
private fun WritableMap.put(key: String, value: Any?) {
|
49
|
+
when (val rawValue = getJsonRawValue(value)) {
|
50
|
+
null -> this.putNull(key)
|
51
|
+
is String -> this.putString(key, rawValue)
|
52
|
+
is Int -> this.putInt(key, rawValue)
|
53
|
+
is Double -> this.putDouble(key, rawValue)
|
54
|
+
is Boolean -> this.putBoolean(key, rawValue)
|
55
|
+
is ReadableArray -> this.putArray(key, rawValue)
|
56
|
+
is ReadableMap -> this.putMap(key, rawValue)
|
57
|
+
else -> throw IllegalArgumentException("Unsupported type: ${value!!::class.simpleName}")
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
private fun WritableArray.push(value: Any?) {
|
62
|
+
when (val rawValue = getJsonRawValue(value)) {
|
63
|
+
null -> this.pushNull()
|
64
|
+
is String -> this.pushString(rawValue)
|
65
|
+
is Int -> this.pushInt(rawValue)
|
66
|
+
is Double -> this.pushDouble(rawValue)
|
67
|
+
is Boolean -> this.pushBoolean(rawValue)
|
68
|
+
is ReadableArray -> this.pushArray(rawValue)
|
69
|
+
is ReadableMap -> this.pushMap(rawValue)
|
70
|
+
else -> throw IllegalArgumentException("Unsupported type: ${value!!::class.simpleName}")
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
fun Any?.toReadableMap(): ReadableMap? {
|
75
|
+
if (this == null) {
|
76
|
+
return null
|
77
|
+
} else {
|
78
|
+
val map = Arguments.createMap()
|
79
|
+
this::class.memberProperties.forEach { property ->
|
80
|
+
val key = property.name
|
81
|
+
val value = property.getter.call(this)
|
82
|
+
map.put(key, value)
|
83
|
+
}
|
84
|
+
return map
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
fun Map<*, *>.toReadableMap(): ReadableMap {
|
89
|
+
val map = Arguments.createMap()
|
90
|
+
forEach { (key, value) ->
|
91
|
+
if (key is String) {
|
92
|
+
map.put(key, value)
|
93
|
+
}
|
94
|
+
}
|
95
|
+
return map
|
96
|
+
}
|
97
|
+
|
98
|
+
fun JSONObject.toReadableMap(): ReadableMap {
|
99
|
+
val map = Arguments.createMap()
|
100
|
+
|
101
|
+
for (key in this.keys()) {
|
102
|
+
map.put(key, this.get(key))
|
103
|
+
}
|
104
|
+
|
105
|
+
return map
|
106
|
+
}
|
107
|
+
|
108
|
+
fun Collection<*>.toReadableArray(): ReadableArray {
|
109
|
+
val array = Arguments.createArray()
|
110
|
+
forEach { item ->
|
111
|
+
array.push(item)
|
112
|
+
}
|
113
|
+
return array
|
114
|
+
}
|
115
|
+
|
116
|
+
fun JSONArray.toReadableArray(): ReadableArray {
|
117
|
+
val array = Arguments.createArray()
|
118
|
+
|
119
|
+
for (index in 0..<this.length()) {
|
120
|
+
array.push(this.get(index))
|
121
|
+
}
|
122
|
+
|
123
|
+
return array
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
fun ReadableArray?.toStringArray(): Array<String>? {
|
128
|
+
return if (this != null) {
|
129
|
+
Array(this.size()) { i -> this.getString(i) ?: "" }
|
130
|
+
} else {
|
131
|
+
null
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
fun ReadableMap.optBoolean(key: String, defaultValue: Boolean? = false): Boolean? {
|
136
|
+
return if (this.hasKey(key) && !this.isNull(key)) {
|
137
|
+
this.getBoolean(key)
|
138
|
+
} else {
|
139
|
+
defaultValue
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
fun ReadableMap.optInt(key: String, defaultValue: Int? = null): Int? {
|
144
|
+
return if (this.hasKey(key) && !this.isNull(key)) {
|
145
|
+
this.getInt(key)
|
146
|
+
} else {
|
147
|
+
defaultValue
|
148
|
+
}
|
149
|
+
}
|