aboutsummaryrefslogtreecommitdiff
path: root/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'wallet')
-rw-r--r--wallet/build.gradle5
-rw-r--r--wallet/proguard-rules.pro33
-rw-r--r--wallet/src/main/java/net/taler/wallet/MainViewModel.kt17
-rw-r--r--wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt36
-rw-r--r--wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt13
-rw-r--r--wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt25
-rw-r--r--wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt41
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt2
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt9
-rw-r--r--wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt164
-rw-r--r--wallet/src/test/java/net/taler/wallet/backend/WalletResponseTest.kt16
11 files changed, 126 insertions, 235 deletions
diff --git a/wallet/build.gradle b/wallet/build.gradle
index 8806a5a..ad3ba29 100644
--- a/wallet/build.gradle
+++ b/wallet/build.gradle
@@ -102,6 +102,8 @@ dependencies {
implementation project(":anastasis-ui")
implementation 'net.taler:akono:0.1'
+ implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
+
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
@@ -129,9 +131,6 @@ dependencies {
implementation "io.noties.markwon:ext-tables:$markwon_version"
implementation "io.noties.markwon:recycler:$markwon_version"
- // JSON parsing and serialization
- implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.10.2'
-
testImplementation 'junit:junit:4.13'
testImplementation 'org.json:json:20200518'
androidTestImplementation 'androidx.test:runner:1.2.0'
diff --git a/wallet/proguard-rules.pro b/wallet/proguard-rules.pro
index 147334d..27f3799 100644
--- a/wallet/proguard-rules.pro
+++ b/wallet/proguard-rules.pro
@@ -23,36 +23,3 @@
-keep class akono.AkonoJni {*;}
-keep class net.taler.wallet.** {*;}
-
-# Jackson
--keep @com.fasterxml.jackson.annotation.JsonIgnoreProperties class * { *; }
--keep @com.fasterxml.jackson.annotation.JsonCreator class * { *; }
--keep @com.fasterxml.jackson.annotation.JsonValue class * { *; }
--keep class com.fasterxml.** { *; }
--keep class org.codehaus.** { *; }
--keepnames class com.fasterxml.jackson.** { *; }
--keepclassmembers public final enum com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility {
- public static final com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility *;
-}
-
--keep class * extends com.fasterxml.** { *; }
--keep class * implements com.fasterxml.** { *; }
-
--keep class * {
- @com.fasterxml.** *;
-}
-
-# KotlinX serialization
--keep @kotlinx.serialization.Serializable class * { *; }
-
-# Kotlin reflection
--dontwarn kotlin.reflect.**
--keep class kotlin.** { *; }
--keep class org.jetbrains.annotations.** { *; }
-
-
-# General
--keepattributes SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,Signature,Exceptions,InnerClasses
--dontobfuscate
--dontoptimize
--dontshrink \ No newline at end of file
diff --git a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
index 3fc49a9..9e49f54 100644
--- a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
@@ -24,18 +24,11 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.viewModelScope
-import com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import net.taler.common.Event
import net.taler.common.assertUiThread
import net.taler.common.toEvent
-import net.taler.lib.common.Amount
-import net.taler.lib.common.AmountMixin
-import net.taler.lib.common.Timestamp
-import net.taler.lib.common.TimestampMixin
import net.taler.wallet.backend.WalletBackendApi
import net.taler.wallet.balances.BalanceItem
import net.taler.wallet.balances.BalanceResponse
@@ -70,12 +63,6 @@ class MainViewModel(val app: Application) : AndroidViewModel(app) {
var merchantVersion: String? = null
private set
- private val mapper = ObjectMapper()
- .registerModule(KotlinModule())
- .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
- .addMixIn(Amount::class.java, AmountMixin::class.java)
- .addMixIn(Timestamp::class.java, TimestampMixin::class.java)
-
private val api = WalletBackendApi(app) { payload ->
if (payload.optString("operation") == "init") {
val result = payload.getJSONObject("result")
@@ -99,9 +86,9 @@ class MainViewModel(val app: Application) : AndroidViewModel(app) {
}
val withdrawManager = WithdrawManager(api, viewModelScope)
- val paymentManager = PaymentManager(api, viewModelScope, mapper)
+ val paymentManager = PaymentManager(api, viewModelScope)
val pendingOperationsManager: PendingOperationsManager = PendingOperationsManager(api)
- val transactionManager: TransactionManager = TransactionManager(api, viewModelScope, mapper)
+ val transactionManager: TransactionManager = TransactionManager(api, viewModelScope)
val refundManager = RefundManager(api, viewModelScope)
val exchangeManager: ExchangeManager = ExchangeManager(api, viewModelScope)
diff --git a/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt b/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt
index 693fe7e..c6261bf 100644
--- a/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt
+++ b/wallet/src/main/java/net/taler/wallet/backend/WalletBackendApi.kt
@@ -26,12 +26,11 @@ import android.os.IBinder
import android.os.Message
import android.os.Messenger
import android.util.Log
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.readValue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
+import net.taler.lib.android.CustomClassDiscriminator
import net.taler.wallet.backend.WalletBackendService.Companion.MSG_COMMAND
import net.taler.wallet.backend.WalletBackendService.Companion.MSG_NOTIFY
import net.taler.wallet.backend.WalletBackendService.Companion.MSG_REPLY
@@ -43,14 +42,12 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
+import kotlin.reflect.full.companionObjectInstance
class WalletBackendApi(
private val app: Application,
private val notificationHandler: ((payload: JSONObject) -> Unit)
) {
- private val json = Json {
- ignoreUnknownKeys = true
- }
private var walletBackendMessenger: Messenger? = null
private val queuedMessages = LinkedList<Message>()
private val handlers = ConcurrentHashMap<Int, (isError: Boolean, message: JSONObject) -> Unit>()
@@ -147,12 +144,18 @@ class WalletBackendApi(
}
}
- suspend fun <T> request(
+ suspend inline fun <reified T> request(
operation: String,
serializer: KSerializer<T>? = null,
- args: (JSONObject.() -> JSONObject)? = null
+ noinline args: (JSONObject.() -> JSONObject)? = null
): WalletResponse<T> = withContext(Dispatchers.Default) {
suspendCoroutine { cont ->
+ val json = Json {
+ ignoreUnknownKeys = true
+ (T::class.companionObjectInstance as? CustomClassDiscriminator)?.let {
+ classDiscriminator = it.discriminator
+ }
+ }
sendRequest(operation, args?.invoke(JSONObject())) { isError, message ->
val response = if (isError) {
val error = json.decodeFromString(WalletErrorInfo.serializer(), message.toString())
@@ -167,25 +170,6 @@ class WalletBackendApi(
}
}
- suspend inline fun <reified T> request(
- operation: String,
- mapper: ObjectMapper,
- noinline args: (JSONObject.() -> JSONObject)? = null
- ): WalletResponse<T> = withContext(Dispatchers.Default) {
- suspendCoroutine { cont ->
- sendRequest(operation, args?.invoke(JSONObject())) { isError, message ->
- val response = if (isError) {
- val error: WalletErrorInfo = mapper.readValue(message.toString())
- WalletResponse.Error(error)
- } else {
- val t: T = mapper.readValue(message.toString())
- WalletResponse.Success(t)
- }
- cont.resume(response)
- }
- }
- }
-
fun destroy() {
// FIXME: implement this!
}
diff --git a/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt b/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt
index 57ce82e..4b39ff8 100644
--- a/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt
+++ b/wallet/src/main/java/net/taler/wallet/backend/WalletResponse.kt
@@ -16,11 +16,6 @@
package net.taler.wallet.backend
-import com.fasterxml.jackson.core.JsonParser
-import com.fasterxml.jackson.databind.DeserializationContext
-import com.fasterxml.jackson.databind.JsonNode
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
-import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -72,7 +67,6 @@ data class WalletErrorInfo(
// Error details, type depends on talerErrorCode
@Serializable(JSONObjectDeserializer::class)
- @JsonDeserialize(using = JsonObjectDeserializer::class)
val details: JSONObject?
) {
val userFacingMsg: String
@@ -107,10 +101,3 @@ class JSONObjectDeserializer : KSerializer<JSONObject> {
error("not supported")
}
}
-
-class JsonObjectDeserializer : StdDeserializer<JSONObject>(JSONObject::class.java) {
- override fun deserialize(p: JsonParser, ctxt: DeserializationContext): JSONObject {
- val node: JsonNode = p.codec.readTree(p)
- return JSONObject(node.toString())
- }
-}
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 4924752..befcd83 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentManager.kt
@@ -20,12 +20,10 @@ import android.util.Log
import androidx.annotation.UiThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.readValue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
-import net.taler.lib.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.WalletErrorInfo
@@ -34,8 +32,6 @@ 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
-import java.net.MalformedURLException
val REGEX_PRODUCT_IMAGE = Regex("^data:image/(jpeg|png);base64,([A-Za-z0-9+/=]+)$")
@@ -63,7 +59,6 @@ sealed class PayStatus {
class PaymentManager(
private val api: WalletBackendApi,
private val scope: CoroutineScope,
- private val mapper: ObjectMapper
) {
private val mPayStatus = MutableLiveData<PayStatus>(PayStatus.None)
@@ -76,7 +71,7 @@ class PaymentManager(
fun preparePay(url: String) = scope.launch {
mPayStatus.value = PayStatus.Loading
mDetailsShown.value = false
- api.request<PreparePayResponse>("preparePay", mapper) {
+ api.request("preparePay", PreparePayResponse.serializer()) {
put("talerPayUri", url)
}.onError {
handleError("preparePay", it)
@@ -93,20 +88,6 @@ class PaymentManager(
}
}
- // TODO validate product images (or leave to wallet-core?)
- private fun getContractTerms(json: JSONObject): ContractTerms {
- val terms: ContractTerms = mapper.readValue(json.getString("contractTermsRaw"))
- // validate product images
- terms.products.forEach { product ->
- product.image?.let { image ->
- if (REGEX_PRODUCT_IMAGE.matchEntire(image) == null) {
- throw MalformedURLException("Invalid image data URL for ${product.description}")
- }
- }
- }
- return terms
- }
-
fun confirmPay(proposalId: String, currency: String) = scope.launch {
api.request("confirmPay", ConfirmPayResult.serializer()) {
put("proposalId", proposalId)
@@ -128,7 +109,7 @@ class PaymentManager(
internal fun abortProposal(proposalId: String) = scope.launch {
Log.i(TAG, "aborting proposal")
- api.request<String>("abortProposal", mapper) {
+ api.request<Unit>("abortProposal") {
put("proposalId", proposalId)
}.onError {
Log.e(TAG, "received error response to abortProposal")
diff --git a/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt b/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt
index c490654..19007b0 100644
--- a/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt
+++ b/wallet/src/main/java/net/taler/wallet/payment/PaymentResponses.kt
@@ -16,42 +16,47 @@
package net.taler.wallet.payment
-import com.fasterxml.jackson.annotation.JsonTypeInfo
-import com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME
-import com.fasterxml.jackson.annotation.JsonTypeName
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import net.taler.common.ContractTerms
+import net.taler.lib.android.CustomClassDiscriminator
import net.taler.lib.common.Amount
import net.taler.wallet.transactions.TransactionError
-@JsonTypeInfo(use = NAME, property = "status")
-sealed class PreparePayResponse(open val proposalId: String) {
- @JsonTypeName("payment-possible")
+@Serializable
+sealed class PreparePayResponse {
+ companion object : CustomClassDiscriminator {
+ override val discriminator: String = "status"
+ }
+
+ @Serializable
+ @SerialName("payment-possible")
data class PaymentPossibleResponse(
- override val proposalId: String,
+ val proposalId: String,
val amountRaw: Amount,
val amountEffective: Amount,
- val contractTerms: ContractTerms
- ) : PreparePayResponse(proposalId) {
+ val contractTerms: ContractTerms,
+ ) : PreparePayResponse() {
fun toPayStatusPrepared() = PayStatus.Prepared(
contractTerms = contractTerms,
proposalId = proposalId,
amountRaw = amountRaw,
- amountEffective = amountEffective
+ amountEffective = amountEffective,
)
}
- @JsonTypeName("insufficient-balance")
+ @Serializable
+ @SerialName("insufficient-balance")
data class InsufficientBalanceResponse(
- override val proposalId: String,
+ val proposalId: String,
val amountRaw: Amount,
- val contractTerms: ContractTerms
- ) : PreparePayResponse(proposalId)
+ val contractTerms: ContractTerms,
+ ) : PreparePayResponse()
- @JsonTypeName("already-confirmed")
+ @Serializable
+ @SerialName("already-confirmed")
data class AlreadyConfirmedResponse(
- override val proposalId: String,
+ val proposalId: String,
/**
* Did the payment succeed?
*/
@@ -62,8 +67,8 @@ sealed class PreparePayResponse(open val proposalId: String) {
/**
* Redirect URL for the fulfillment page, only given if paid==true.
*/
- val nextUrl: String?
- ) : PreparePayResponse(proposalId)
+ val nextUrl: String?,
+ ) : PreparePayResponse()
}
@Serializable
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
index f494b05..9dc2d23 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionAdapter.kt
@@ -104,7 +104,7 @@ internal class TransactionAdapter(
private fun bindExtraInfo(transaction: Transaction) {
if (transaction.error != null) {
extraInfoView.text =
- context.getString(R.string.payment_error, transaction.error.text)
+ context.getString(R.string.payment_error, transaction.error!!.text)
extraInfoView.setTextColor(red)
extraInfoView.visibility = VISIBLE
} else if (transaction is TransactionWithdrawal && !transaction.confirmed) {
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
index e9b1b71..6b5a79b 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/TransactionManager.kt
@@ -20,11 +20,11 @@ import androidx.annotation.UiThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.switchMap
-import com.fasterxml.jackson.databind.ObjectMapper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import net.taler.wallet.backend.WalletBackendApi
import java.util.HashMap
+import java.util.LinkedList
sealed class TransactionsResult {
class Error(val msg: String) : TransactionsResult()
@@ -33,8 +33,7 @@ sealed class TransactionsResult {
class TransactionManager(
private val api: WalletBackendApi,
- private val scope: CoroutineScope,
- private val mapper: ObjectMapper
+ private val scope: CoroutineScope
) {
private val mProgress = MutableLiveData<Boolean>()
@@ -64,14 +63,14 @@ class TransactionManager(
}
if (liveData.value == null) mProgress.value = true
- api.request<Transactions>("getTransactions", mapper) {
+ api.request("getTransactions", Transactions.serializer()) {
if (searchQuery != null) put("search", searchQuery)
put("currency", currency)
}.onError {
liveData.postValue(TransactionsResult.Error(it.userFacingMsg))
mProgress.postValue(false)
}.onSuccess { result ->
- val transactions = result.transactions
+ val transactions = LinkedList(result.transactions)
// TODO remove when fixed in wallet-core
val comparator = compareBy<Transaction>(
{ it.pending },
diff --git a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
index 1ed6788..8c00540 100644
--- a/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
+++ b/wallet/src/main/java/net/taler/wallet/transactions/Transactions.kt
@@ -20,42 +20,30 @@ import android.content.Context
import androidx.annotation.DrawableRes
import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.fasterxml.jackson.annotation.JsonSubTypes
-import com.fasterxml.jackson.annotation.JsonSubTypes.Type
-import com.fasterxml.jackson.annotation.JsonTypeInfo
-import com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY
-import com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME
-import com.fasterxml.jackson.annotation.JsonTypeName
+import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
-import net.taler.lib.common.Amount
+import kotlinx.serialization.Transient
import net.taler.common.ContractMerchant
import net.taler.common.ContractProduct
+import net.taler.lib.common.Amount
import net.taler.lib.common.Timestamp
import net.taler.wallet.R
import net.taler.wallet.cleanExchange
import net.taler.wallet.transactions.WithdrawalDetails.ManualTransfer
import net.taler.wallet.transactions.WithdrawalDetails.TalerBankIntegrationApi
-import java.util.LinkedList
-data class Transactions(val transactions: LinkedList<Transaction>)
+@Serializable
+data class Transactions(val transactions: List<Transaction>)
+
+@Serializable
+sealed class Transaction {
+ abstract val transactionId: String
+ abstract val timestamp: Timestamp
+ abstract val pending: Boolean
+ abstract val error: TransactionError?
+ abstract val amountRaw: Amount
+ abstract val amountEffective: Amount
-@JsonTypeInfo(use = NAME, include = PROPERTY, property = "type")
-@JsonSubTypes(
- Type(value = TransactionWithdrawal::class, name = "withdrawal"),
- Type(value = TransactionPayment::class, name = "payment"),
- Type(value = TransactionRefund::class, name = "refund"),
- Type(value = TransactionTip::class, name = "tip"),
- Type(value = TransactionRefresh::class, name = "refresh")
-)
-abstract class Transaction(
- val transactionId: String,
- val timestamp: Timestamp,
- val pending: Boolean,
- val error: TransactionError? = null,
- val amountRaw: Amount,
- val amountEffective: Amount
-) {
@get:DrawableRes
abstract val icon: Int
@@ -79,24 +67,26 @@ sealed class AmountType {
@Serializable
data class TransactionError(
private val ec: Int,
- private val hint: String?
+ private val hint: String? = null,
) {
val text get() = if (hint == null) "$ec" else "$ec $hint"
}
-@JsonTypeName("withdrawal")
+@Serializable
+@SerialName("withdrawal")
class TransactionWithdrawal(
- transactionId: String,
- timestamp: Timestamp,
- pending: Boolean,
+ override val transactionId: String,
+ override val timestamp: Timestamp,
+ override val pending: Boolean,
val exchangeBaseUrl: String,
val withdrawalDetails: WithdrawalDetails,
- error: TransactionError? = null,
- amountRaw: Amount,
- amountEffective: Amount
-) : Transaction(transactionId, timestamp, pending, error, amountRaw, amountEffective) {
+ override val error: TransactionError? = null,
+ override val amountRaw: Amount,
+ override val amountEffective: Amount
+) : Transaction() {
override val icon = R.drawable.transaction_withdrawal
override val detailPageLayout = R.layout.fragment_transaction_withdrawal
+ @Transient
override val amountType = AmountType.Positive
override fun getTitle(context: Context) = cleanExchange(exchangeBaseUrl)
override val generalTitleRes = R.string.withdraw_title
@@ -107,13 +97,10 @@ class TransactionWithdrawal(
)
}
-@JsonTypeInfo(use = NAME, include = PROPERTY, property = "type")
-@JsonSubTypes(
- Type(value = TalerBankIntegrationApi::class, name = "taler-bank-integration-api"),
- Type(value = ManualTransfer::class, name = "manual-transfer")
-)
+@Serializable
sealed class WithdrawalDetails {
- @JsonTypeName("manual-transfer")
+ @Serializable
+ @SerialName("manual-transfer")
class ManualTransfer(
/**
* Payto URIs that the exchange supports.
@@ -123,7 +110,8 @@ sealed class WithdrawalDetails {
val exchangePaytoUris: List<String>
) : WithdrawalDetails()
- @JsonTypeName("taler-bank-integration-api")
+ @Serializable
+ @SerialName("taler-bank-integration-api")
class TalerBankIntegrationApi(
/**
* Set to true if the bank has confirmed the withdrawal, false if not.
@@ -136,71 +124,77 @@ sealed class WithdrawalDetails {
/**
* If the withdrawal is unconfirmed, this can include a URL for user-initiated confirmation.
*/
- val bankConfirmationUrl: String?
+ val bankConfirmationUrl: String? = null,
) : WithdrawalDetails()
}
-@JsonTypeName("payment")
+@Serializable
+@SerialName("payment")
class TransactionPayment(
- transactionId: String,
- timestamp: Timestamp,
- pending: Boolean,
+ override val transactionId: String,
+ override val timestamp: Timestamp,
+ override val pending: Boolean,
val info: TransactionInfo,
val status: PaymentStatus,
- error: TransactionError? = null,
- amountRaw: Amount,
- amountEffective: Amount
-) : Transaction(transactionId, timestamp, pending, error, amountRaw, amountEffective) {
+ override val error: TransactionError? = null,
+ override val amountRaw: Amount,
+ override val amountEffective: Amount
+) : Transaction() {
override val icon = R.drawable.ic_cash_usd_outline
override val detailPageLayout = R.layout.fragment_transaction_payment
+ @Transient
override val amountType = AmountType.Negative
override fun getTitle(context: Context) = info.merchant.name
override val generalTitleRes = R.string.payment_title
}
+@Serializable
class TransactionInfo(
val orderId: String,
val merchant: ContractMerchant,
val summary: String,
- @get:JsonProperty("summary_i18n")
- val summaryI18n: Map<String, String>?,
+ @SerialName("summary_i18n")
+ val summaryI18n: Map<String, String>? = null,
val products: List<ContractProduct>,
val fulfillmentUrl: String
)
+@Serializable
enum class PaymentStatus {
- @JsonProperty("aborted")
+ @SerialName("aborted")
Aborted,
- @JsonProperty("failed")
+ @SerialName("failed")
Failed,
- @JsonProperty("paid")
+ @SerialName("paid")
Paid,
- @JsonProperty("accepted")
+ @SerialName("accepted")
Accepted
}
-@JsonTypeName("refund")
+@Serializable
+@SerialName("refund")
class TransactionRefund(
- transactionId: String,
- timestamp: Timestamp,
- pending: Boolean,
+ override val transactionId: String,
+ override val timestamp: Timestamp,
+ override val pending: Boolean,
val refundedTransactionId: String,
val info: TransactionInfo,
/**
* Part of the refund that couldn't be applied because the refund permissions were expired
*/
val amountInvalid: Amount? = null,
- error: TransactionError? = null,
- @JsonProperty("amountEffective") // TODO remove when fixed in wallet-core
- amountRaw: Amount,
- @JsonProperty("amountRaw") // TODO remove when fixed in wallet-core
- amountEffective: Amount
-) : Transaction(transactionId, timestamp, pending, error, amountRaw, amountEffective) {
+ override val error: TransactionError? = null,
+ @SerialName("amountEffective") // TODO remove when fixed in wallet-core
+ override val amountRaw: Amount,
+ @SerialName("amountRaw") // TODO remove when fixed in wallet-core
+ override val amountEffective: Amount
+) : Transaction() {
override val icon = R.drawable.transaction_refund
override val detailPageLayout = R.layout.fragment_transaction_payment
+ @Transient
override val amountType = AmountType.Positive
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_refund_from, info.merchant.name)
@@ -209,20 +203,22 @@ class TransactionRefund(
override val generalTitleRes = R.string.refund_title
}
-@JsonTypeName("tip")
+@Serializable
+@SerialName("tip")
class TransactionTip(
- transactionId: String,
- timestamp: Timestamp,
- pending: Boolean,
+ override val transactionId: String,
+ override val timestamp: Timestamp,
+ override val pending: Boolean,
// TODO status: TipStatus,
val exchangeBaseUrl: String,
val merchant: ContractMerchant,
- error: TransactionError? = null,
- amountRaw: Amount,
- amountEffective: Amount
-) : Transaction(transactionId, timestamp, pending, error, amountRaw, amountEffective) {
+ override val error: TransactionError? = null,
+ override val amountRaw: Amount,
+ override val amountEffective: Amount
+) : Transaction() {
override val icon = R.drawable.transaction_tip_accepted // TODO different when declined
override val detailPageLayout = R.layout.fragment_transaction_payment
+ @Transient
override val amountType = AmountType.Positive
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_tip_from, merchant.name)
@@ -231,18 +227,20 @@ class TransactionTip(
override val generalTitleRes = R.string.tip_title
}
-@JsonTypeName("refresh")
+@Serializable
+@SerialName("refresh")
class TransactionRefresh(
- transactionId: String,
- timestamp: Timestamp,
- pending: Boolean,
+ override val transactionId: String,
+ override val timestamp: Timestamp,
+ override val pending: Boolean,
val exchangeBaseUrl: String,
- error: TransactionError? = null,
- amountRaw: Amount,
- amountEffective: Amount
-) : Transaction(transactionId, timestamp, pending, error, amountRaw, amountEffective) {
+ override val error: TransactionError? = null,
+ override val amountRaw: Amount,
+ override val amountEffective: Amount
+) : Transaction() {
override val icon = R.drawable.transaction_refresh
override val detailPageLayout = R.layout.fragment_transaction_withdrawal
+ @Transient
override val amountType = AmountType.Negative
override fun getTitle(context: Context): String {
return context.getString(R.string.transaction_refresh)
diff --git a/wallet/src/test/java/net/taler/wallet/backend/WalletResponseTest.kt b/wallet/src/test/java/net/taler/wallet/backend/WalletResponseTest.kt
index a81626c..4872149 100644
--- a/wallet/src/test/java/net/taler/wallet/backend/WalletResponseTest.kt
+++ b/wallet/src/test/java/net/taler/wallet/backend/WalletResponseTest.kt
@@ -16,15 +16,7 @@
package net.taler.wallet.backend
-import com.fasterxml.jackson.databind.DeserializationFeature
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.kotlin.KotlinModule
-import com.fasterxml.jackson.module.kotlin.readValue
import kotlinx.serialization.json.Json
-import net.taler.lib.common.Amount
-import net.taler.lib.common.AmountMixin
-import net.taler.lib.common.Timestamp
-import net.taler.lib.common.TimestampMixin
import net.taler.wallet.balances.BalanceResponse
import org.junit.Assert.assertEquals
import org.junit.Test
@@ -35,12 +27,6 @@ class WalletResponseTest {
ignoreUnknownKeys = true
}
- private val mapper = ObjectMapper()
- .registerModule(KotlinModule())
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
- .addMixIn(Amount::class.java, AmountMixin::class.java)
- .addMixIn(Timestamp::class.java, TimestampMixin::class.java)
-
@Test
fun testBalanceResponse() {
val serializer = WalletResponse.Success.serializer(BalanceResponse.serializer())
@@ -82,8 +68,6 @@ class WalletResponseTest {
}
""".trimIndent()
val info = json.decodeFromString(WalletErrorInfo.serializer(), infoJson)
- val infoJackson: WalletErrorInfo = mapper.readValue(infoJson)
println(info.userFacingMsg)
- assertEquals(info.userFacingMsg, infoJackson.userFacingMsg)
}
}