Skip to content

Commit d2e85e4

Browse files
Merge pull request #105 from qonversion/release/4.1.0
Release/4.1.0
2 parents 30c4960 + e904307 commit d2e85e4

File tree

16 files changed

+194
-66
lines changed

16 files changed

+194
-66
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.1.0
2+
* New Product fields: storeTitle, storeDescription, price, currencyCode, prettyIntroductoryPrice.
3+
* Improved errors details.
4+
15
## 4.0.0
26
* From now Qonversion supports Google Play Billing Library 4.0.0 version for Android.
37

android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
group 'com.qonversion.flutter.sdk.qonversion_flutter_sdk'
2-
version '4.0.0'
2+
version '4.1.0'
33

44
buildscript {
55
ext.kotlin_version = '1.3.50'
6-
ext.qonversion_version = '3.0.0'
6+
ext.qonversion_version = '3.1.0'
77
repositories {
88
google()
99
jcenter()

android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/FlutterResult+CustomErrors.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.qonversion.flutter.sdk.qonversion_flutter_sdk
22

3+
import com.qonversion.android.sdk.QonversionError
34
import io.flutter.plugin.common.MethodChannel
45

56
private const val passValidValue = "Please make sure you pass a valid value"
@@ -36,8 +37,9 @@ fun MethodChannel.Result.noProductIdError() {
3637
return this.error("8", "Could not find productId value", "Please provide valid productId")
3738
}
3839

39-
fun MethodChannel.Result.qonversionError(message: String, cause: String) {
40-
return this.error("9", message, cause)
40+
fun MethodChannel.Result.qonversionError(error: QonversionError) {
41+
val errorDetails = getErrorDetails(error)
42+
return this.error("9", error.description, errorDetails)
4143
}
4244

4345
fun MethodChannel.Result.noNewProductIdError() {
@@ -60,8 +62,9 @@ fun MethodChannel.Result.noPropertyValue() {
6062
return this.error("14", "Could not find property value", passValidValue)
6163
}
6264

63-
fun MethodChannel.Result.offeringsError(description: String?, message: String?) {
64-
return this.error("Offerings", "Could not get offerings", "$description $message")
65+
fun MethodChannel.Result.offeringsError(error: QonversionError) {
66+
val errorDetails = getErrorDetails(error)
67+
return this.error("Offerings", "Could not get offerings. ${error.description}.", errorDetails)
6568
}
6669

6770
fun MethodChannel.Result.noSdkInfo() {
@@ -75,3 +78,12 @@ fun MethodChannel.Result.noProductIdField(details: String?) {
7578
fun MethodChannel.Result.jsonSerializationError(details: String?) {
7679
return this.error("JSONSerialization", "JSON Serialization Error", details)
7780
}
81+
82+
private fun getErrorDetails(error: QonversionError): String {
83+
var result = "Qonversion Error Code: ${error.code}"
84+
if (error.additionalMessage.isNotEmpty()) {
85+
result += ". Additional Message: ${error.additionalMessage}"
86+
}
87+
88+
return result
89+
}

android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/Mapper.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.google.gson.Gson
55
import com.google.gson.JsonSyntaxException
66
import com.google.gson.reflect.TypeToken
77
import com.qonversion.android.sdk.QonversionError
8+
import com.qonversion.android.sdk.QonversionErrorCode
89
import com.qonversion.android.sdk.dto.QLaunchResult
910
import com.qonversion.android.sdk.dto.QPermission
1011
import com.qonversion.android.sdk.dto.eligibility.QEligibility
@@ -18,13 +19,23 @@ import com.qonversion.android.sdk.dto.products.QTrialDuration
1819

1920
data class PurchaseResult(val permissions: Map<String, QPermission>? = null, val error: QonversionError? = null) {
2021
fun toMap(): Map<String, Any?> {
22+
val isUserCancelled = error?.code == QonversionErrorCode.CanceledPurchase
2123
return mapOf(
2224
"permissions" to permissions?.mapValues { it.value.toMap() },
23-
"error" to (error?.description ?: error?.additionalMessage)
25+
"error" to error.toMap(),
26+
"is_cancelled" to isUserCancelled
2427
)
2528
}
2629
}
2730

31+
fun QonversionError?.toMap(): Map<String, String>? {
32+
if (this == null) return null
33+
34+
return mapOf("code" to code.toString(),
35+
"description" to description,
36+
"additionalMessage" to additionalMessage)
37+
}
38+
2839
fun QLaunchResult.toMap(): Map<String, Any> {
2940
return mapOf(
3041
"uid" to uid,
@@ -128,7 +139,7 @@ fun mapQProduct(jsonProduct: String): QProduct? {
128139
val trialDuration = mappedProduct[ProductFields.TRIAL_DURATION] as? Double
129140
val productTrialDuration = trialDuration?.toInt()?.let { QTrialDuration.fromType(it) }
130141

131-
val offeringId = mappedProduct[ProductFields.OFFERING_ID] as String
142+
val offeringId = mappedProduct[ProductFields.OFFERING_ID] as? String
132143

133144
val originalSkuDetails = mappedProduct[SkuDetailsFields.ORIGINAL_JSON] as? String
134145
val skuDetails = originalSkuDetails?.let { SkuDetails(it) }

android/src/main/kotlin/com/qonversion/flutter/sdk/qonversion_flutter_sdk/QonversionFlutterSdkPlugin.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
133133
}
134134

135135
override fun onError(error: QonversionError) {
136-
result.qonversionError(error.description, error.additionalMessage)
136+
result.qonversionError(error)
137137
}
138138
}
139139
)
@@ -233,7 +233,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
233233
}
234234

235235
override fun onError(error: QonversionError) {
236-
result.qonversionError(error.description, error.additionalMessage)
236+
result.qonversionError(error)
237237
}
238238
})
239239
}
@@ -245,7 +245,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
245245
}
246246

247247
override fun onError(error: QonversionError) {
248-
result.qonversionError(error.description, error.additionalMessage)
248+
result.qonversionError(error)
249249
}
250250
})
251251
}
@@ -258,7 +258,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
258258
}
259259

