diff options
author | Torsten Grote <t@grobox.de> | 2022-11-02 08:58:45 -0300 |
---|---|---|
committer | Torsten Grote <t@grobox.de> | 2022-11-02 08:58:45 -0300 |
commit | 865f80d49a8741de55d27002717d7ca1b42c875f (patch) | |
tree | a2402ce7c72780510a3c707d803b012e2318d732 /wallet/src/main/java/net/taler/wallet/payment | |
parent | 55624eb33bae14380efe8ca085dc420390b23702 (diff) | |
download | taler-android-865f80d49a8741de55d27002717d7ca1b42c875f.tar.gz taler-android-865f80d49a8741de55d27002717d7ca1b42c875f.tar.bz2 taler-android-865f80d49a8741de55d27002717d7ca1b42c875f.zip |
[wallet] Open payto:// URIs and hook into deposit to bank account flow
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/payment')
3 files changed, 0 insertions, 385 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/payment/DepositFragment.kt b/wallet/src/main/java/net/taler/wallet/payment/DepositFragment.kt deleted file mode 100644 index add9467..0000000 --- a/wallet/src/main/java/net/taler/wallet/payment/DepositFragment.kt +++ /dev/null @@ -1,262 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2022 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -package net.taler.wallet.payment - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Button -import androidx.compose.material.OutlinedTextField -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.colorResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.fragment.app.Fragment -import androidx.fragment.app.activityViewModels -import com.google.android.material.composethemeadapter.MdcTheme -import net.taler.common.Amount -import net.taler.wallet.MainViewModel -import net.taler.wallet.R -import net.taler.wallet.compose.collectAsStateLifecycleAware - -class DepositFragment : Fragment() { - private val model: MainViewModel by activityViewModels() - private val paymentManager get() = model.paymentManager - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - val amount = arguments?.getString("amount")?.let { - Amount.fromJSONString(it) - } ?: error("no amount passed") - - return ComposeView(requireContext()).apply { - setContent { - MdcTheme { - Surface { - val state = paymentManager.depositState.collectAsStateLifecycleAware() - MakeDepositComposable( - state = state.value, - amount = amount, - onMakeDeposit = this@DepositFragment::onDepositButtonClicked, - ) - } - } - } - } - } - - override fun onStart() { - super.onStart() - activity?.setTitle(R.string.send_deposit_title) - } - - override fun onDestroy() { - super.onDestroy() - if (!requireActivity().isChangingConfigurations) { - paymentManager.resetDepositState() - } - } - - private fun onDepositButtonClicked( - amount: Amount, - receiverName: String, - iban: String, - bic: String, - ) { - paymentManager.onDepositButtonClicked(amount, receiverName, iban, bic) - } -} - -@Composable -private fun MakeDepositComposable( - state: DepositState, - amount: Amount, - onMakeDeposit: (Amount, String, String, String) -> Unit, -) { - val scrollState = rememberScrollState() - Column( - modifier = Modifier - .fillMaxWidth() - .verticalScroll(scrollState), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - var name by rememberSaveable { mutableStateOf("") } - var iban by rememberSaveable { mutableStateOf("") } - var bic by rememberSaveable { mutableStateOf("") } - val focusRequester = remember { FocusRequester() } - OutlinedTextField( - modifier = Modifier - .padding(16.dp) - .focusRequester(focusRequester), - value = name, - enabled = !state.showFees, - onValueChange = { input -> - name = input - }, - isError = name.isBlank(), - label = { - Text( - stringResource(R.string.send_deposit_name), - color = if (name.isBlank()) { - colorResource(R.color.red) - } else Color.Unspecified, - ) - } - ) - LaunchedEffect(Unit) { - focusRequester.requestFocus() - } - OutlinedTextField( - modifier = Modifier - .padding(16.dp), - value = iban, - enabled = !state.showFees, - onValueChange = { input -> - iban = input - }, - isError = iban.isBlank(), - label = { - Text( - text = stringResource(R.string.send_deposit_iban), - color = if (iban.isBlank()) { - colorResource(R.color.red) - } else Color.Unspecified, - ) - } - ) - OutlinedTextField( - modifier = Modifier - .padding(16.dp), - value = bic, - enabled = !state.showFees, - onValueChange = { input -> - bic = input - }, - label = { - Text( - text = stringResource(R.string.send_deposit_bic), - ) - } - ) - Text( - modifier = Modifier.padding(horizontal = 16.dp), - text = stringResource(id = R.string.amount_chosen), - ) - Text( - modifier = Modifier.padding(16.dp), - fontSize = 24.sp, - color = colorResource(R.color.green), - text = amount.toString(), - ) - AnimatedVisibility(visible = state.showFees) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - val effectiveAmount = state.effectiveDepositAmount - val fee = amount - (effectiveAmount ?: Amount.zero(amount.currency)) - Text( - modifier = Modifier.padding(horizontal = 16.dp), - text = stringResource(id = R.string.withdraw_fees), - ) - Text( - modifier = Modifier.padding(16.dp), - fontSize = 24.sp, - color = colorResource(if (fee.isZero()) R.color.green else R.color.red), - text = if (fee.isZero()) { - fee.toString() - } else { - stringResource(R.string.amount_negative, fee.toString()) - }, - ) - Text( - modifier = Modifier.padding(horizontal = 16.dp), - text = stringResource(id = R.string.send_deposit_amount_effective), - ) - Text( - modifier = Modifier.padding(16.dp), - fontSize = 24.sp, - color = colorResource(R.color.green), - text = effectiveAmount.toString(), - ) - } - } - AnimatedVisibility(visible = state is DepositState.Error) { - Text( - modifier = Modifier.padding(16.dp), - fontSize = 18.sp, - color = colorResource(R.color.red), - text = (state as? DepositState.Error)?.msg ?: "", - ) - } - val focusManager = LocalFocusManager.current - Button( - modifier = Modifier.padding(16.dp), - enabled = iban.isNotBlank(), - onClick = { - focusManager.clearFocus() - onMakeDeposit(amount, name, iban, bic) - }, - ) { - Text(text = stringResource( - if (state.showFees) R.string.send_deposit_create_button - else R.string.send_deposit_check_fees_button - )) - } - } -} - -@Preview -@Composable -fun PreviewMakeDepositComposable() { - Surface { - val state = DepositState.FeesChecked( - effectiveDepositAmount = Amount.fromDouble("TESTKUDOS", 42.00), - ) - MakeDepositComposable( - state = state, - amount = Amount.fromDouble("TESTKUDOS", 42.23)) { _, _, _, _ -> - } - } -} diff --git a/wallet/src/main/java/net/taler/wallet/payment/DepositState.kt b/wallet/src/main/java/net/taler/wallet/payment/DepositState.kt deleted file mode 100644 index 8598911..0000000 --- a/wallet/src/main/java/net/taler/wallet/payment/DepositState.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of GNU Taler - * (C) 2022 Taler Systems S.A. - * - * GNU Taler is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 3, or (at your option) any later version. - * - * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -package net.taler.wallet.payment - -import net.taler.common.Amount - -sealed class DepositState { - - open val showFees: Boolean = false - open val effectiveDepositAmount: Amount? = null - - object Start : DepositState() - object CheckingFees : DepositState() - class FeesChecked( - override val effectiveDepositAmount: Amount, - ) : DepositState() { - override val showFees = true - } - - class MakingDeposit( - override val effectiveDepositAmount: Amount, - ) : DepositState() { - override val showFees = true - } - - object Success : DepositState() - - class Error(val msg: String) : DepositState() - -} diff --git a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt index 0af4262..53cb259 100644 --- a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt +++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt @@ -21,14 +21,10 @@ import androidx.annotation.UiThread import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import kotlinx.serialization.Serializable import net.taler.common.Amount import net.taler.common.ContractTerms import net.taler.wallet.TAG -import net.taler.wallet.accounts.PaytoUriIban import net.taler.wallet.backend.TalerErrorInfo import net.taler.wallet.backend.WalletBackendApi import net.taler.wallet.payment.PayStatus.AlreadyPaid @@ -68,9 +64,6 @@ class PaymentManager( private val mPayStatus = MutableLiveData<PayStatus>(PayStatus.None) internal val payStatus: LiveData<PayStatus> = mPayStatus - private val mDepositState = MutableStateFlow<DepositState>(DepositState.Start) - internal val depositState = mDepositState.asStateFlow() - @UiThread fun preparePay(url: String) = scope.launch { mPayStatus.value = PayStatus.Loading @@ -131,76 +124,4 @@ class PaymentManager( mPayStatus.value = PayStatus.Error(error.userFacingMsg) } - /* Deposits */ - - @UiThread - fun onDepositButtonClicked(amount: Amount, receiverName: String, iban: String, bic: String) { - val paytoUri: String = PaytoUriIban( - iban = iban, - bic = bic, - targetPath = "", - params = mapOf("receiver-name" to receiverName), - ).paytoUri - - if (depositState.value.showFees) { - val effectiveDepositAmount = depositState.value.effectiveDepositAmount - ?: Amount.zero(amount.currency) - makeDeposit(paytoUri, amount, effectiveDepositAmount) - } else { - prepareDeposit(paytoUri, amount) - } - } - - private fun prepareDeposit(paytoUri: String, amount: Amount) { - mDepositState.value = DepositState.CheckingFees - scope.launch { - api.request("prepareDeposit", PrepareDepositResponse.serializer()) { - put("depositPaytoUri", paytoUri) - put("amount", amount.toJSONString()) - }.onError { - Log.e(TAG, "Error prepareDeposit $it") - mDepositState.value = DepositState.Error(it.userFacingMsg) - }.onSuccess { - mDepositState.value = DepositState.FeesChecked( - effectiveDepositAmount = it.effectiveDepositAmount, - ) - } - } - } - - private fun makeDeposit( - paytoUri: String, - amount: Amount, - effectiveDepositAmount: Amount, - ) { - mDepositState.value = DepositState.MakingDeposit(effectiveDepositAmount) - scope.launch { - api.request("createDepositGroup", CreateDepositGroupResponse.serializer()) { - put("depositPaytoUri", paytoUri) - put("amount", amount.toJSONString()) - }.onError { - Log.e(TAG, "Error createDepositGroup $it") - mDepositState.value = DepositState.Error(it.userFacingMsg) - }.onSuccess { - mDepositState.value = DepositState.Success - } - } - } - - @UiThread - fun resetDepositState() { - mDepositState.value = DepositState.Start - } } - -@Serializable -data class PrepareDepositResponse( - val totalDepositCost: Amount, - val effectiveDepositAmount: Amount, -) - -@Serializable -data class CreateDepositGroupResponse( - val depositGroupId: String, - val transactionId: String, -) |