diff --git a/checkout-core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt b/checkout-core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt index ece6673222..93dfeda372 100644 --- a/checkout-core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt +++ b/checkout-core/src/main/java/com/adyen/checkout/core/internal/data/model/ErrorResponseBody.kt @@ -51,11 +51,11 @@ data class ErrorResponseBody( override fun deserialize(jsonObject: JSONObject): ErrorResponseBody { return try { ErrorResponseBody( - status = jsonObject.optInt(STATUS), - errorCode = jsonObject.optString(ERROR_CODE), - message = jsonObject.optString(MESSAGE), - errorType = jsonObject.optString(ERROR_TYPE), - pspReference = jsonObject.optString(PSP_REFERENCE), + status = jsonObject.getIntOrNull(STATUS), + errorCode = jsonObject.getStringOrNull(ERROR_CODE), + message = jsonObject.getStringOrNull(MESSAGE), + errorType = jsonObject.getStringOrNull(ERROR_TYPE), + pspReference = jsonObject.getStringOrNull(PSP_REFERENCE), ) } catch (e: JSONException) { throw ModelSerializationException(ErrorResponseBody::class.java, e) diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/Amount.kt b/components-core/src/main/java/com/adyen/checkout/components/core/Amount.kt index f92adf12c4..5dc27282ed 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/Amount.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/Amount.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.components.core import com.adyen.checkout.components.core.internal.util.EMPTY_VALUE import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getLongOrNull import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException @@ -41,7 +42,7 @@ data class Amount( override fun deserialize(jsonObject: JSONObject): Amount { return Amount( currency = jsonObject.getStringOrNull(CURRENCY), - value = jsonObject.optLong(VALUE, EMPTY_VALUE), + value = jsonObject.getLongOrNull(VALUE) ?: EMPTY_VALUE, ) } } diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/Installments.kt b/components-core/src/main/java/com/adyen/checkout/components/core/Installments.kt index e3428b4034..a70e87ebf1 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/Installments.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/Installments.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.components.core import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getIntOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -41,7 +42,7 @@ data class Installments( return try { Installments( plan = jsonObject.getString(PLAN), - value = jsonObject.optInt(VALUE, 1) + value = jsonObject.getIntOrNull(VALUE) ?: 1, ) } catch (e: JSONException) { throw ModelSerializationException(Installments::class.java, e) diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/Issuer.kt b/components-core/src/main/java/com/adyen/checkout/components/core/Issuer.kt index 57161575fc..1f323099fb 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/Issuer.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/Issuer.kt @@ -9,6 +9,7 @@ package com.adyen.checkout.components.core import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException @@ -44,7 +45,7 @@ data class Issuer( return Issuer( id = jsonObject.getStringOrNull(ID), name = jsonObject.getStringOrNull(NAME), - isDisabled = jsonObject.optBoolean(DISABLED, false), + isDisabled = jsonObject.getBooleanOrNull(DISABLED) ?: false, ) } } diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/OrderRequest.kt b/components-core/src/main/java/com/adyen/checkout/components/core/OrderRequest.kt index 734e739014..c78d7c8224 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/OrderRequest.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/OrderRequest.kt @@ -9,6 +9,7 @@ package com.adyen.checkout.components.core import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -38,8 +39,8 @@ data class OrderRequest constructor( override fun deserialize(jsonObject: JSONObject): OrderRequest { return OrderRequest( - pspReference = jsonObject.optString(PSP_REFERENCE, ""), - orderData = jsonObject.optString(ORDER_DATA, "") + pspReference = jsonObject.getStringOrNull(PSP_REFERENCE).orEmpty(), + orderData = jsonObject.getStringOrNull(ORDER_DATA).orEmpty(), ) } } diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/OrderResponse.kt b/components-core/src/main/java/com/adyen/checkout/components/core/OrderResponse.kt index 7eb2b8131c..d92b40ec85 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/OrderResponse.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/OrderResponse.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.components.core import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -38,7 +39,7 @@ data class OrderResponse( putOpt(AMOUNT, ModelUtils.serializeOpt(modelObject.amount, Amount.SERIALIZER)) putOpt( REMAINING_AMOUNT, - ModelUtils.serializeOpt(modelObject.remainingAmount, Amount.SERIALIZER) + ModelUtils.serializeOpt(modelObject.remainingAmount, Amount.SERIALIZER), ) } catch (e: JSONException) { throw ModelSerializationException(OrderResponse::class.java, e) @@ -48,12 +49,12 @@ data class OrderResponse( override fun deserialize(jsonObject: JSONObject): OrderResponse { return OrderResponse( - pspReference = jsonObject.optString(PSP_REFERENCE, ""), - orderData = jsonObject.optString(ORDER_DATA, ""), + pspReference = jsonObject.getStringOrNull(PSP_REFERENCE).orEmpty(), + orderData = jsonObject.getStringOrNull(ORDER_DATA).orEmpty(), amount = ModelUtils.deserializeOpt(jsonObject.optJSONObject(AMOUNT), Amount.SERIALIZER), remainingAmount = ModelUtils.deserializeOpt( jsonObject.optJSONObject(REMAINING_AMOUNT), - Amount.SERIALIZER + Amount.SERIALIZER, ), ) } diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/PaymentComponentData.kt b/components-core/src/main/java/com/adyen/checkout/components/core/PaymentComponentData.kt index aeb4b7a57a..ba6bd96a6a 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/PaymentComponentData.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/PaymentComponentData.kt @@ -12,6 +12,8 @@ import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils.deserializeOpt import com.adyen.checkout.core.internal.data.model.ModelUtils.serializeOpt +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -89,17 +91,17 @@ data class PaymentComponentData( ), order = deserializeOpt(jsonObject.optJSONObject(ORDER), OrderRequest.SERIALIZER), amount = deserializeOpt(jsonObject.optJSONObject(AMOUNT), Amount.SERIALIZER), - storePaymentMethod = jsonObject.optBoolean(STORE_PAYMENT_METHOD), - shopperReference = jsonObject.optString(SHOPPER_REFERENCE), + storePaymentMethod = jsonObject.getBooleanOrNull(STORE_PAYMENT_METHOD), + shopperReference = jsonObject.getStringOrNull(SHOPPER_REFERENCE), billingAddress = deserializeOpt(jsonObject.optJSONObject(BILLING_ADDRESS), Address.SERIALIZER), deliveryAddress = deserializeOpt(jsonObject.optJSONObject(DELIVERY_ADDRESS), Address.SERIALIZER), shopperName = deserializeOpt(jsonObject.optJSONObject(SHOPPER_NAME), ShopperName.SERIALIZER), - telephoneNumber = jsonObject.optString(TELEPHONE_NUMBER), - shopperEmail = jsonObject.optString(SHOPPER_EMAIL), - dateOfBirth = jsonObject.optString(DATE_OF_BIRTH), - socialSecurityNumber = jsonObject.optString(SOCIAL_SECURITY_NUMBER), + telephoneNumber = jsonObject.getStringOrNull(TELEPHONE_NUMBER), + shopperEmail = jsonObject.getStringOrNull(SHOPPER_EMAIL), + dateOfBirth = jsonObject.getStringOrNull(DATE_OF_BIRTH), + socialSecurityNumber = jsonObject.getStringOrNull(SOCIAL_SECURITY_NUMBER), installments = deserializeOpt(jsonObject.optJSONObject(INSTALLMENTS), Installments.SERIALIZER), - supportNativeRedirect = jsonObject.optBoolean(SUPPORT_NATIVE_REDIRECT), + supportNativeRedirect = jsonObject.getBooleanOrNull(SUPPORT_NATIVE_REDIRECT), ) } } diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/action/Action.kt b/components-core/src/main/java/com/adyen/checkout/components/core/action/Action.kt index 05e025517a..6d79d16f3b 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/action/Action.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/action/Action.kt @@ -9,6 +9,7 @@ package com.adyen.checkout.components.core.action import com.adyen.checkout.core.exception.CheckoutException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import org.json.JSONObject /** @@ -41,10 +42,7 @@ abstract class Action : ModelObject() { } override fun deserialize(jsonObject: JSONObject): Action { - val actionType = jsonObject.optString(TYPE) - if (actionType.isEmpty()) { - throw CheckoutException("Action type not found") - } + val actionType = jsonObject.getStringOrNull(TYPE) ?: throw CheckoutException("Action type not found") val serializer = getChildSerializer(actionType) return serializer.deserialize(jsonObject) } diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/action/TwintSdkData.kt b/components-core/src/main/java/com/adyen/checkout/components/core/action/TwintSdkData.kt index b62db89c2d..547f0a6435 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/action/TwintSdkData.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/action/TwintSdkData.kt @@ -9,6 +9,7 @@ package com.adyen.checkout.components.core.action import com.adyen.checkout.core.exception.ModelSerializationException +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -41,7 +42,7 @@ data class TwintSdkData( return try { TwintSdkData( token = jsonObject.getString(TOKEN), - isStored = jsonObject.optBoolean(IS_STORED), + isStored = jsonObject.getBooleanOrNull(IS_STORED) ?: false, ) } catch (e: JSONException) { throw ModelSerializationException(TwintSdkData::class.java, e) diff --git a/components-core/src/main/java/com/adyen/checkout/components/core/internal/data/model/PublicKeyResponse.kt b/components-core/src/main/java/com/adyen/checkout/components/core/internal/data/model/PublicKeyResponse.kt index 775e7d766f..8884c44a59 100644 --- a/components-core/src/main/java/com/adyen/checkout/components/core/internal/data/model/PublicKeyResponse.kt +++ b/components-core/src/main/java/com/adyen/checkout/components/core/internal/data/model/PublicKeyResponse.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.components.core.internal.data.model import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -38,7 +39,7 @@ internal data class PublicKeyResponse( override fun deserialize(jsonObject: JSONObject): PublicKeyResponse { return try { PublicKeyResponse( - publicKey = jsonObject.optString(PUBLIC_KEY) + publicKey = jsonObject.getStringOrNull(PUBLIC_KEY).orEmpty(), ) } catch (e: JSONException) { throw ModelSerializationException(PublicKeyResponse::class.java, e) diff --git a/googlepay/src/main/java/com/adyen/checkout/googlepay/BillingAddressParameters.kt b/googlepay/src/main/java/com/adyen/checkout/googlepay/BillingAddressParameters.kt index 03ef5e2662..1673aae4de 100644 --- a/googlepay/src/main/java/com/adyen/checkout/googlepay/BillingAddressParameters.kt +++ b/googlepay/src/main/java/com/adyen/checkout/googlepay/BillingAddressParameters.kt @@ -9,6 +9,7 @@ package com.adyen.checkout.googlepay import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException @@ -49,7 +50,7 @@ data class BillingAddressParameters( override fun deserialize(jsonObject: JSONObject) = BillingAddressParameters( format = jsonObject.getStringOrNull(FORMAT), - isPhoneNumberRequired = jsonObject.optBoolean(PHONE_NUMBER_REQUIRED), + isPhoneNumberRequired = jsonObject.getBooleanOrNull(PHONE_NUMBER_REQUIRED) ?: false, ) } } diff --git a/googlepay/src/main/java/com/adyen/checkout/googlepay/ShippingAddressParameters.kt b/googlepay/src/main/java/com/adyen/checkout/googlepay/ShippingAddressParameters.kt index 133d6f2b5a..04722a1b7a 100644 --- a/googlepay/src/main/java/com/adyen/checkout/googlepay/ShippingAddressParameters.kt +++ b/googlepay/src/main/java/com/adyen/checkout/googlepay/ShippingAddressParameters.kt @@ -11,6 +11,7 @@ import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.JsonUtils.parseOptStringList import com.adyen.checkout.core.internal.data.model.JsonUtils.serializeOptStringList import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -50,7 +51,7 @@ data class ShippingAddressParameters( override fun deserialize(jsonObject: JSONObject) = ShippingAddressParameters( allowedCountryCodes = parseOptStringList(jsonObject.optJSONArray(ALLOWED_COUNTRY_CODES)), - isPhoneNumberRequired = jsonObject.optBoolean(PHONE_NUMBER_REQUIRED), + isPhoneNumberRequired = jsonObject.getBooleanOrNull(PHONE_NUMBER_REQUIRED) ?: false, ) } } diff --git a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/CardParameters.kt b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/CardParameters.kt index cf72f8d6c2..629fb15a84 100644 --- a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/CardParameters.kt +++ b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/CardParameters.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.core.internal.data.model.JsonUtils.serializeOptStringL import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils.deserializeOpt import com.adyen.checkout.core.internal.data.model.ModelUtils.serializeOpt +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull import com.adyen.checkout.googlepay.BillingAddressParameters import kotlinx.parcelize.Parcelize import org.json.JSONException @@ -51,7 +52,7 @@ internal data class CardParameters( putOpt(BILLING_ADDRESS_REQUIRED, modelObject.isBillingAddressRequired) putOpt( BILLING_ADDRESS_PARAMETERS, - serializeOpt(modelObject.billingAddressParameters, BillingAddressParameters.SERIALIZER) + serializeOpt(modelObject.billingAddressParameters, BillingAddressParameters.SERIALIZER), ) } } catch (e: JSONException) { @@ -62,13 +63,13 @@ internal data class CardParameters( override fun deserialize(jsonObject: JSONObject) = CardParameters( allowedAuthMethods = parseOptStringList(jsonObject.optJSONArray(ALLOWED_AUTH_METHODS)), allowedCardNetworks = parseOptStringList(jsonObject.optJSONArray(ALLOWED_CARD_NETWORKS)), - isAllowPrepaidCards = jsonObject.optBoolean(ALLOW_PREPAID_CARDS), - isAllowCreditCards = jsonObject.optBoolean(ALLOW_CREDIT_CARDS), - isAssuranceDetailsRequired = jsonObject.optBoolean(ASSURANCE_DETAILS_REQUIRED), - isBillingAddressRequired = jsonObject.optBoolean(BILLING_ADDRESS_REQUIRED), + isAllowPrepaidCards = jsonObject.getBooleanOrNull(ALLOW_PREPAID_CARDS) ?: false, + isAllowCreditCards = jsonObject.getBooleanOrNull(ALLOW_CREDIT_CARDS), + isAssuranceDetailsRequired = jsonObject.getBooleanOrNull(ASSURANCE_DETAILS_REQUIRED), + isBillingAddressRequired = jsonObject.getBooleanOrNull(BILLING_ADDRESS_REQUIRED) ?: false, billingAddressParameters = deserializeOpt( jsonObject.optJSONObject(BILLING_ADDRESS_PARAMETERS), - BillingAddressParameters.SERIALIZER + BillingAddressParameters.SERIALIZER, ), ) } diff --git a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/IsReadyToPayRequestModel.kt b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/IsReadyToPayRequestModel.kt index b383e211ad..c1f7bdc573 100644 --- a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/IsReadyToPayRequestModel.kt +++ b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/IsReadyToPayRequestModel.kt @@ -11,6 +11,8 @@ import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils.deserializeOptList import com.adyen.checkout.core.internal.data.model.ModelUtils.serializeOptList +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull +import com.adyen.checkout.core.internal.data.model.getIntOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -38,7 +40,7 @@ internal data class IsReadyToPayRequestModel( putOpt(API_VERSION_MINOR, modelObject.apiVersionMinor) putOpt( ALLOWED_PAYMENT_METHODS, - serializeOptList(modelObject.allowedPaymentMethods, GooglePayPaymentMethodModel.SERIALIZER) + serializeOptList(modelObject.allowedPaymentMethods, GooglePayPaymentMethodModel.SERIALIZER), ) putOpt(EXISTING_PAYMENT_METHOD_REQUIRED, modelObject.isExistingPaymentMethodRequired) } @@ -48,13 +50,14 @@ internal data class IsReadyToPayRequestModel( } override fun deserialize(jsonObject: JSONObject) = IsReadyToPayRequestModel( - apiVersion = jsonObject.optInt(API_VERSION), - apiVersionMinor = jsonObject.optInt(API_VERSION_MINOR), + apiVersion = jsonObject.getIntOrNull(API_VERSION) ?: 0, + apiVersionMinor = jsonObject.getIntOrNull(API_VERSION_MINOR) ?: 0, allowedPaymentMethods = deserializeOptList( jsonObject.optJSONArray(ALLOWED_PAYMENT_METHODS), - GooglePayPaymentMethodModel.SERIALIZER + GooglePayPaymentMethodModel.SERIALIZER, ), - isExistingPaymentMethodRequired = jsonObject.optBoolean(EXISTING_PAYMENT_METHOD_REQUIRED) + isExistingPaymentMethodRequired = jsonObject.getBooleanOrNull(EXISTING_PAYMENT_METHOD_REQUIRED) + ?: false, ) } } diff --git a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/PaymentDataRequestModel.kt b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/PaymentDataRequestModel.kt index 08b74268e7..acaa06eb12 100644 --- a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/PaymentDataRequestModel.kt +++ b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/data/model/PaymentDataRequestModel.kt @@ -13,6 +13,8 @@ import com.adyen.checkout.core.internal.data.model.ModelUtils.deserializeOpt import com.adyen.checkout.core.internal.data.model.ModelUtils.deserializeOptList import com.adyen.checkout.core.internal.data.model.ModelUtils.serializeOpt import com.adyen.checkout.core.internal.data.model.ModelUtils.serializeOptList +import com.adyen.checkout.core.internal.data.model.getBooleanOrNull +import com.adyen.checkout.core.internal.data.model.getIntOrNull import com.adyen.checkout.googlepay.MerchantInfo import com.adyen.checkout.googlepay.ShippingAddressParameters import kotlinx.parcelize.Parcelize @@ -51,17 +53,17 @@ internal data class PaymentDataRequestModel( putOpt(MERCHANT_INFO, serializeOpt(modelObject.merchantInfo, MerchantInfo.SERIALIZER)) putOpt( ALLOWED_PAYMENT_METHODS, - serializeOptList(modelObject.allowedPaymentMethods, GooglePayPaymentMethodModel.SERIALIZER) + serializeOptList(modelObject.allowedPaymentMethods, GooglePayPaymentMethodModel.SERIALIZER), ) putOpt( TRANSACTION_INFO, - serializeOpt(modelObject.transactionInfo, TransactionInfoModel.SERIALIZER) + serializeOpt(modelObject.transactionInfo, TransactionInfoModel.SERIALIZER), ) putOpt(EMAIL_REQUIRED, modelObject.isEmailRequired) putOpt(SHIPPING_ADDRESS_REQUIRED, modelObject.isShippingAddressRequired) putOpt( SHIPPING_ADDRESS_PARAMETERS, - serializeOpt(modelObject.shippingAddressParameters, ShippingAddressParameters.SERIALIZER) + serializeOpt(modelObject.shippingAddressParameters, ShippingAddressParameters.SERIALIZER), ) } } catch (e: JSONException) { @@ -71,25 +73,26 @@ internal data class PaymentDataRequestModel( override fun deserialize(jsonObject: JSONObject): PaymentDataRequestModel { val paymentDataRequestModel = PaymentDataRequestModel() - paymentDataRequestModel.apiVersion = jsonObject.optInt(API_VERSION) - paymentDataRequestModel.apiVersionMinor = jsonObject.optInt(API_VERSION_MINOR) + paymentDataRequestModel.apiVersion = jsonObject.getIntOrNull(API_VERSION) ?: 0 + paymentDataRequestModel.apiVersionMinor = jsonObject.getIntOrNull(API_VERSION_MINOR) ?: 0 paymentDataRequestModel.merchantInfo = deserializeOpt( jsonObject.optJSONObject(MERCHANT_INFO), - MerchantInfo.SERIALIZER + MerchantInfo.SERIALIZER, ) paymentDataRequestModel.allowedPaymentMethods = deserializeOptList( jsonObject.optJSONArray(ALLOWED_PAYMENT_METHODS), - GooglePayPaymentMethodModel.SERIALIZER + GooglePayPaymentMethodModel.SERIALIZER, ) paymentDataRequestModel.transactionInfo = deserializeOpt( jsonObject.optJSONObject(TRANSACTION_INFO), - TransactionInfoModel.SERIALIZER + TransactionInfoModel.SERIALIZER, ) - paymentDataRequestModel.isEmailRequired = jsonObject.optBoolean(EMAIL_REQUIRED) - paymentDataRequestModel.isShippingAddressRequired = jsonObject.optBoolean(SHIPPING_ADDRESS_REQUIRED) + paymentDataRequestModel.isEmailRequired = jsonObject.getBooleanOrNull(EMAIL_REQUIRED) ?: false + paymentDataRequestModel.isShippingAddressRequired = + jsonObject.getBooleanOrNull(SHIPPING_ADDRESS_REQUIRED) ?: false paymentDataRequestModel.shippingAddressParameters = deserializeOpt( jsonObject.optJSONObject(SHIPPING_ADDRESS_PARAMETERS), - ShippingAddressParameters.SERIALIZER + ShippingAddressParameters.SERIALIZER, ) return paymentDataRequestModel } diff --git a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/util/GooglePayUtils.kt b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/util/GooglePayUtils.kt index 64eccaa025..990cc45d51 100644 --- a/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/util/GooglePayUtils.kt +++ b/googlepay/src/main/java/com/adyen/checkout/googlepay/internal/util/GooglePayUtils.kt @@ -143,7 +143,7 @@ internal object GooglePayUtils { val tokenizationDataJson = paymentMethodDataJson.getJSONObject(TOKENIZATION_DATA) googlePayToken = tokenizationDataJson.getString(TOKEN) val infoJson = paymentMethodDataJson.optJSONObject(INFO) - if (infoJson != null && infoJson.has(CARD_NETWORK)) { + if (infoJson != null && !infoJson.isNull(CARD_NETWORK)) { googlePayCardNetwork = infoJson.getString(CARD_NETWORK) } } catch (e: JSONException) { diff --git a/lint/src/main/java/com/adyen/checkout/lint/JSONOptFunctions.kt b/lint/src/main/java/com/adyen/checkout/lint/JSONOptFunctions.kt new file mode 100644 index 0000000000..de8ca2af51 --- /dev/null +++ b/lint/src/main/java/com/adyen/checkout/lint/JSONOptFunctions.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 Adyen N.V. + * + * This file is open source and available under the MIT license. See the LICENSE file for more info. + * + * Created by oscars on 14/8/2024. + */ + +package com.adyen.checkout.lint + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.intellij.psi.PsiMethod +import org.jetbrains.uast.UCallExpression + +internal val JSON_OPT_FUNCTIONS_ISSUE = Issue.create( + id = "JSONOptFunctions", + briefDescription = "JSONObject \"opt\" functions should not be used directly", + explanation = """ + JSONObject's optString, optBoolean, optInt, optLong and optDouble functions are non nullable and return + arbitrary default values which could cause unexpected bugs. Use an internal extension function that returns + null instead. + """.trimIndent().replace(Regex("(\n*)\n"), "$1"), + implementation = Implementation(JSONOptFunctionsDetector::class.java, Scope.JAVA_FILE_SCOPE), + category = Category.CUSTOM_LINT_CHECKS, + priority = 5, + severity = Severity.ERROR, + androidSpecific = true, +) + +internal class JSONOptFunctionsDetector : Detector(), Detector.UastScanner { + + override fun getApplicableMethodNames(): List = listOf( + "optString", "optBoolean", "optInt", "optLong", "optDouble", + ) + + override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { + if (!context.evaluator.isMemberInClass(method, "org.json.JSONObject")) return + val methodName = node.methodIdentifier?.name.orEmpty() + val replacement = when (methodName) { + "optString" -> "getStringOrNull" + "optBoolean" -> "getBooleanOrNull" + "optInt" -> "getIntOrNull" + "optLong" -> "getLongOrNull" + "optDouble" -> "getDoubleOrNull" + else -> return + } + context.report( + JSON_OPT_FUNCTIONS_ISSUE, + node, + context.getLocation(node.methodIdentifier), + "JSONObject.$methodName should not be used directly. Use an internal extension function instead.", + fix() + .alternatives( + // this replacement does not compile when 2 arguments are passed to the opt functions instead of 1. + // however, it's easy for the developer to fix it manually + fix() + .replace() + .all() + .with(replacement) + .imports("com.adyen.checkout.core.internal.data.model.$replacement") + .reformat(true) + .shortenNames() + .build(), + ), + ) + } +} diff --git a/lint/src/main/java/com/adyen/checkout/lint/LintIssueRegistry.kt b/lint/src/main/java/com/adyen/checkout/lint/LintIssueRegistry.kt index 664187418c..7597f92cf5 100644 --- a/lint/src/main/java/com/adyen/checkout/lint/LintIssueRegistry.kt +++ b/lint/src/main/java/com/adyen/checkout/lint/LintIssueRegistry.kt @@ -22,5 +22,6 @@ internal class LintIssueRegistry : IssueRegistry() { NOT_ADYEN_LOG_ISSUE, OBJECT_IN_PUBLIC_SEALED_CLASS_ISSUE, TEXT_IN_LAYOUT_XML_ISSUE, + JSON_OPT_FUNCTIONS_ISSUE, ) } diff --git a/lint/src/test/java/com/adyen/checkout/lint/JSONOptFunctionsTest.kt b/lint/src/test/java/com/adyen/checkout/lint/JSONOptFunctionsTest.kt new file mode 100644 index 0000000000..eb9142d568 --- /dev/null +++ b/lint/src/test/java/com/adyen/checkout/lint/JSONOptFunctionsTest.kt @@ -0,0 +1,193 @@ +package com.adyen.checkout.lint + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest.java +import com.android.tools.lint.checks.infrastructure.LintDetectorTest.kotlin +import com.android.tools.lint.checks.infrastructure.TestLintTask.lint +import org.junit.Test + +class JSONOptFunctionsTest { + + @Test + fun whenJSONObjectOptFunctionsAreUsed_thenIssueIsDetected() { + lint() + .files( + JSON_OBJECT_STUB, + kotlin( + """ + package test + + import org.json.JSONObject + + class SomeClass { + fun someFun(jsonObject: JSONObject) { + val stringWithoutFallback = jsonObject.optString("key") + val stringWithFallback = jsonObject.optString("key", "fallback") + val intWithoutFallback = jsonObject.optInt("key") + val intWithFallback = jsonObject.optInt("key", 1) + val doubleWithoutFallback = jsonObject.optDouble("key") + val doubleWithFallback = jsonObject.optDouble("key", 1.0) + val longWithoutFallback = jsonObject.optLong("key") + val longWithFallback = jsonObject.optLong("key", 1L) + val booleanWithoutFallback = jsonObject.optBoolean("key") + val booleanWithFallback = jsonObject.optBoolean("key", true) + } + } + """.trimIndent(), + ), + ) + .issues(JSON_OPT_FUNCTIONS_ISSUE) + .allowMissingSdk() + .run() + .expect( + """ +src/test/SomeClass.kt:7: Error: JSONObject.optString should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val stringWithoutFallback = jsonObject.optString("key") + ~~~~~~~~~ +src/test/SomeClass.kt:8: Error: JSONObject.optString should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val stringWithFallback = jsonObject.optString("key", "fallback") + ~~~~~~~~~ +src/test/SomeClass.kt:9: Error: JSONObject.optInt should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val intWithoutFallback = jsonObject.optInt("key") + ~~~~~~ +src/test/SomeClass.kt:10: Error: JSONObject.optInt should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val intWithFallback = jsonObject.optInt("key", 1) + ~~~~~~ +src/test/SomeClass.kt:11: Error: JSONObject.optDouble should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val doubleWithoutFallback = jsonObject.optDouble("key") + ~~~~~~~~~ +src/test/SomeClass.kt:12: Error: JSONObject.optDouble should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val doubleWithFallback = jsonObject.optDouble("key", 1.0) + ~~~~~~~~~ +src/test/SomeClass.kt:13: Error: JSONObject.optLong should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val longWithoutFallback = jsonObject.optLong("key") + ~~~~~~~ +src/test/SomeClass.kt:14: Error: JSONObject.optLong should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val longWithFallback = jsonObject.optLong("key", 1L) + ~~~~~~~ +src/test/SomeClass.kt:15: Error: JSONObject.optBoolean should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val booleanWithoutFallback = jsonObject.optBoolean("key") + ~~~~~~~~~~ +src/test/SomeClass.kt:16: Error: JSONObject.optBoolean should not be used directly. Use an internal extension function instead. [JSONOptFunctions] + val booleanWithFallback = jsonObject.optBoolean("key", true) + ~~~~~~~~~~ +10 errors, 0 warnings + """.trimIndent(), + ) + .expectFixDiffs( + """ +Fix for src/test/SomeClass.kt line 7: Replace with getStringOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getStringOrNull +@@ -7 +8 +- val stringWithoutFallback = jsonObject.optString("key") ++ val stringWithoutFallback = jsonObject.getStringOrNull("key") +Fix for src/test/SomeClass.kt line 8: Replace with getStringOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getStringOrNull +@@ -8 +9 +- val stringWithFallback = jsonObject.optString("key", "fallback") ++ val stringWithFallback = jsonObject.getStringOrNull("key", "fallback") +Fix for src/test/SomeClass.kt line 9: Replace with getIntOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getIntOrNull +@@ -9 +10 +- val intWithoutFallback = jsonObject.optInt("key") ++ val intWithoutFallback = jsonObject.getIntOrNull("key") +Fix for src/test/SomeClass.kt line 10: Replace with getIntOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getIntOrNull +@@ -10 +11 +- val intWithFallback = jsonObject.optInt("key", 1) ++ val intWithFallback = jsonObject.getIntOrNull("key", 1) +Fix for src/test/SomeClass.kt line 11: Replace with getDoubleOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getDoubleOrNull +@@ -11 +12 +- val doubleWithoutFallback = jsonObject.optDouble("key") ++ val doubleWithoutFallback = jsonObject.getDoubleOrNull("key") +Fix for src/test/SomeClass.kt line 12: Replace with getDoubleOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getDoubleOrNull +@@ -12 +13 +- val doubleWithFallback = jsonObject.optDouble("key", 1.0) ++ val doubleWithFallback = jsonObject.getDoubleOrNull("key", 1.0) +Fix for src/test/SomeClass.kt line 13: Replace with getLongOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getLongOrNull +@@ -13 +14 +- val longWithoutFallback = jsonObject.optLong("key") ++ val longWithoutFallback = jsonObject.getLongOrNull("key") +Fix for src/test/SomeClass.kt line 14: Replace with getLongOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getLongOrNull +@@ -14 +15 +- val longWithFallback = jsonObject.optLong("key", 1L) ++ val longWithFallback = jsonObject.getLongOrNull("key", 1L) +Fix for src/test/SomeClass.kt line 15: Replace with getBooleanOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getBooleanOrNull +@@ -15 +16 +- val booleanWithoutFallback = jsonObject.optBoolean("key") ++ val booleanWithoutFallback = jsonObject.getBooleanOrNull("key") +Fix for src/test/SomeClass.kt line 16: Replace with getBooleanOrNull: +@@ -3 +3 ++ import com.adyen.checkout.core.internal.data.model.getBooleanOrNull +@@ -16 +17 +- val booleanWithFallback = jsonObject.optBoolean("key", true) ++ val booleanWithFallback = jsonObject.getBooleanOrNull("key", true) + """.trimIndent(), + ) + } + + companion object { + + private val JSON_OBJECT_STUB = java( + """ + package org.json; + + public class JSONObject { + + @NonNull public String optString(@Nullable String name) { + return "stub"; + } + + @NonNull public String optString(@Nullable String name, @NonNull String fallback) { + return "stub"; + } + + public int optInt(@Nullable String name) { + return 0; + } + + public int optInt(@Nullable String name, int fallback) { + return 0; + } + + public long optLong(@Nullable String name) { + return 0L; + } + + public long optLong(@Nullable String name, long fallback) { + return 0L; + } + + public double optDouble(@Nullable String name) { + return Double.NaN; + } + + public double optDouble(@Nullable String name, double fallback) { + return Double.NaN; + } + + public boolean optBoolean(@Nullable String name) { + return false; + } + + public boolean optBoolean(@Nullable String name, boolean fallback) { + return false; + } + } + """.trimIndent(), + ) + } +} diff --git a/redirect/src/main/java/com/adyen/checkout/redirect/internal/ui/DefaultRedirectDelegate.kt b/redirect/src/main/java/com/adyen/checkout/redirect/internal/ui/DefaultRedirectDelegate.kt index c9b438fbd3..de0baabdc1 100644 --- a/redirect/src/main/java/com/adyen/checkout/redirect/internal/ui/DefaultRedirectDelegate.kt +++ b/redirect/src/main/java/com/adyen/checkout/redirect/internal/ui/DefaultRedirectDelegate.kt @@ -31,6 +31,7 @@ import com.adyen.checkout.core.exception.CheckoutException import com.adyen.checkout.core.exception.ComponentException import com.adyen.checkout.core.exception.HttpException import com.adyen.checkout.core.exception.ModelSerializationException +import com.adyen.checkout.core.internal.data.model.getStringOrNull import com.adyen.checkout.core.internal.util.adyenLog import com.adyen.checkout.redirect.internal.data.api.NativeRedirectService import com.adyen.checkout.redirect.internal.data.model.NativeRedirectRequest @@ -171,7 +172,7 @@ constructor( coroutineScope.launch { val request = NativeRedirectRequest( redirectData = nativeRedirectData, - returnQueryString = details.optString(RETURN_URL_QUERY_STRING_PARAMETER), + returnQueryString = details.getStringOrNull(RETURN_URL_QUERY_STRING_PARAMETER).orEmpty(), ) try { val response = nativeRedirectService.makeNativeRedirect(request, componentParams.clientKey) diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionModel.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionModel.kt index 18a85beb1e..50eb5b0bdb 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionModel.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionModel.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.sessions.core import com.adyen.checkout.components.core.PaymentMethodsApiResponse import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -43,8 +44,8 @@ data class SessionModel( override fun deserialize(jsonObject: JSONObject): SessionModel { return SessionModel( - id = jsonObject.optString(ID), - sessionData = jsonObject.optString(SESSION_DATA) + id = jsonObject.getStringOrNull(ID).orEmpty(), + sessionData = jsonObject.getStringOrNull(SESSION_DATA) ) } } diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupConfiguration.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupConfiguration.kt index 74cfa2f6be..f985ec6f23 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupConfiguration.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupConfiguration.kt @@ -52,7 +52,7 @@ data class SessionSetupConfiguration( return try { SessionSetupConfiguration( enableStoreDetails = jsonObject.getBooleanOrNull(ENABLE_STORE_DETAILS), - showInstallmentAmount = jsonObject.optBoolean(SHOW_INSTALLMENT_AMOUNT), + showInstallmentAmount = jsonObject.getBooleanOrNull(SHOW_INSTALLMENT_AMOUNT) ?: false, installmentOptions = jsonObject.optJSONObject(INSTALLMENT_OPTIONS) ?.jsonToMap(SessionSetupInstallmentOptions.SERIALIZER), showRemovePaymentMethodButton = jsonObject.getBooleanOrNull(SHOW_REMOVE_PAYMENT_METHOD_BUTTON), diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupInstallmentOptions.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupInstallmentOptions.kt index e7f197b4d9..69f1589663 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupInstallmentOptions.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupInstallmentOptions.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.sessions.core import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.JsonUtils import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getIntOrNull import com.adyen.checkout.core.internal.data.model.optIntList import com.adyen.checkout.core.internal.data.model.optStringList import kotlinx.parcelize.Parcelize @@ -48,7 +49,7 @@ data class SessionSetupInstallmentOptions( return try { SessionSetupInstallmentOptions( plans = jsonObject.optStringList(PLANS).orEmpty(), - preselectedValue = jsonObject.optInt(PRESELECTED_VALUE), + preselectedValue = jsonObject.getIntOrNull(PRESELECTED_VALUE), values = jsonObject.optIntList(VALUES) ) } catch (e: JSONException) { diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupResponse.kt index ed32a60092..2fad56cee6 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/SessionSetupResponse.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.components.core.PaymentMethodsApiResponse import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -70,20 +71,20 @@ data class SessionSetupResponse( override fun deserialize(jsonObject: JSONObject): SessionSetupResponse { return try { SessionSetupResponse( - id = jsonObject.optString(ID), - sessionData = jsonObject.optString(SESSION_DATA), + id = jsonObject.getStringOrNull(ID).orEmpty(), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), amount = ModelUtils.deserializeOpt(jsonObject.optJSONObject(AMOUNT), Amount.SERIALIZER), - expiresAt = jsonObject.optString(EXPIRES_AT), + expiresAt = jsonObject.getStringOrNull(EXPIRES_AT).orEmpty(), paymentMethodsApiResponse = ModelUtils.deserializeOpt( jsonObject.optJSONObject(PAYMENT_METHODS), PaymentMethodsApiResponse.SERIALIZER ), - returnUrl = jsonObject.optString(RETURN_URL), + returnUrl = jsonObject.getStringOrNull(RETURN_URL), configuration = ModelUtils.deserializeOpt( jsonObject.optJSONObject(CONFIGURATION), SessionSetupConfiguration.SERIALIZER ), - shopperLocale = jsonObject.optString(SHOPPER_LOCALE), + shopperLocale = jsonObject.getStringOrNull(SHOPPER_LOCALE), ) } catch (e: JSONException) { throw ModelSerializationException(SessionSetupResponse::class.java, e) diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceRequest.kt index 2b27cc96be..3652db5235 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceRequest.kt @@ -14,6 +14,7 @@ import com.adyen.checkout.components.core.paymentmethod.PaymentMethodDetails import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -57,7 +58,7 @@ data class SessionBalanceRequest( override fun deserialize(jsonObject: JSONObject): SessionBalanceRequest { return try { SessionBalanceRequest( - sessionData = jsonObject.optString(SESSION_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), paymentMethod = ModelUtils.deserializeOpt( jsonObject.optJSONObject(PAYMENT_METHOD), PaymentMethodDetails.SERIALIZER diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceResponse.kt index d64bd628b3..0a54d9e078 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionBalanceResponse.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.core.exception.CheckoutException import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -49,7 +50,7 @@ data class SessionBalanceResponse( override fun deserialize(jsonObject: JSONObject): SessionBalanceResponse { return SessionBalanceResponse( - sessionData = jsonObject.optString(SESSION_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), balance = ModelUtils.deserializeOpt(jsonObject.optJSONObject(BALANCE), Amount.SERIALIZER) ?: throw CheckoutException("Balance not found"), transactionLimit = ModelUtils.deserializeOpt( diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderRequest.kt index 32bf12a9bc..55199dddae 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderRequest.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.components.core.OrderRequest import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -44,7 +45,7 @@ data class SessionCancelOrderRequest( override fun deserialize(jsonObject: JSONObject): SessionCancelOrderRequest { return try { SessionCancelOrderRequest( - sessionData = jsonObject.optString(SESSION_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), order = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ORDER), OrderRequest.SERIALIZER) ) } catch (e: JSONException) { diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderResponse.kt index 25cb081912..639c643dce 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionCancelOrderResponse.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.sessions.core.internal.data.model import androidx.annotation.RestrictTo import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -40,8 +41,8 @@ data class SessionCancelOrderResponse( override fun deserialize(jsonObject: JSONObject): SessionCancelOrderResponse { return SessionCancelOrderResponse( - sessionData = jsonObject.optString(SESSION_DATA), - status = jsonObject.optString(STATUS) + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), + status = jsonObject.getStringOrNull(STATUS) ) } } diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsRequest.kt index 868e8b86a7..453b63a17d 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsRequest.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.sessions.core.internal.data.model import androidx.annotation.RestrictTo import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import com.adyen.checkout.core.internal.util.JSONObjectParceler import kotlinx.parcelize.Parcelize import kotlinx.parcelize.WriteWith @@ -47,8 +48,8 @@ data class SessionDetailsRequest( override fun deserialize(jsonObject: JSONObject): SessionDetailsRequest { return try { SessionDetailsRequest( - sessionData = jsonObject.optString(SESSION_DATA), - paymentData = jsonObject.optString(PAYMENT_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), + paymentData = jsonObject.getStringOrNull(PAYMENT_DATA), details = jsonObject.optJSONObject(DETAILS) ) } catch (e: JSONException) { diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsResponse.kt index 35c742e86e..e87790414a 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDetailsResponse.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.components.core.action.Action import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -55,11 +56,11 @@ data class SessionDetailsResponse( override fun deserialize(jsonObject: JSONObject): SessionDetailsResponse { return SessionDetailsResponse( - sessionData = jsonObject.optString(SESSION_DATA), - status = jsonObject.optString(STATUS), - resultCode = jsonObject.optString(RESULT_CODE), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), + status = jsonObject.getStringOrNull(STATUS), + resultCode = jsonObject.getStringOrNull(RESULT_CODE), action = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ACTION), Action.SERIALIZER), - sessionResult = jsonObject.optString(SESSION_RESULT), + sessionResult = jsonObject.getStringOrNull(SESSION_RESULT), order = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ORDER), OrderResponse.SERIALIZER), ) } diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenRequest.kt index cce3a5b34b..235be2540a 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenRequest.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.sessions.core.internal.data.model import androidx.annotation.RestrictTo import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -41,8 +42,8 @@ data class SessionDisableTokenRequest( override fun deserialize(jsonObject: JSONObject): SessionDisableTokenRequest { return try { SessionDisableTokenRequest( - sessionData = jsonObject.optString(SESSION_DATA), - storedPaymentMethodId = jsonObject.optString(STORED_PAYMENT_METHOD_ID), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), + storedPaymentMethodId = jsonObject.getStringOrNull(STORED_PAYMENT_METHOD_ID).orEmpty(), ) } catch (e: JSONException) { throw ModelSerializationException(SessionDisableTokenRequest::class.java, e) diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenResponse.kt index e0fe3c37d1..51e3bcc845 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionDisableTokenResponse.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.sessions.core.internal.data.model import androidx.annotation.RestrictTo import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -38,7 +39,7 @@ data class SessionDisableTokenResponse( override fun deserialize(jsonObject: JSONObject): SessionDisableTokenResponse { return try { SessionDisableTokenResponse( - sessionData = jsonObject.optString(SESSION_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), ) } catch (e: JSONException) { throw ModelSerializationException(SessionDisableTokenResponse::class.java, e) diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderRequest.kt index c6d04dc87e..46c3993525 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderRequest.kt @@ -11,6 +11,7 @@ package com.adyen.checkout.sessions.core.internal.data.model import androidx.annotation.RestrictTo import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -39,7 +40,7 @@ data class SessionOrderRequest( override fun deserialize(jsonObject: JSONObject): SessionOrderRequest { return try { SessionOrderRequest( - sessionData = jsonObject.optString(SESSION_DATA) + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), ) } catch (e: JSONException) { throw ModelSerializationException(SessionOrderRequest::class.java, e) diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderResponse.kt index 63f7f0ca49..08913c2b24 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionOrderResponse.kt @@ -10,6 +10,7 @@ package com.adyen.checkout.sessions.core.internal.data.model import androidx.annotation.RestrictTo import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -43,9 +44,9 @@ data class SessionOrderResponse( override fun deserialize(jsonObject: JSONObject): SessionOrderResponse { return SessionOrderResponse( - sessionData = jsonObject.optString(SESSION_DATA), - orderData = jsonObject.optString(ORDER_DATA), - pspReference = jsonObject.optString(PSP_REFERENCE) + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), + orderData = jsonObject.getStringOrNull(ORDER_DATA).orEmpty(), + pspReference = jsonObject.getStringOrNull(PSP_REFERENCE).orEmpty(), ) } } diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsRequest.kt index 40bf1b5a22..ecabdfa241 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsRequest.kt @@ -14,6 +14,7 @@ import com.adyen.checkout.components.core.paymentmethod.PaymentMethodDetails import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -45,7 +46,7 @@ data class SessionPaymentsRequest( override fun deserialize(jsonObject: JSONObject): SessionPaymentsRequest { return try { SessionPaymentsRequest( - sessionData = jsonObject.optString(SESSION_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), paymentComponentData = ModelUtils.deserializeOpt( jsonObject, PaymentComponentData.SERIALIZER diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsResponse.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsResponse.kt index 88ea349dd2..5422b4fff7 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsResponse.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionPaymentsResponse.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.components.core.action.Action import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -55,12 +56,12 @@ data class SessionPaymentsResponse( override fun deserialize(jsonObject: JSONObject): SessionPaymentsResponse { return SessionPaymentsResponse( - sessionData = jsonObject.optString(SESSION_DATA), - status = jsonObject.optString(STATUS), - resultCode = jsonObject.optString(RESULT_CODE), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), + status = jsonObject.getStringOrNull(STATUS), + resultCode = jsonObject.getStringOrNull(RESULT_CODE), action = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ACTION), Action.SERIALIZER), order = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ORDER), OrderResponse.SERIALIZER), - sessionResult = jsonObject.optString(SESSION_RESULT), + sessionResult = jsonObject.getStringOrNull(SESSION_RESULT), ) } } diff --git a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionSetupRequest.kt b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionSetupRequest.kt index 0cfcc692cb..b92aaea3b5 100644 --- a/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionSetupRequest.kt +++ b/sessions-core/src/main/java/com/adyen/checkout/sessions/core/internal/data/model/SessionSetupRequest.kt @@ -13,6 +13,7 @@ import com.adyen.checkout.components.core.OrderRequest import com.adyen.checkout.core.exception.ModelSerializationException import com.adyen.checkout.core.internal.data.model.ModelObject import com.adyen.checkout.core.internal.data.model.ModelUtils +import com.adyen.checkout.core.internal.data.model.getStringOrNull import kotlinx.parcelize.Parcelize import org.json.JSONException import org.json.JSONObject @@ -44,7 +45,7 @@ data class SessionSetupRequest( override fun deserialize(jsonObject: JSONObject): SessionSetupRequest { return try { SessionSetupRequest( - sessionData = jsonObject.optString(SESSION_DATA), + sessionData = jsonObject.getStringOrNull(SESSION_DATA).orEmpty(), order = ModelUtils.deserializeOpt(jsonObject.optJSONObject(ORDER), OrderRequest.SERIALIZER) ) } catch (e: JSONException) {