260260
override fun onError(error: QonversionError) {
261-
result.offeringsError(error.description, error.additionalMessage)
261+
result.offeringsError(error)
262262
}
263263
})
264264
}
@@ -270,7 +270,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
270270
}
271271

272272
override fun onError(error: QonversionError) {
273-
result.qonversionError(error.description, error.additionalMessage)
273+
result.qonversionError(error)
274274
}
275275
})
276276
}
@@ -342,7 +342,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
342342
}
343343

344344
override fun onError(error: QonversionError) {
345-
result.qonversionError(error.additionalMessage, error.description)
345+
result.qonversionError(error)
346346
}
347347
})
348348
}
@@ -360,7 +360,7 @@ class QonversionFlutterSdkPlugin : MethodCallHandler, FlutterPlugin, ActivityAwa
360360
result.success(permissions.mapValues { it.value.toMap() })
361361

362362
override fun onError(error: QonversionError) =
363-
result.qonversionError(error.description, error.additionalMessage)
363+
result.qonversionError(error)
364364
}
365365

366366
private fun handleMissingProductIdField(result: Result, functionName: String?) {

ios/Classes/FlutterError+Custom.swift

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ extension FlutterError {
3838
message: "Could not find provider",
3939
details: passValidValue)
4040

41-
static func failedToGetProducts(_ description: String) -> FlutterError {
42-
return FlutterError(code: "7",
43-
message: "Failed to get products",
44-
details: description)
41+
static func failedToGetProducts(_ error: NSError) -> FlutterError {
42+
return mapQonversionError(error, errorCode: "7", errorMessage: "Failed to get products")
4543
}
4644

4745
static let noProductId = FlutterError(code: "8",
@@ -52,10 +50,8 @@ extension FlutterError {
5250
message: "Could not find product",
5351
details: "Please provide a valid product")
5452

55-
static func qonversionError(_ description: String) -> FlutterError {
56-
return FlutterError(code: "9",
57-
message: "Qonversion Error",
58-
details: description)
53+
static func qonversionError(_ error: NSError) -> FlutterError {
54+
return mapQonversionError(error, errorCode: "9")
5955
}
6056

6157
static func parsingError(_ description: String) -> FlutterError {
@@ -72,10 +68,8 @@ extension FlutterError {
7268
message: "Could not find property value",
7369
details: passValidValue)
7470

75-
static func offeringsError(_ description: String) -> FlutterError {
76-
return FlutterError(code: "Offerings",
77-
message: "Could not get offerings",
78-
details: description)
71+
static func offeringsError(_ error: NSError) -> FlutterError {
72+
return mapQonversionError(error, errorCode: "Offerings", errorMessage: "Could not get offerings")
7973
}
8074

8175
static let noSdkInfo = FlutterError(code: "15",
@@ -100,4 +94,23 @@ extension FlutterError {
10094
message: "Could not find qonversionId in Product",
10195
details: description)
10296
}
97+
98+
private static func mapQonversionError(_ error: NSError, errorCode: String, errorMessage: String? = nil) -> FlutterError {
99+
var message = ""
100+
101+
if let errorMessage = errorMessage {
102+
message = errorMessage + ". "
103+
}
104+
message += error.localizedDescription
105+
106+
var details = "Qonversion Error Code: \(error.code)"
107+
108+
if let additionalMessage = error.userInfo[NSDebugDescriptionErrorKey] {
109+
details = "\(details). Additional Message: \(additionalMessage)"
110+
}
111+
112+
return FlutterError(code: errorCode,
113+
message: message,
114+
details: details)
115+
}
103116
}

ios/Classes/Mapper.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,28 @@ enum ParsingError: Error {
1313

1414
struct PurchaseResult {
1515
let permissions: [String : Qonversion.Permission]
16-
let error: Error?
16+
let error: NSError?
1717
let isCancelled: Bool
1818

1919
func toMap() -> [String: Any?] {
2020
return [
2121
"permissions": permissions.mapValues { $0.toMap() },
22-
"error": error?.localizedDescription,
22+
"error": error?.toMap(),
2323
"is_cancelled": isCancelled,
2424
]
2525
}
26+
27+
}
28+
29+
extension NSError {
30+
func toMap() -> [String: Any?] {
31+
let errorMap = [
32+
"code": code,
33+
"description": localizedDescription,
34+
"additionalMessage": userInfo[NSDebugDescriptionErrorKey]]
35+
36+
return errorMap
37+
}
2638
}
2739

2840
extension Qonversion.LaunchResult {
@@ -133,7 +145,7 @@ extension Dictionary {
133145
let product = Qonversion.Product()
134146

135147
product.qonversionID = id
136-
148+
137149
product.storeID = data[ProductFields.storeId] as? String ?? ""
138150

139151
if let type = data[ProductFields.type] as? Int {

ios/Classes/SKProduct+toMap.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ extension SKProductDiscount {
5757
"numberOfPeriods": numberOfPeriods,
5858
"subscriptionPeriod": subscriptionPeriod.toMap(),
5959
"paymentMode": paymentMode.rawValue,
60+
"priceLocale": priceLocale.toMap()
6061
]
6162
}
6263
}

ios/Classes/SwiftQonversionFlutterSdkPlugin.swift

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
117117
}
118118

119119
Qonversion.launch(withKey: apiKey) { launchResult, error in
120-
if let error = error {
121-
return result(FlutterError.qonversionError(error.localizedDescription))
120+
if let nsError = error as NSError? {
121+
return result(FlutterError.qonversionError(nsError))
122122
}
123123

124124
let resultMap = launchResult.toMap()
@@ -138,8 +138,8 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
138138

139139
private func products(_ result: @escaping FlutterResult) {
140140
Qonversion.products { (products, error) in
141-
if let error = error {
142-
return result(FlutterError.failedToGetProducts(error.localizedDescription))
141+
if let nsError = error as NSError? {
142+
return result(FlutterError.failedToGetProducts(nsError))
143143
}
144144

145145
let productsMap = products.mapValues { $0.toMap() }
@@ -154,8 +154,9 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
154154
}
155155

156156
Qonversion.purchase(productId) { (permissions, error, isCancelled) in
157+
let nsError = error as NSError?
157158
let purchaseResult = PurchaseResult(permissions: permissions,
158-
error: error,
159+
error: nsError,
159160
isCancelled: isCancelled)
160161
result(purchaseResult.toMap())
161162
}
@@ -169,16 +170,17 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
169170
do {
170171
let data = Data(jsonProduct.utf8)
171172
if let jsonMap = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
172-
173+
173174
guard let product = jsonMap.toProduct() else {
174175
let errorMessage = "Failed to deserialize Qonversion Product. There is no qonversionId"
175176
NSLog(errorMessage)
176177
return result(FlutterError.noProductIdField(errorMessage))
177178
}
178179

179180
Qonversion.purchaseProduct(product) { (permissions, error, isCancelled) in
181+
let nsError = error as NSError?
180182
let purchaseResult = PurchaseResult(permissions: permissions,
181-
error: error,
183+
error: nsError,
182184
isCancelled: isCancelled)
183185
result(purchaseResult.toMap())
184186
}
@@ -199,8 +201,9 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
199201
promoPurchasesExecutionBlocks.removeValue(forKey: productId)
200202

201203
executionBlock { (permissions, error, isCancelled) in
204+
let nsError = error as NSError?
202205
let purchaseResult = PurchaseResult(permissions: permissions,
203-
error: error,
206+
error: nsError,
204207
isCancelled: isCancelled)
205208
result(purchaseResult.toMap())
206209
}
@@ -211,8 +214,8 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
211214

212215
private func checkPermissions(_ result: @escaping FlutterResult) {
213216
Qonversion.checkPermissions { (permissions, error) in
214-
if let error = error {
215-
return result(FlutterError.qonversionError(error.localizedDescription))
217+
if let nsError = error as NSError? {
218+
return result(FlutterError.qonversionError(nsError))
216219
}
217220

218221
let permissionsDict = permissions.mapValues { $0.toMap() }
@@ -222,8 +225,8 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
222225

223226
private func restore(_ result: @escaping FlutterResult) {
224227
Qonversion.restore { (permissions, error) in
225-
if let error = error {
226-
return result(FlutterError.qonversionError(error.localizedDescription))
228+
if let nsError = error as NSError? {
229+
return result(FlutterError.qonversionError(nsError))
227230
}
228231

229232
let permissionsDict = permissions.mapValues { $0.toMap() }
@@ -233,8 +236,8 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
233236

234237
private func offerings(_ result: @escaping FlutterResult) {
235238
Qonversion.offerings { offerings, error in
236-
if let error = error {
237-
result(FlutterError.offeringsError(error.localizedDescription))
239+
if let nsError = error as NSError? {
240+
result(FlutterError.offeringsError(nsError))
238241
}
239242

240243
guard let offerings = offerings else {
@@ -273,7 +276,9 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
273276
} catch ParsingError.runtimeError(let message) {
274277
result(FlutterError.parsingError(message))
275278
} catch {
276-
result(FlutterError.qonversionError(error.localizedDescription))
279+
if let nsError = error as NSError? {
280+
result(FlutterError.qonversionError(nsError))
281+
}
277282
}
278283
}
279284

@@ -297,8 +302,8 @@ public class SwiftQonversionFlutterSdkPlugin: NSObject, FlutterPlugin {
297302
}
298303

299304
Qonversion.checkTrialIntroEligibility(forProductIds: ids) { eligibilities, error in
300-
if let error = error {
301-
return result(FlutterError.qonversionError(error.localizedDescription))
305+
if let nsError = error as NSError? {
306+
return result(FlutterError.qonversionError(nsError))
302307
}
303308

304309
result(eligibilities.mapValues { $0.toMap() }.toJson())

0 commit comments

Comments
 (0)