summaryrefslogtreecommitdiff
path: root/wallet/src/main/java/net/taler/wallet/withdraw
diff options
context:
space:
mode:
authorTorsten Grote <t@grobox.de>2020-03-18 14:24:41 -0300
committerTorsten Grote <t@grobox.de>2020-03-18 14:24:41 -0300
commita4796ec47d89a851b260b6fc195494547208a025 (patch)
treed2941b68ff2ce22c523e7aa634965033b1100560 /wallet/src/main/java/net/taler/wallet/withdraw
downloadtaler-android-a4796ec47d89a851b260b6fc195494547208a025.tar.gz
taler-android-a4796ec47d89a851b260b6fc195494547208a025.tar.bz2
taler-android-a4796ec47d89a851b260b6fc195494547208a025.zip
Merge all three apps into one repository
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/withdraw')
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt64
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt109
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt80
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt209
-rw-r--r--wallet/src/main/java/net/taler/wallet/withdraw/WithdrawSuccessfulFragment.kt44
5 files changed, 506 insertions, 0 deletions
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt
new file mode 100644
index 0000000..f0f6610
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/ErrorFragment.kt
@@ -0,0 +1,64 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 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.withdraw
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.navigation.fragment.findNavController
+import kotlinx.android.synthetic.main.fragment_error.*
+import net.taler.wallet.R
+import net.taler.wallet.WalletViewModel
+
+class ErrorFragment : Fragment() {
+
+ private val model: WalletViewModel by activityViewModels()
+ private val withdrawManager by lazy { model.withdrawManager }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_error, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ errorTitle.setText(R.string.withdraw_error_title)
+ errorMessage.setText(R.string.withdraw_error_message)
+
+ // show dev error message if dev mode is on
+ val status = withdrawManager.withdrawStatus.value
+ if (model.devMode.value == true && status is WithdrawStatus.Error) {
+ errorDevMessage.visibility = VISIBLE
+ errorDevMessage.text = status.message
+ } else {
+ errorDevMessage.visibility = GONE
+ }
+
+ backButton.setOnClickListener {
+ findNavController().navigateUp()
+ }
+ }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
new file mode 100644
index 0000000..454816b
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/PromptWithdrawFragment.kt
@@ -0,0 +1,109 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 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.withdraw
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
+import kotlinx.android.synthetic.main.fragment_prompt_withdraw.*
+import net.taler.wallet.R
+import net.taler.wallet.WalletViewModel
+import net.taler.wallet.fadeIn
+import net.taler.wallet.fadeOut
+import net.taler.wallet.withdraw.WithdrawStatus.Loading
+import net.taler.wallet.withdraw.WithdrawStatus.TermsOfServiceReviewRequired
+import net.taler.wallet.withdraw.WithdrawStatus.Withdrawing
+
+class PromptWithdrawFragment : Fragment() {
+
+ private val model: WalletViewModel by activityViewModels()
+ private val withdrawManager by lazy { model.withdrawManager }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_prompt_withdraw, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ button_cancel_withdraw.setOnClickListener {
+ withdrawManager.cancelCurrentWithdraw()
+ findNavController().navigateUp()
+ }
+
+ button_confirm_withdraw.setOnClickListener {
+ val status = withdrawManager.withdrawStatus.value
+ if (status !is WithdrawStatus.ReceivedDetails) throw AssertionError()
+ it.fadeOut()
+ confirmProgressBar.fadeIn()
+ withdrawManager.acceptWithdrawal(status.talerWithdrawUri, status.suggestedExchange)
+ }
+
+ withdrawManager.withdrawStatus.observe(viewLifecycleOwner, Observer {
+ showWithdrawStatus(it)
+ })
+ }
+
+ private fun showWithdrawStatus(status: WithdrawStatus?) = when (status) {
+ is WithdrawStatus.ReceivedDetails -> {
+ model.showProgressBar.value = false
+ progressBar.fadeOut()
+
+ introView.fadeIn()
+ @SuppressLint("SetTextI18n")
+ withdrawAmountView.text = "${status.amount.amount} ${status.amount.currency}"
+ withdrawAmountView.fadeIn()
+ feeView.fadeIn()
+
+ exchangeIntroView.fadeIn()
+ withdrawExchangeUrl.text = status.suggestedExchange
+ withdrawExchangeUrl.fadeIn()
+
+ button_confirm_withdraw.isEnabled = true
+ }
+ is WithdrawStatus.Success -> {
+ model.showProgressBar.value = false
+ withdrawManager.withdrawStatus.value = null
+ findNavController().navigate(R.id.action_promptWithdraw_to_withdrawSuccessful)
+ }
+ is Loading -> {
+ model.showProgressBar.value = true
+ }
+ is Withdrawing -> {
+ model.showProgressBar.value = true
+ }
+ is TermsOfServiceReviewRequired -> {
+ model.showProgressBar.value = false
+ findNavController().navigate(R.id.action_promptWithdraw_to_reviewExchangeTOS)
+ }
+ is WithdrawStatus.Error -> {
+ model.showProgressBar.value = false
+ findNavController().navigate(R.id.action_promptWithdraw_to_errorFragment)
+ }
+ null -> model.showProgressBar.value = false
+ }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt
new file mode 100644
index 0000000..cd01a33
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/ReviewExchangeTosFragment.kt
@@ -0,0 +1,80 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 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.withdraw
+
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.navigation.fragment.findNavController
+import kotlinx.android.synthetic.main.fragment_review_exchange_tos.*
+import net.taler.wallet.R
+import net.taler.wallet.WalletViewModel
+import net.taler.wallet.fadeIn
+import net.taler.wallet.fadeOut
+
+class ReviewExchangeTosFragment : Fragment() {
+
+ private val model: WalletViewModel by activityViewModels()
+ private val withdrawManager by lazy { model.withdrawManager }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_review_exchange_tos, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ acceptTosCheckBox.isChecked = false
+ acceptTosCheckBox.setOnCheckedChangeListener { _, isChecked ->
+ acceptTosButton.isEnabled = isChecked
+ }
+ abortTosButton.setOnClickListener {
+ withdrawManager.cancelCurrentWithdraw()
+ findNavController().navigateUp()
+ }
+ acceptTosButton.setOnClickListener {
+ withdrawManager.acceptCurrentTermsOfService()
+ }
+ withdrawManager.withdrawStatus.observe(viewLifecycleOwner, Observer {
+ when (it) {
+ is WithdrawStatus.TermsOfServiceReviewRequired -> {
+ tosTextView.text = it.tosText
+ tosTextView.fadeIn()
+ acceptTosCheckBox.fadeIn()
+ progressBar.fadeOut()
+ }
+ is WithdrawStatus.Loading -> {
+ findNavController().navigate(R.id.action_reviewExchangeTOS_to_promptWithdraw)
+ }
+ is WithdrawStatus.ReceivedDetails -> {
+ findNavController().navigate(R.id.action_reviewExchangeTOS_to_promptWithdraw)
+ }
+ else -> {
+ }
+ }
+ })
+ }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
new file mode 100644
index 0000000..e3af757
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawManager.kt
@@ -0,0 +1,209 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 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.withdraw
+
+import android.util.Log
+import androidx.lifecycle.MutableLiveData
+import net.taler.wallet.Amount
+import net.taler.wallet.TAG
+import net.taler.wallet.backend.WalletBackendApi
+import org.json.JSONObject
+
+sealed class WithdrawStatus {
+ data class Loading(val talerWithdrawUri: String) : WithdrawStatus()
+ data class TermsOfServiceReviewRequired(
+ val talerWithdrawUri: String,
+ val exchangeBaseUrl: String,
+ val tosText: String,
+ val tosEtag: String,
+ val amount: Amount,
+ val suggestedExchange: String
+ ) : WithdrawStatus()
+
+ data class ReceivedDetails(
+ val talerWithdrawUri: String,
+ val amount: Amount,
+ val suggestedExchange: String
+ ) : WithdrawStatus()
+
+ data class Withdrawing(val talerWithdrawUri: String) : WithdrawStatus()
+
+ object Success : WithdrawStatus()
+ data class Error(val message: String?) : WithdrawStatus()
+}
+
+class WithdrawManager(private val walletBackendApi: WalletBackendApi) {
+
+ val withdrawStatus = MutableLiveData<WithdrawStatus>()
+ val testWithdrawalInProgress = MutableLiveData(false)
+
+ private var currentWithdrawRequestId = 0
+
+ fun withdrawTestkudos() {
+ testWithdrawalInProgress.value = true
+
+ walletBackendApi.sendRequest("withdrawTestkudos", null) { _, _ ->
+ testWithdrawalInProgress.postValue(false)
+ }
+ }
+
+ fun getWithdrawalInfo(talerWithdrawUri: String) {
+ val args = JSONObject()
+ args.put("talerWithdrawUri", talerWithdrawUri)
+
+ withdrawStatus.value = WithdrawStatus.Loading(talerWithdrawUri)
+
+ this.currentWithdrawRequestId++
+ val myWithdrawRequestId = this.currentWithdrawRequestId
+
+ walletBackendApi.sendRequest("getWithdrawDetailsForUri", args) { isError, result ->
+ if (isError) {
+ Log.e(TAG, "Error getWithdrawDetailsForUri ${result.toString(4)}")
+ val message = if (result.has("message")) result.getString("message") else null
+ withdrawStatus.postValue(WithdrawStatus.Error(message))
+ return@sendRequest
+ }
+ if (myWithdrawRequestId != this.currentWithdrawRequestId) {
+ val mismatch = "$myWithdrawRequestId != ${this.currentWithdrawRequestId}"
+ Log.w(TAG, "Got withdraw result for different request id $mismatch")
+ return@sendRequest
+ }
+ Log.v(TAG, "got getWithdrawDetailsForUri result")
+ val status = withdrawStatus.value
+ if (status !is WithdrawStatus.Loading) {
+ Log.v(TAG, "ignoring withdrawal info result, not loading.")
+ return@sendRequest
+ }
+ val wi = result.getJSONObject("bankWithdrawDetails")
+ val suggestedExchange = wi.getString("suggestedExchange")
+ // We just use the suggested exchange, in the future there will be
+ // a selection dialog.
+ getWithdrawalInfoWithExchange(talerWithdrawUri, suggestedExchange)
+ }
+ }
+
+ private fun getWithdrawalInfoWithExchange(talerWithdrawUri: String, selectedExchange: String) {
+ val args = JSONObject()
+ args.put("talerWithdrawUri", talerWithdrawUri)
+ args.put("selectedExchange", selectedExchange)
+
+ this.currentWithdrawRequestId++
+ val myWithdrawRequestId = this.currentWithdrawRequestId
+
+ walletBackendApi.sendRequest("getWithdrawDetailsForUri", args) { isError, result ->
+ if (isError) {
+ Log.e(TAG, "Error getWithdrawDetailsForUri ${result.toString(4)}")
+ val message = if (result.has("message")) result.getString("message") else null
+ withdrawStatus.postValue(WithdrawStatus.Error(message))
+ return@sendRequest
+ }
+ if (myWithdrawRequestId != this.currentWithdrawRequestId) {
+ val mismatch = "$myWithdrawRequestId != ${this.currentWithdrawRequestId}"
+ Log.w(TAG, "Got withdraw result for different request id $mismatch")
+ return@sendRequest
+ }
+ Log.v(TAG, "got getWithdrawDetailsForUri result (with exchange details)")
+ val status = withdrawStatus.value
+ if (status !is WithdrawStatus.Loading) {
+ Log.v(TAG, "ignoring withdrawal info result, not loading.")
+ return@sendRequest
+ }
+ val wi = result.getJSONObject("bankWithdrawDetails")
+ val suggestedExchange = wi.getString("suggestedExchange")
+ val amount = Amount.fromJson(wi.getJSONObject("amount"))
+
+ val ei = result.getJSONObject("exchangeWithdrawDetails")
+ val termsOfServiceAccepted = ei.getBoolean("termsOfServiceAccepted")
+
+ if (!termsOfServiceAccepted) {
+ val exchange = ei.getJSONObject("exchangeInfo")
+ val tosText = exchange.getString("termsOfServiceText")
+ val tosEtag = exchange.optString("termsOfServiceLastEtag", "undefined")
+ withdrawStatus.postValue(
+ WithdrawStatus.TermsOfServiceReviewRequired(
+ status.talerWithdrawUri,
+ selectedExchange,
+ tosText,
+ tosEtag,
+ amount,
+ suggestedExchange
+ )
+ )
+ } else {
+ withdrawStatus.postValue(
+ WithdrawStatus.ReceivedDetails(
+ status.talerWithdrawUri,
+ amount,
+ suggestedExchange
+ )
+ )
+ }
+ }
+ }
+
+ fun acceptWithdrawal(talerWithdrawUri: String, selectedExchange: String) {
+ val args = JSONObject()
+ args.put("talerWithdrawUri", talerWithdrawUri)
+ args.put("selectedExchange", selectedExchange)
+
+ withdrawStatus.value = WithdrawStatus.Withdrawing(talerWithdrawUri)
+
+ walletBackendApi.sendRequest("acceptWithdrawal", args) { isError, _ ->
+ if (isError) {
+ Log.v(TAG, "got acceptWithdrawal error result")
+ return@sendRequest
+ }
+ Log.v(TAG, "got acceptWithdrawal result")
+ val status = withdrawStatus.value
+ if (status !is WithdrawStatus.Withdrawing) {
+ Log.v(TAG, "ignoring acceptWithdrawal result, invalid state")
+ }
+ withdrawStatus.postValue(WithdrawStatus.Success)
+ }
+ }
+
+ /**
+ * Accept the currently displayed terms of service.
+ */
+ fun acceptCurrentTermsOfService() {
+ when (val s = withdrawStatus.value) {
+ is WithdrawStatus.TermsOfServiceReviewRequired -> {
+ val args = JSONObject()
+ args.put("exchangeBaseUrl", s.exchangeBaseUrl)
+ args.put("etag", s.tosEtag)
+ walletBackendApi.sendRequest("acceptExchangeTermsOfService", args) { isError, _ ->
+ if (isError) {
+ return@sendRequest
+ }
+ withdrawStatus.postValue(
+ WithdrawStatus.ReceivedDetails(
+ s.talerWithdrawUri,
+ s.amount,
+ s.suggestedExchange
+ )
+ )
+ }
+ }
+ }
+ }
+
+ fun cancelCurrentWithdraw() {
+ currentWithdrawRequestId++
+ withdrawStatus.value = null
+ }
+
+}
diff --git a/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawSuccessfulFragment.kt b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawSuccessfulFragment.kt
new file mode 100644
index 0000000..5daeff1
--- /dev/null
+++ b/wallet/src/main/java/net/taler/wallet/withdraw/WithdrawSuccessfulFragment.kt
@@ -0,0 +1,44 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 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.withdraw
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import kotlinx.android.synthetic.main.fragment_withdraw_successful.*
+import net.taler.wallet.R
+
+class WithdrawSuccessfulFragment : Fragment() {
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_withdraw_successful, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ backButton.setOnClickListener {
+ findNavController().navigateUp()
+ }
+ }
+
+}