summaryrefslogtreecommitdiff
path: root/app/src/main/java/net/taler/wallet/payment/PaymentManager.kt
blob: 2e40250d77d93ff1fbde3a6785c33ea590a067ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package net.taler.wallet.payment

import android.util.Log
import androidx.annotation.UiThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import net.taler.wallet.Amount
import net.taler.wallet.TAG
import net.taler.wallet.backend.WalletBackendApi
import org.json.JSONObject

class PaymentManager(private val walletBackendApi: WalletBackendApi) {

    private val mPayStatus = MutableLiveData<PayStatus>(PayStatus.None)
    internal val payStatus: LiveData<PayStatus> = mPayStatus

    private var currentPayRequestId = 0

    @UiThread
    fun preparePay(url: String) {
        mPayStatus.value = PayStatus.Loading

        val args = JSONObject(mapOf("url" to url))

        currentPayRequestId += 1
        val payRequestId = currentPayRequestId

        walletBackendApi.sendRequest("preparePay", args) { isError, result ->
            when {
                isError -> {
                    Log.v(TAG, "got preparePay error result")
                    mPayStatus.value = PayStatus.Error(result.toString())
                }
                payRequestId != this.currentPayRequestId -> {
                    Log.v(TAG, "preparePay result was for old request")
                }
                else -> {
                    val status = result.getString("status")
                    mPayStatus.postValue(getPayStatusUpdate(status, result))
                }
            }
        }
    }

    private fun getPayStatusUpdate(status: String, json: JSONObject) = when (status) {
        "payment-possible" -> PayStatus.Prepared(
            contractTerms = getContractTerms(json),
            proposalId = json.getString("proposalId"),
            totalFees = Amount.fromJson(json.getJSONObject("totalFees"))
        )
        "paid" -> PayStatus.AlreadyPaid(getContractTerms(json))
        "insufficient-balance" -> PayStatus.InsufficientBalance(getContractTerms(json))
        "error" -> PayStatus.Error("got some error")
        else -> PayStatus.Error("unknown status")
    }

    private fun getContractTerms(json: JSONObject): ContractTerms {
        val ctJson = JSONObject(json.getString("contractTermsRaw"))
        val amount = Amount.fromString(ctJson.getString("amount"))
        val summary = ctJson.getString("summary")
        return ContractTerms(summary, amount)
    }

    fun confirmPay(proposalId: String) {
        val args = JSONObject(mapOf("proposalId" to proposalId))

        walletBackendApi.sendRequest("confirmPay", args) { _, _ ->
            mPayStatus.postValue(PayStatus.Success)
        }
    }

    fun abortProposal(proposalId: String) {
        val args = JSONObject(mapOf("proposalId" to proposalId))

        Log.i(TAG, "aborting proposal")

        walletBackendApi.sendRequest("abortProposal", args) { isError, _ ->
            if (isError) {
                Log.e(TAG, "received error response to abortProposal")
                return@sendRequest
            }
            mPayStatus.postValue(PayStatus.None)
        }
    }

    @UiThread
    fun resetPayStatus() {
        mPayStatus.value = PayStatus.None
    }

}

sealed class PayStatus {
    object None : PayStatus()
    object Loading : PayStatus()
    data class Prepared(
        val contractTerms: ContractTerms,
        val proposalId: String,
        val totalFees: Amount
    ) : PayStatus()

    data class InsufficientBalance(val contractTerms: ContractTerms) : PayStatus()
    data class AlreadyPaid(val contractTerms: ContractTerms) : PayStatus()
    data class Error(val error: String) : PayStatus()
    object Success : PayStatus()
}

data class ContractTerms(val summary: String, val amount: Amount)