Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ public enum class ApiPaymentMethodType {
@SerialName(value = "cash")
CASH,

@SerialName(value = "psp_provided")
PSP_PROVIDED,

@SerialName(value = "stripe")
STRIPE,

Expand All @@ -37,7 +34,6 @@ internal object ApiPaymentMethodTypeSerializer : KSerializer<ApiPaymentMethodTyp

override fun deserialize(decoder: Decoder): ApiPaymentMethodType = when (decoder.decodeString()) {
"cash" -> ApiPaymentMethodType.CASH
"psp_provided" -> ApiPaymentMethodType.PSP_PROVIDED
"stripe" -> ApiPaymentMethodType.STRIPE
"logpay" -> ApiPaymentMethodType.LOGPAY
"public_transport_ticket" -> ApiPaymentMethodType.PUBLIC_TRANSPORT_TICKET
Expand All @@ -50,7 +46,6 @@ internal object ApiPaymentMethodTypeSerializer : KSerializer<ApiPaymentMethodTyp
encoder.encodeString(
when (value) {
ApiPaymentMethodType.CASH -> "cash"
ApiPaymentMethodType.PSP_PROVIDED -> "psp_provided"
ApiPaymentMethodType.STRIPE -> "stripe"
ApiPaymentMethodType.LOGPAY -> "logpay"
ApiPaymentMethodType.PUBLIC_TRANSPORT_TICKET -> "public_transport_ticket"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
package com.ioki.passenger.api.models

import com.ioki.passenger.api.models.ApiProvider.PaymentMethodType
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonContentPolymorphicSerializer
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive

@Serializable
public data class ApiProvider(
val name: String,
@SerialName(value = "psp")
val paymentServiceProvider: PaymentServiceProvider,
@SerialName(value = "payment_service_provider") val paymentServiceProvider: PaymentServiceProvider?,
@SerialName(value = "ride_payment_method_types")
val ridePaymentMethodTypes: Set<ApiPaymentMethodType>,
val ridePaymentMethodTypes: Set<PaymentMethodType>,
@SerialName(value = "ticketing_payment_method_types")
val ticketingPaymentMethodTypes: Set<ApiPaymentMethodType>,
val ticketingPaymentMethodTypes: Set<PaymentMethodType>,
@SerialName(value = "service_credit_payment_method_types")
val serviceCreditPaymentMethodTypes: Set<ApiPaymentMethodType>,
val serviceCreditPaymentMethodTypes: Set<PaymentMethodType>,
@SerialName(value = "personal_discount_payment_method_types")
val personalDiscountPaymentMethodTypes: Set<ApiPaymentMethodType>,
val personalDiscountPaymentMethodTypes: Set<PaymentMethodType>,
@SerialName(value = "tip_payment_method_types")
val tipPaymentMethodTypes: Set<ApiPaymentMethodType>,
@SerialName(value = "stripe_payment_method_types")
val stripeTypes: Set<ApiStripeType>?,
@SerialName(value = "logpay_payment_method_types")
val logPayTypes: Set<ApiLogPayType>?,
val tipPaymentMethodTypes: Set<PaymentMethodType>,
@SerialName(value = "service_credit_options") val creditOptions: CreditOptions?,
@SerialName(value = "stripe_account_id") val stripeAccountId: String?,
@SerialName(value = "merchant_name") val merchantName: String?,
@SerialName(value = "country_code") val countryCode: String,
val features: Features,
Expand All @@ -38,18 +42,6 @@ public data class ApiProvider(
@Serializable
public data class CreditOptions(val packages: List<ApiOfferedCreditPackage>)

@Serializable
public enum class PaymentServiceProvider {
@SerialName(value = "no_psp")
NONE,

@SerialName(value = "logpay")
LOGPAY,

@SerialName(value = "stripe")
STRIPE,
}

@Serializable
public data class Features(
@SerialName(value = "payment") val paymentEnabled: Boolean,
Expand Down Expand Up @@ -111,14 +103,104 @@ public data class ApiProvider(
)
}
}

@Serializable(with = PaymentMethodTypeSerializer::class)
public enum class PaymentMethodType {
@SerialName(value = "cash")
CASH,

@SerialName(value = "psp_provided")
PSP_PROVIDED,

@SerialName(value = "public_transport_ticket")
PUBLIC_TRANSPORT_TICKET,

@SerialName(value = "service_credits")
SERVICE_CREDITS,

@SerialName(value = "pos_payment")
POS_PAYMENT,
UNSUPPORTED,
}
}

internal object PaymentMethodTypeSerializer : KSerializer<PaymentMethodType> {
override val descriptor = String.serializer().descriptor

override fun deserialize(decoder: Decoder): PaymentMethodType = when (decoder.decodeString()) {
"cash" -> PaymentMethodType.CASH
"psp_provided" -> PaymentMethodType.PSP_PROVIDED
"public_transport_ticket" -> PaymentMethodType.PUBLIC_TRANSPORT_TICKET
"service_credits" -> PaymentMethodType.SERVICE_CREDITS
"pos_payment" -> PaymentMethodType.POS_PAYMENT
else -> PaymentMethodType.UNSUPPORTED
}

override fun serialize(encoder: Encoder, value: PaymentMethodType) {
encoder.encodeString(
when (value) {
PaymentMethodType.CASH -> "cash"
PaymentMethodType.PSP_PROVIDED -> "psp_provided"
PaymentMethodType.PUBLIC_TRANSPORT_TICKET -> "public_transport_ticket"
PaymentMethodType.SERVICE_CREDITS -> "service_credits"
PaymentMethodType.POS_PAYMENT -> "pos_payment"
PaymentMethodType.UNSUPPORTED -> "unsupported"
},
)
}
}

public val ApiProvider.Features.permissionCenterEnabled: Boolean
get() = analyticsTracking || marketingAutomation || newsletterEnabled || receiptsEnabled

public val ApiProvider.allPaymentMethodTypes: Set<ApiPaymentMethodType>
public val ApiProvider.allPaymentMethodTypes: Set<PaymentMethodType>
get() =
ridePaymentMethodTypes +
serviceCreditPaymentMethodTypes +
personalDiscountPaymentMethodTypes +
tipPaymentMethodTypes

internal object PaymentServiceProviderSerializer : JsonContentPolymorphicSerializer<PaymentServiceProvider>(
PaymentServiceProvider::class,
) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<PaymentServiceProvider> {
val jsonObject = element.jsonObject
val type = jsonObject.getValue("type").jsonPrimitive.content
return when (type) {
Comment thread
StefMa marked this conversation as resolved.
Outdated
"payment_service_provider/stripe" -> PaymentServiceProvider.Stripe.serializer()
"payment_service_provider/logpay" -> PaymentServiceProvider.LogPay.serializer()
else -> throw IllegalArgumentException("Unsupported PaymentServiceProvider type.")
Comment thread
StefMa marked this conversation as resolved.
Outdated
}
}
}

@Serializable(PaymentServiceProviderSerializer::class)
public sealed class PaymentServiceProvider {
public abstract val type: Type
Comment thread
elmira-y marked this conversation as resolved.
Outdated

@Serializable
public data class Stripe(
@SerialName(value = "stripe_account_id") val stripeAccountId: String?,
@SerialName(value = "stripe_payment_method_types") val stripeTypes: List<ApiStripeType>?,
@SerialName(value = "google_pay_supported") val googlePaySupported: Boolean,
) : PaymentServiceProvider() {
override val type: Type = Type.STRIPE
}

@Serializable
public data class LogPay(
@SerialName(value = "logpay_payment_method_types") val logPayTypes: List<ApiLogPayType>?,
@SerialName(value = "use_legacy_paypal_flow") val useLegacyPaypalFlow: Boolean,
) : PaymentServiceProvider() {
override val type: Type = Type.LOGPAY
}

@Serializable
public enum class Type {
@SerialName(value = "payment_service_provider/logpay")
LOGPAY,

@SerialName(value = "payment_service_provider/stripe")
STRIPE,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ public enum class ApiStripeType {
@SerialName(value = "sepa_debit")
SEPA_DEBIT,

@SerialName(value = "google_pay")
GOOGLE_PAY,
UNSUPPORTED,
}

Expand All @@ -28,7 +26,6 @@ internal object ApiStripeTypeSerializer : KSerializer<ApiStripeType> {
when (value) {
ApiStripeType.CARD -> "card"
ApiStripeType.SEPA_DEBIT -> "sepa_debit"
ApiStripeType.GOOGLE_PAY -> "google_pay"
ApiStripeType.UNSUPPORTED -> "unsupported"
},
)
Expand All @@ -37,7 +34,6 @@ internal object ApiStripeTypeSerializer : KSerializer<ApiStripeType> {
override fun deserialize(decoder: Decoder): ApiStripeType = when (decoder.decodeString()) {
"card" -> ApiStripeType.CARD
"sepa_debit" -> ApiStripeType.SEPA_DEBIT
"google_pay" -> ApiStripeType.GOOGLE_PAY
else -> ApiStripeType.UNSUPPORTED
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
package com.ioki.passenger.api.models

import com.ioki.passenger.api.test.models.createApiBootstrapResponse
import com.ioki.passenger.api.test.models.createApiClientInfoResponse
import com.ioki.passenger.api.test.models.createApiProvider
import kotlin.test.Test

internal class ApiBootstrapResponseTest : IokiApiModelTest() {
@Test
fun serializationMinimal() {
testJsonStringCanBeConvertedToModel(
createApiBootstrapResponse(
provider = createApiProvider(
name = "Some Company Inc.",
countryCode = "DE",
features = ApiProvider.Features.NONE,
),
client = createApiClientInfoResponse(
distributionUrl = "url",
termsOfServiceUrl = "https://example.com/terms_of_service.html",
privacyPolicyUrl = "https://example.com/privacy_policy.html",
imprintUrl = "https://example.com/imprint_url.html",
phoneNumberRequired = false,
emailAddressRequired = false,
),
products = emptyList(),
ridesWithFailedPayments = emptyList(),
renewableTicketingVouchers = emptyList(),
productSupportUris = emptyList(),
),
bootstrapMinimal,
)
}

@Test
fun serialization() {
testJsonStringCanBeConvertedToModel(
ApiBootstrapResponse(
createApiBootstrapResponse(
provider = createApiProvider(
name = "Some Company Inc.",
countryCode = "DE",
paymentServiceProvider = ApiProvider.PaymentServiceProvider.NONE,
features = ApiProvider.Features.NONE,
),
client = createApiClientInfoResponse(
Expand All @@ -33,13 +59,56 @@ internal class ApiBootstrapResponseTest : IokiApiModelTest() {
}
}

private val bootstrapMinimal =
"""
{
"provider": {
"name": "Some Company Inc.",
"country_code": "DE",
"ride_payment_method_types": [],
"ticketing_payment_method_types": [],
"service_credit_payment_method_types": [],
"personal_discount_payment_method_types": [],
"tip_payment_method_types": [],
"custom_urls": [],
"features": {
"non_purchasable_personal_discounts" : false,
"payment":false,
"promo_codes" : false,
"purchasable_personal_discounts" : false,
"service_credits" : false,
"analytics_tracking" : false,
"user_email_required" : false,
"marketing_automation": false,
"newsletter": false,
"receipts": false,
"apply_for_non_purchasable_personal_discounts": false,
"tickets": false
}
},
"products": [],
"client": {
"distribution_url": "url",
"terms_of_service_url": "https://example.com/terms_of_service.html",
"privacy_policy_url": "https://example.com/privacy_policy.html",
"imprint_url": "https://example.com/imprint_url.html",
"phone_number_required": false,
"email_address_required": false,
"signin_verification_channels": [],
"signup_verification_channels": []
},
"rides_with_failed_payments": [],
"renewable_ticketing_vouchers": [],
"product_support_uris": []
}
"""

private val bootstrap =
"""
{
"provider": {
"name": "Some Company Inc.",
"country_code": "DE",
"psp": "no_psp",
"ride_payment_method_types": [],
"ticketing_payment_method_types": [],
"service_credit_payment_method_types": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ internal class ApiPaymentMethodResponseTypeTest {
companion object {
fun data(): Collection<Array<Any>> = listOf(
arrayOf(ApiPaymentMethodType.CASH, "\"cash\""),
arrayOf(ApiPaymentMethodType.PSP_PROVIDED, "\"psp_provided\""),
arrayOf(ApiPaymentMethodType.STRIPE, "\"stripe\""),
arrayOf(ApiPaymentMethodType.LOGPAY, "\"logpay\""),
arrayOf(
Expand Down
Loading