From 18866e4c5dc83cd2c856244db17dc3c6f5dabec1 Mon Sep 17 00:00:00 2001 From: amnix Date: Thu, 17 Oct 2024 14:45:05 +0900 Subject: [PATCH 1/4] Added Support for BitCash, NetCash and Paidy --- .../ui/screens/payment/KomojuPaymentScreen.kt | 23 +++-- .../payment/KomojuPaymentScreenModel.kt | 96 +++++++++++++++++-- .../screens/payment/KomojuPaymentUIState.kt | 13 ++- .../payment/composables/BitCashForm.kt | 1 + .../payment/composables/NetCashForm.kt | 5 +- .../screens/payment/composables/PaidyForm.kt | 74 ++++++++++++++ .../payment/composables/PaymentMethodForm.kt | 12 ++- .../payment/composables/PaymentMethodsRow.kt | 2 +- .../main/res/drawable/komoju_ic_net_cash.xml | 29 ++++++ .../com/komoju/mobile/sdk/entities/Payment.kt | 1 + .../mobile/sdk/entities/PaymentRequest.kt | 3 + .../sdk/remote/dtos/PaymentRequestDto.kt | 31 +++++- .../sdk/remote/mappers/PaymentMapper.kt | 10 +- 13 files changed, 278 insertions(+), 22 deletions(-) create mode 100644 android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaidyForm.kt create mode 100644 android/src/main/res/drawable/komoju_ic_net_cash.xml diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreen.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreen.kt index a33537c..6303624 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreen.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreen.kt @@ -100,6 +100,8 @@ internal data class KomojuPaymentScreen(private val sdkConfiguration: KomojuSDK. onNetCashDisplayDataChange = screenViewModel::onNetCashDisplayDataChange, webMoneyDisplayData = uiState.webMoneyDisplayData, onWebMoneyDisplayDataChange = screenViewModel::onWebMoneyDisplayDataChange, + paidyDisplayData = uiState.paidyDisplayData, + onPaidyDisplayDataChange = screenViewModel::onPaidyDisplayDataChange, onPaymentRequested = screenViewModel::onPaymentRequested, ) } @@ -114,6 +116,8 @@ internal data class KomojuPaymentScreen(private val sdkConfiguration: KomojuSDK. } if (uiState.selectedPaymentMethod is PaymentMethod.CreditCard && sdkConfiguration.inlinedProcessing.not() && + uiState.isLoading || + uiState.selectedPaymentMethod !is PaymentMethod.CreditCard && uiState.isLoading ) { Box( @@ -128,12 +132,19 @@ internal data class KomojuPaymentScreen(private val sdkConfiguration: KomojuSDK. } if (inlineWebViewURL != null) { InlinedWebView( - modifier = Modifier.background(Color.White).align(Alignment.CenterEnd).animateContentSize().then( - when { - shouldShowFullScreenWebView -> Modifier.fillMaxSize() - else -> Modifier.width(Dp.Hairline).fillMaxHeight() - }, - ), + modifier = Modifier + .background(Color.White) + .align(Alignment.CenterEnd) + .animateContentSize() + .then( + when { + shouldShowFullScreenWebView -> Modifier.fillMaxSize() + else -> + Modifier + .width(Dp.Hairline) + .fillMaxHeight() + }, + ), url = inlineWebViewURL, onDone = { screenViewModel.onInlinedDeeplinkCaptured(it) diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt index f302cf2..d44e220 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt @@ -1,5 +1,6 @@ package com.komoju.android.sdk.ui.screens.payment +import androidx.core.text.isDigitsOnly import cafe.adriel.voyager.core.model.screenModelScope import com.komoju.android.sdk.KomojuSDK import com.komoju.android.sdk.navigation.RouterStateScreenModel @@ -16,6 +17,7 @@ import com.komoju.android.sdk.utils.isValidEmail import com.komoju.mobile.sdk.entities.Payment import com.komoju.mobile.sdk.entities.PaymentMethod import com.komoju.mobile.sdk.entities.PaymentRequest +import com.komoju.mobile.sdk.entities.PaymentStatus import com.komoju.mobile.sdk.entities.PaymentStatus.Companion.isSuccessful import com.komoju.mobile.sdk.entities.SecureTokenRequest import com.komoju.mobile.sdk.entities.SecureTokenResponse.Status.ERRORED @@ -96,6 +98,10 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat it.copy(webMoneyDisplayData = webMoneyDisplayData) } + fun onPaidyDisplayDataChange(paidyDisplayData: PaidyDisplayData) = mutableState.update { + it.copy(paidyDisplayData = paidyDisplayData) + } + fun onPaymentRequested(paymentMethod: PaymentMethod) { if (paymentMethod.validate()) { changeInlinePaymentState(InlinedPaymentPrimaryButtonState.LOADING) @@ -106,9 +112,14 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat val request = paymentMethod.toPaymentRequest() screenModelScope.launch { komojuApi.sessions.pay(config.sessionId.orEmpty(), request).onSuccess { payment -> - mutableState.update { it.copy(isLoading = true) } - changeInlinePaymentState(InlinedPaymentPrimaryButtonState.LOADING) - payment.handle() + if (payment is Payment.Error) { + mutableState.update { it.copy(isLoading = false) } + changeInlinePaymentState(InlinedPaymentPrimaryButtonState.ERROR) + } else { + mutableState.update { it.copy(isLoading = true) } + changeInlinePaymentState(InlinedPaymentPrimaryButtonState.LOADING) + payment.handle() + } }.onFailure { mutableState.update { it.copy(isLoading = false) } changeInlinePaymentState(InlinedPaymentPrimaryButtonState.ERROR) @@ -159,6 +170,9 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat ), ) } + if (newState == InlinedPaymentPrimaryButtonState.ERROR) { + mutableRouter.value = Router.SetPaymentResultAndPop() + } } private suspend fun verifyAndProcessInlinedPayment(token: String, amount: String, currency: String) { @@ -169,7 +183,6 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat currency = currency, onError = { changeInlinePaymentState(InlinedPaymentPrimaryButtonState.ERROR) - mutableRouter.value = Router.SetPaymentResultAndPop() }, onSuccess = { changeInlinePaymentState(InlinedPaymentPrimaryButtonState.SUCCESS) @@ -192,6 +205,7 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat when (this) { is Payment.Konbini -> mutableRouter.value = Router.Replace(KomojuPaymentRoute.KonbiniAwaitingPayment(config, payment = this)) is Payment.OffSitePayment -> _offSitePaymentURL.value = redirectURL + is Payment.Completed -> mutableRouter.value = Router.SetPaymentResultAndPop(KomojuSDK.PaymentResult(isSuccessFul = status == PaymentStatus.CAPTURED)) else -> Unit } } @@ -199,10 +213,66 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat private fun PaymentMethod.validate() = when (this) { is PaymentMethod.CreditCard -> state.value.creditCardDisplayData.validate() is PaymentMethod.Konbini -> state.value.konbiniDisplayData.validate(state.value.commonDisplayData) + is PaymentMethod.Paidy -> state.value.paidyDisplayData.validate() + is PaymentMethod.NetCash -> state.value.netCashDisplayData.validate() + is PaymentMethod.BitCash -> state.value.bitCashDisplayData.validate() is PaymentMethod.OffSitePayment -> true // No input required for Offsite payment else -> false } + private fun BitCashDisplayData.validate(): Boolean { + val idError = when { + bitCashId.isBlank() -> "The entered net cash id cannot be empty" + bitCashId.length != 16 -> "The entered net cash id is not valid" + else -> null + } + mutableState.update { + it.copy( + bitCashDisplayData = it.bitCashDisplayData.copy( + bitCashError = idError, + ), + ) + } + return idError == null + } + private fun NetCashDisplayData.validate(): Boolean { + val idError = when { + netCashId.isBlank() -> "The entered net cash id cannot be empty" + netCashId.length !in 16..20 -> "The entered net cash id is not valid" + else -> null + } + mutableState.update { + it.copy( + netCashDisplayData = it.netCashDisplayData.copy( + netCashError = idError, + ), + ) + } + return idError == null + } + + private fun PaidyDisplayData.validate(): Boolean { + val fullNameError = when { + fullName.isBlank() -> "The entered name cannot be empty" + else -> null + } + val phoneNumberError = when { + phoneNumber.isBlank() -> "The entered phone number cannot be empty" + phoneNumber.length < 7 -> "The entered phone number is not valid" + phoneNumber.isDigitsOnly().not() -> "The entered phone number is not valid" + else -> null + } + mutableState.update { + it.copy( + paidyDisplayData = it.paidyDisplayData.copy( + fullNameError = fullNameError, + phoneNumberError = phoneNumberError, + ), + ) + } + return fullNameError == null && phoneNumberError == null + } + private fun CreditCardDisplayData.validate(): Boolean { val fullNameOnCardError = when { fullNameOnCard.isBlank() -> "The entered cardholder name cannot be empty" @@ -257,7 +327,10 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat private fun PaymentMethod.toPaymentRequest(): PaymentRequest = when (this) { is PaymentMethod.BankTransfer -> TODO() - is PaymentMethod.BitCash -> TODO() + is PaymentMethod.BitCash -> PaymentRequest.BitCash( + paymentMethod = this, + bitCashId = state.value.bitCashDisplayData.bitCashId, + ) is PaymentMethod.CreditCard -> error("Credit Card needs to generate tokens first!") is PaymentMethod.Konbini -> PaymentRequest.Konbini( paymentMethod = this, @@ -265,9 +338,16 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat email = state.value.commonDisplayData.email, ) - is PaymentMethod.NetCash -> TODO() - is PaymentMethod.Other -> TODO() - is PaymentMethod.Paidy -> TODO() + is PaymentMethod.NetCash -> PaymentRequest.NetCash( + paymentMethod = this, + netCashId = state.value.netCashDisplayData.netCashId, + ) + is PaymentMethod.Other -> error("payment method is not supported!") + is PaymentMethod.Paidy -> PaymentRequest.Paidy( + paymentMethod = this, + fullName = state.value.paidyDisplayData.fullName, + phoneNumber = state.value.paidyDisplayData.phoneNumber, + ) is PaymentMethod.PayEasy -> TODO() is PaymentMethod.WebMoney -> TODO() is PaymentMethod.OffSitePayment -> PaymentRequest.OffSitePaymentRequest(this) diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt index bcc2f98..89c411c 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt @@ -16,10 +16,12 @@ internal data class KomojuPaymentUIState( val bitCashDisplayData: BitCashDisplayData = BitCashDisplayData(), val netCashDisplayData: NetCashDisplayData = NetCashDisplayData(), val webMoneyDisplayData: WebMoneyDisplayData = WebMoneyDisplayData(), + val paidyDisplayData: PaidyDisplayData = PaidyDisplayData(), val inlinedCreditCardProcessingURL: String? = null, ) internal data class CommonDisplayData( + val fullName: String = String.empty, val lastName: String = String.empty, val firstName: String = String.empty, val lastNamePhonetic: String = String.empty, @@ -49,8 +51,15 @@ internal data class KonbiniDisplayData( val konbiniBrandNullError: String? = null, ) -internal data class BitCashDisplayData(val bitCashId: String = String.empty) +internal data class BitCashDisplayData(val bitCashId: String = String.empty, val bitCashError: String? = null) -internal data class NetCashDisplayData(val netCashId: String = String.empty) +internal data class NetCashDisplayData(val netCashId: String = String.empty, val netCashError: String? = null) internal data class WebMoneyDisplayData(val prepaidNumber: String = String.empty) + +internal data class PaidyDisplayData( + val fullName: String = String.empty, + val fullNameError: String? = null, + val phoneNumber: String = String.empty, + val phoneNumberError: String? = null, +) diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/BitCashForm.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/BitCashForm.kt index 9e51610..bd5a976 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/BitCashForm.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/BitCashForm.kt @@ -38,6 +38,7 @@ internal fun BitCashForm( onValueChange = { onBitCashDisplayDataChange(bitCashDisplayData.copy(bitCashId = it)) }, + error = bitCashDisplayData.bitCashError, ) Spacer(modifier = Modifier.height(16.dp)) PrimaryButton( diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/NetCashForm.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/NetCashForm.kt index f042864..c087636 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/NetCashForm.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/NetCashForm.kt @@ -33,11 +33,12 @@ internal fun NetCashForm( Column { TextField( value = netCashDisplayData.netCashId, - titleKey = "BIT_CASH_INPUT_LABEL", - placeholderKey = "BIT_CASH_INPUT_PLACEHOLDER", + titleKey = "NET_CASH_INPUT_LABEL", + placeholderKey = "NET_CASH_INPUT_PLACEHOLDER", onValueChange = { onNetCashDisplayDataChange(netCashDisplayData.copy(netCashId = it)) }, + error = netCashDisplayData.netCashError, ) Spacer(modifier = Modifier.height(16.dp)) PrimaryButton( diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaidyForm.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaidyForm.kt new file mode 100644 index 0000000..c9eeb8e --- /dev/null +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaidyForm.kt @@ -0,0 +1,74 @@ +package com.komoju.android.sdk.ui.screens.payment.composables + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.komoju.android.sdk.ui.composables.PrimaryButton +import com.komoju.android.sdk.ui.screens.payment.PaidyDisplayData +import com.komoju.android.sdk.ui.theme.KomojuMobileSdkTheme +import com.komoju.android.sdk.ui.theme.LocalI18nTexts +import com.komoju.mobile.sdk.entities.PaymentMethod + +@Composable +internal fun PaidyForm(paidy: PaymentMethod.Paidy, paidyDisplayData: PaidyDisplayData, onPaidyDisplayDataChange: (PaidyDisplayData) -> Unit, onPayButtonClicked: () -> Unit) { + Column { + TextField( + value = paidyDisplayData.fullName, + titleKey = "FULL_NAME", + placeholderKey = "FULL_NAME_PLACEHOLDER", + onValueChange = { + onPaidyDisplayDataChange(paidyDisplayData.copy(fullName = it)) + }, + error = paidyDisplayData.fullNameError, + ) + TextField( + value = paidyDisplayData.phoneNumber, + titleKey = "TELEPHONE_NUMBER", + placeholderKey = "TELEPHONE_NUMBER_PLACEHOLDER", + keyboardType = KeyboardType.Phone, + onValueChange = { + onPaidyDisplayDataChange(paidyDisplayData.copy(phoneNumber = it)) + }, + error = paidyDisplayData.phoneNumberError, + ) + PrimaryButton(LocalI18nTexts.current["CONTINUE_TO_PAIDY"], modifier = Modifier.fillMaxWidth().padding(all = 16.dp), onPayButtonClicked) + } +} + +@Composable +@Preview(showBackground = true) +private fun PaidyFormPreview() { + val paidy = PaymentMethod.Paidy( + displayName = "Paidy", + hashedGateway = "hashedGateway", + exchangeRate = 1.0, + currency = "JPY", + amount = "100", + additionalFields = emptyList(), + isOffsite = true, + ) + + var paidyDisplayData by remember { + mutableStateOf(PaidyDisplayData()) + } + KomojuMobileSdkTheme { + PaidyForm( + paidy, + paidyDisplayData = paidyDisplayData, + onPaidyDisplayDataChange = { + paidyDisplayData = it + }, + onPayButtonClicked = { + }, + ) + } +} diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodForm.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodForm.kt index 2f4d315..e7ba97f 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodForm.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodForm.kt @@ -6,6 +6,7 @@ import com.komoju.android.sdk.ui.screens.payment.CommonDisplayData import com.komoju.android.sdk.ui.screens.payment.CreditCardDisplayData import com.komoju.android.sdk.ui.screens.payment.KonbiniDisplayData import com.komoju.android.sdk.ui.screens.payment.NetCashDisplayData +import com.komoju.android.sdk.ui.screens.payment.PaidyDisplayData import com.komoju.android.sdk.ui.screens.payment.WebMoneyDisplayData import com.komoju.mobile.sdk.entities.PaymentMethod @@ -24,6 +25,8 @@ internal fun PaymentMethodForm( onNetCashDisplayDataChange: (NetCashDisplayData) -> Unit, webMoneyDisplayData: WebMoneyDisplayData, onWebMoneyDisplayDataChange: (WebMoneyDisplayData) -> Unit, + paidyDisplayData: PaidyDisplayData, + onPaidyDisplayDataChange: (PaidyDisplayData) -> Unit, onPaymentRequested: (PaymentMethod) -> Unit, ) { when (paymentMethod) { @@ -90,7 +93,14 @@ internal fun PaymentMethodForm( }, ) - is PaymentMethod.Paidy -> Unit + is PaymentMethod.Paidy -> PaidyForm( + paidy = paymentMethod, + paidyDisplayData = paidyDisplayData, + onPaidyDisplayDataChange = onPaidyDisplayDataChange, + onPayButtonClicked = { + onPaymentRequested(paymentMethod) + }, + ) is PaymentMethod.PayEasy -> Unit is PaymentMethod.Other -> Unit diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodsRow.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodsRow.kt index 93d010e..9654233 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodsRow.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/PaymentMethodsRow.kt @@ -75,7 +75,7 @@ private val PaymentMethod.displayIcon is PaymentMethod.BitCash -> R.drawable.komoju_ic_bitcash is PaymentMethod.CreditCard -> R.drawable.komoju_ic_credit_card is PaymentMethod.Konbini -> R.drawable.komoju_ic_konbini - is PaymentMethod.NetCash -> R.drawable.komoju_ic_credit_card + is PaymentMethod.NetCash -> R.drawable.komoju_ic_net_cash is PaymentMethod.Paidy -> R.drawable.komoju_ic_paidy is PaymentMethod.PayEasy -> R.drawable.komoju_ic_pay_easy is PaymentMethod.WebMoney -> R.drawable.komoju_ic_web_money diff --git a/android/src/main/res/drawable/komoju_ic_net_cash.xml b/android/src/main/res/drawable/komoju_ic_net_cash.xml new file mode 100644 index 0000000..bcab96a --- /dev/null +++ b/android/src/main/res/drawable/komoju_ic_net_cash.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/Payment.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/Payment.kt index 4c669cf..a4ea57f 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/Payment.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/Payment.kt @@ -19,6 +19,7 @@ sealed interface Payment { data class CreditCard(override val status: PaymentStatus, override val amount: String, override val currency: String) : Payment data class OffSitePayment(override val status: PaymentStatus, override val amount: String, override val currency: String, val type: String, val redirectURL: String) : Payment + data class Completed(override val status: PaymentStatus, override val amount: String, override val currency: String) : Payment data class Error(val code: String, val message: String, override val amount: String, override val currency: String) : Payment { override val status: PaymentStatus = PaymentStatus.EXPIRED diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt index bd5ff38..e124d3e 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt @@ -6,5 +6,8 @@ sealed interface PaymentRequest { val paymentMethod: PaymentMethod data class Konbini(override val paymentMethod: PaymentMethod.Konbini, val konbiniBrand: KonbiniBrand, val email: String) : PaymentRequest + data class Paidy(override val paymentMethod: PaymentMethod.Paidy, val fullName: String, val phoneNumber: String) : PaymentRequest data class OffSitePaymentRequest(override val paymentMethod: PaymentMethod.OffSitePayment) : PaymentRequest + data class NetCash(override val paymentMethod: PaymentMethod.NetCash, val netCashId: String) : PaymentRequest + data class BitCash(override val paymentMethod: PaymentMethod.BitCash, val bitCashId: String) : PaymentRequest } diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt index b567fdc..461a285 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt @@ -20,9 +20,38 @@ internal data class PaymentRequestDto(@SerialName("payment_details") val payment type = paymentRequest.paymentMethod.type.id, ), ) + + is PaymentRequest.Paidy -> PaymentRequestDto( + paymentDetails = PaymentDetails( + type = "paidy", + fullName = paymentRequest.fullName, + phoneNumber = paymentRequest.phoneNumber, + ), + ) + + is PaymentRequest.NetCash -> PaymentRequestDto( + paymentDetails = PaymentDetails( + type = "net_cash", + prepaidNumber = paymentRequest.netCashId, + ), + ) + + is PaymentRequest.BitCash -> PaymentRequestDto( + paymentDetails = PaymentDetails( + type = "bit_cash", + prepaidNumber = paymentRequest.bitCashId, + ), + ) } } @Serializable - data class PaymentDetails(@SerialName("store") val store: String? = null, @SerialName("type") val type: String? = null, @SerialName("email") val email: String? = null) + data class PaymentDetails( + @SerialName("store") val store: String? = null, + @SerialName("type") val type: String? = null, + @SerialName("email") val email: String? = null, + @SerialName("customer_name") val fullName: String? = null, + @SerialName("phone") val phoneNumber: String? = null, + @SerialName("prepaid_number") val prepaidNumber: String? = null, + ) } diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt index 0a29215..ff39912 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt @@ -29,13 +29,21 @@ internal object PaymentMapper { currency = payment.currency.orEmpty(), status = PaymentStatus.fromString(payment.status.orEmpty()), ) - in OffSitePaymentType.supportedTypes -> Payment.OffSitePayment( + + in OffSitePaymentType.supportedTypes, "paidy" -> Payment.OffSitePayment( amount = payment?.amount.orEmpty(), currency = payment?.currency.orEmpty(), redirectURL = payment?.paymentDetails?.redirectUrl.orEmpty(), status = PaymentStatus.fromString(payment?.status.orEmpty()), type = type.orEmpty(), ) + + "net_cash", "bit_cash" -> Payment.Completed( + amount = payment.amount.orEmpty(), + currency = payment.currency.orEmpty(), + status = PaymentStatus.fromString(payment.status.orEmpty()), + ) + else -> error("Invalid payment type") } } From 338a3688b8cd47073747b48caefc5f7c5ff82f1d Mon Sep 17 00:00:00 2001 From: amnix Date: Thu, 17 Oct 2024 14:53:16 +0900 Subject: [PATCH 2/4] Added Support for webMoney --- .../payment/KomojuPaymentScreenModel.kt | 22 ++++++++++++++++++- .../screens/payment/KomojuPaymentUIState.kt | 2 +- .../payment/composables/WebMoneyForm.kt | 1 + .../mobile/sdk/entities/PaymentRequest.kt | 1 + .../sdk/remote/dtos/PaymentRequestDto.kt | 7 ++++++ .../sdk/remote/mappers/PaymentMapper.kt | 2 +- 6 files changed, 32 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt index d44e220..1322604 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt @@ -216,10 +216,27 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat is PaymentMethod.Paidy -> state.value.paidyDisplayData.validate() is PaymentMethod.NetCash -> state.value.netCashDisplayData.validate() is PaymentMethod.BitCash -> state.value.bitCashDisplayData.validate() + is PaymentMethod.WebMoney -> state.value.webMoneyDisplayData.validate() is PaymentMethod.OffSitePayment -> true // No input required for Offsite payment else -> false } + private fun WebMoneyDisplayData.validate(): Boolean{ + val prepaidNumberError = when { + prepaidNumber.isBlank() -> "The entered prepaid number cannot be empty" + prepaidNumber.length != 16 -> "The entered prepaid number is not valid" + else -> null + } + mutableState.update { + it.copy( + webMoneyDisplayData = it.webMoneyDisplayData.copy( + prepaidNumberError = prepaidNumberError, + ), + ) + } + return prepaidNumberError == null + } + private fun BitCashDisplayData.validate(): Boolean { val idError = when { bitCashId.isBlank() -> "The entered net cash id cannot be empty" @@ -349,7 +366,10 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat phoneNumber = state.value.paidyDisplayData.phoneNumber, ) is PaymentMethod.PayEasy -> TODO() - is PaymentMethod.WebMoney -> TODO() + is PaymentMethod.WebMoney -> PaymentRequest.WebMoney( + paymentMethod = this, + prepaidNumber = state.value.webMoneyDisplayData.prepaidNumber, + ) is PaymentMethod.OffSitePayment -> PaymentRequest.OffSitePaymentRequest(this) } diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt index 89c411c..ba53c56 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentUIState.kt @@ -55,7 +55,7 @@ internal data class BitCashDisplayData(val bitCashId: String = String.empty, val internal data class NetCashDisplayData(val netCashId: String = String.empty, val netCashError: String? = null) -internal data class WebMoneyDisplayData(val prepaidNumber: String = String.empty) +internal data class WebMoneyDisplayData(val prepaidNumber: String = String.empty, val prepaidNumberError: String? = null) internal data class PaidyDisplayData( val fullName: String = String.empty, diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/WebMoneyForm.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/WebMoneyForm.kt index 0f29bbe..56b1dcd 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/WebMoneyForm.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/composables/WebMoneyForm.kt @@ -38,6 +38,7 @@ internal fun WebMoneyForm( onValueChange = { onWebMoneyDisplayDataChange(webMoneyDisplayData.copy(prepaidNumber = it)) }, + error = webMoneyDisplayData.prepaidNumberError, ) Spacer(modifier = Modifier.height(16.dp)) PrimaryButton( diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt index e124d3e..23f3459 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/entities/PaymentRequest.kt @@ -10,4 +10,5 @@ sealed interface PaymentRequest { data class OffSitePaymentRequest(override val paymentMethod: PaymentMethod.OffSitePayment) : PaymentRequest data class NetCash(override val paymentMethod: PaymentMethod.NetCash, val netCashId: String) : PaymentRequest data class BitCash(override val paymentMethod: PaymentMethod.BitCash, val bitCashId: String) : PaymentRequest + data class WebMoney(override val paymentMethod: PaymentMethod.WebMoney, val prepaidNumber: String) : PaymentRequest } diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt index 461a285..68f357e 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/dtos/PaymentRequestDto.kt @@ -42,6 +42,13 @@ internal data class PaymentRequestDto(@SerialName("payment_details") val payment prepaidNumber = paymentRequest.bitCashId, ), ) + + is PaymentRequest.WebMoney -> PaymentRequestDto( + paymentDetails = PaymentDetails( + type = "bit_cash", + prepaidNumber = paymentRequest.prepaidNumber, + ), + ) } } diff --git a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt index ff39912..f9f14ca 100644 --- a/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt +++ b/shared/src/commonMain/kotlin/com/komoju/mobile/sdk/remote/mappers/PaymentMapper.kt @@ -38,7 +38,7 @@ internal object PaymentMapper { type = type.orEmpty(), ) - "net_cash", "bit_cash" -> Payment.Completed( + "net_cash", "bit_cash", "web_money" -> Payment.Completed( amount = payment.amount.orEmpty(), currency = payment.currency.orEmpty(), status = PaymentStatus.fromString(payment.status.orEmpty()), From aea5bbd5976fccb489da027707ac4eb938f9abfd Mon Sep 17 00:00:00 2001 From: amnix Date: Thu, 17 Oct 2024 14:53:26 +0900 Subject: [PATCH 3/4] Added Support for webMoney --- .../sdk/ui/screens/payment/KomojuPaymentScreenModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt index 1322604..10e86b1 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt @@ -221,7 +221,7 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat else -> false } - private fun WebMoneyDisplayData.validate(): Boolean{ + private fun WebMoneyDisplayData.validate(): Boolean { val prepaidNumberError = when { prepaidNumber.isBlank() -> "The entered prepaid number cannot be empty" prepaidNumber.length != 16 -> "The entered prepaid number is not valid" @@ -232,7 +232,7 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat webMoneyDisplayData = it.webMoneyDisplayData.copy( prepaidNumberError = prepaidNumberError, ), - ) + ) } return prepaidNumberError == null } From 553b91d7884418ff4f054c610d7c452121c0dbac Mon Sep 17 00:00:00 2001 From: amnix Date: Thu, 17 Oct 2024 14:57:15 +0900 Subject: [PATCH 4/4] ktlint fixup --- .../android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt index 10e86b1..8763f2a 100644 --- a/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt +++ b/android/src/main/java/com/komoju/android/sdk/ui/screens/payment/KomojuPaymentScreenModel.kt @@ -343,7 +343,6 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat ) private fun PaymentMethod.toPaymentRequest(): PaymentRequest = when (this) { - is PaymentMethod.BankTransfer -> TODO() is PaymentMethod.BitCash -> PaymentRequest.BitCash( paymentMethod = this, bitCashId = state.value.bitCashDisplayData.bitCashId, @@ -365,6 +364,7 @@ internal class KomojuPaymentScreenModel(private val config: KomojuSDK.Configurat fullName = state.value.paidyDisplayData.fullName, phoneNumber = state.value.paidyDisplayData.phoneNumber, ) + is PaymentMethod.BankTransfer -> TODO() is PaymentMethod.PayEasy -> TODO() is PaymentMethod.WebMoney -> PaymentRequest.WebMoney( paymentMethod = this,