diff options
Diffstat (limited to 'wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt')
-rw-r--r-- | wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt | 119 |
1 files changed, 84 insertions, 35 deletions
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 34a8023..647c98c 100644 --- a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt +++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt @@ -22,40 +22,63 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import kotlinx.serialization.Serializable +import kotlinx.serialization.encodeToString +import net.taler.common.Amount import net.taler.common.ContractTerms -import net.taler.lib.common.Amount import net.taler.wallet.TAG -import net.taler.wallet.backend.WalletBackendApi +import net.taler.wallet.backend.BackendManager import net.taler.wallet.backend.TalerErrorInfo +import net.taler.wallet.backend.WalletBackendApi import net.taler.wallet.payment.PayStatus.AlreadyPaid import net.taler.wallet.payment.PayStatus.InsufficientBalance import net.taler.wallet.payment.PreparePayResponse.AlreadyConfirmedResponse import net.taler.wallet.payment.PreparePayResponse.InsufficientBalanceResponse import net.taler.wallet.payment.PreparePayResponse.PaymentPossibleResponse +import org.json.JSONObject val REGEX_PRODUCT_IMAGE = Regex("^data:image/(jpeg|png);base64,([A-Za-z0-9+/=]+)$") sealed class PayStatus { - object None : PayStatus() - object Loading : PayStatus() + data object None : PayStatus() + data object Loading : PayStatus() data class Prepared( val contractTerms: ContractTerms, - val proposalId: String, + val transactionId: String, val amountRaw: Amount, - val amountEffective: Amount + val amountEffective: Amount, + ) : PayStatus() + + data class Checked( + val details: WalletTemplateDetails, + val supportedCurrencies: List<String>, ) : PayStatus() data class InsufficientBalance( val contractTerms: ContractTerms, - val amountRaw: Amount + val amountRaw: Amount, + ) : PayStatus() + + data class AlreadyPaid( + val transactionId: String, ) : PayStatus() - // TODO bring user to fulfilment URI - object AlreadyPaid : PayStatus() - data class Error(val error: String) : PayStatus() - data class Success(val currency: String) : PayStatus() + data class Pending( + val transactionId: String? = null, + val error: TalerErrorInfo? = null, + ) : PayStatus() + data class Success( + val transactionId: String, + val currency: String, + ) : PayStatus() } +@Serializable +data class CheckPayTemplateResponse( + val templateDetails: WalletTemplateDetails, + val supportedCurrencies: List<String>, +) + class PaymentManager( private val api: WalletBackendApi, private val scope: CoroutineScope, @@ -67,50 +90,76 @@ class PaymentManager( @UiThread fun preparePay(url: String) = scope.launch { mPayStatus.value = PayStatus.Loading - api.request("preparePay", PreparePayResponse.serializer()) { + api.request("preparePayForUri", PreparePayResponse.serializer()) { put("talerPayUri", url) }.onError { - handleError("preparePay", it) + handleError("preparePayForUri", it) }.onSuccess { response -> mPayStatus.value = when (response) { is PaymentPossibleResponse -> response.toPayStatusPrepared() is InsufficientBalanceResponse -> InsufficientBalance( - response.contractTerms, - response.amountRaw + contractTerms = response.contractTerms, + amountRaw = response.amountRaw + ) + is AlreadyConfirmedResponse -> AlreadyPaid( + transactionId = response.transactionId, ) - is AlreadyConfirmedResponse -> AlreadyPaid } } } - fun confirmPay(proposalId: String, currency: String) = scope.launch { + fun confirmPay(transactionId: String, currency: String) = scope.launch { api.request("confirmPay", ConfirmPayResult.serializer()) { - put("proposalId", proposalId) + put("transactionId", transactionId) }.onError { handleError("confirmPay", it) - }.onSuccess { - mPayStatus.postValue(PayStatus.Success(currency)) + }.onSuccess { response -> + mPayStatus.postValue(when (response) { + is ConfirmPayResult.Done -> PayStatus.Success( + transactionId = response.transactionId, + currency = currency, + ) + is ConfirmPayResult.Pending -> PayStatus.Pending( + transactionId = response.transactionId, + error = response.lastError, + ) + }) } } - @UiThread - fun abortPay() { - val ps = payStatus.value - if (ps is PayStatus.Prepared) { - abortProposal(ps.proposalId) + fun checkPayForTemplate(url: String) = scope.launch { + mPayStatus.value = PayStatus.Loading + api.request("checkPayForTemplate", CheckPayTemplateResponse.serializer()) { + put("talerPayTemplateUri", url) + }.onError { + handleError("checkPayForTemplate", it) + }.onSuccess { response -> + mPayStatus.value = PayStatus.Checked( + details = response.templateDetails, + supportedCurrencies = response.supportedCurrencies, + ) } - resetPayStatus() } - internal fun abortProposal(proposalId: String) = scope.launch { - Log.i(TAG, "aborting proposal") - api.request<Unit>("abortProposal") { - put("proposalId", proposalId) + fun preparePayForTemplate(url: String, params: TemplateParams) = scope.launch { + mPayStatus.value = PayStatus.Loading + api.request("preparePayForTemplate", PreparePayResponse.serializer()) { + put("talerPayTemplateUri", url) + put("templateParams", JSONObject(BackendManager.json.encodeToString(params))) }.onError { - Log.e(TAG, "received error response to abortProposal") - handleError("abortProposal", it) - }.onSuccess { - mPayStatus.postValue(PayStatus.None) + handleError("preparePayForTemplate", it) + }.onSuccess { response -> + mPayStatus.value = when (response) { + is PaymentPossibleResponse -> response.toPayStatusPrepared() + is InsufficientBalanceResponse -> InsufficientBalance( + contractTerms = response.contractTerms, + amountRaw = response.amountRaw, + ) + + is AlreadyConfirmedResponse -> AlreadyPaid( + transactionId = response.transactionId, + ) + } } } @@ -121,7 +170,7 @@ class PaymentManager( private fun handleError(operation: String, error: TalerErrorInfo) { Log.e(TAG, "got $operation error result $error") - mPayStatus.value = PayStatus.Error(error.userFacingMsg) + mPayStatus.value = PayStatus.Pending(error = error) } } |