summaryrefslogtreecommitdiff
path: root/merchant-lib/src/main/java/net/taler/merchantlib
diff options
context:
space:
mode:
Diffstat (limited to 'merchant-lib/src/main/java/net/taler/merchantlib')
-rw-r--r--merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt63
-rw-r--r--merchant-lib/src/main/java/net/taler/merchantlib/OrderHistory.kt4
-rw-r--r--merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt12
-rw-r--r--merchant-lib/src/main/java/net/taler/merchantlib/Refunds.kt3
-rw-r--r--merchant-lib/src/main/java/net/taler/merchantlib/Response.kt18
5 files changed, 51 insertions, 49 deletions
diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt b/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt
index a467c41..950cea6 100644
--- a/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt
+++ b/merchant-lib/src/main/java/net/taler/merchantlib/MerchantApi.kt
@@ -17,16 +17,19 @@
package net.taler.merchantlib
import io.ktor.client.HttpClient
+import io.ktor.client.call.body
import io.ktor.client.engine.okhttp.OkHttp
-import io.ktor.client.features.json.JsonFeature
-import io.ktor.client.features.json.serializer.KotlinxSerializer
+import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
+import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.delete
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.request.post
+import io.ktor.client.request.setBody
import io.ktor.http.ContentType.Application.Json
import io.ktor.http.HttpHeaders.Authorization
import io.ktor.http.contentType
+import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -35,47 +38,47 @@ import net.taler.merchantlib.Response.Companion.response
class MerchantApi(
private val httpClient: HttpClient = getDefaultHttpClient(),
- private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
+ private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO,
) {
suspend fun getConfig(baseUrl: String): Response<ConfigResponse> = withContext(ioDispatcher) {
response {
- httpClient.get("$baseUrl/config") as ConfigResponse
+ httpClient.get("$baseUrl/config").body()
}
}
suspend fun postOrder(
merchantConfig: MerchantConfig,
- orderRequest: PostOrderRequest
+ orderRequest: PostOrderRequest,
): Response<PostOrderResponse> = withContext(ioDispatcher) {
response {
httpClient.post(merchantConfig.urlFor("private/orders")) {
- header(Authorization, "ApiKey ${merchantConfig.apiKey}")
+ auth(merchantConfig)
contentType(Json)
- body = orderRequest
- } as PostOrderResponse
+ setBody(orderRequest)
+ }.body()
}
}
suspend fun checkOrder(
merchantConfig: MerchantConfig,
- orderId: String
+ orderId: String,
): Response<CheckPaymentResponse> = withContext(ioDispatcher) {
response {
httpClient.get(merchantConfig.urlFor("private/orders/$orderId")) {
- header(Authorization, "ApiKey ${merchantConfig.apiKey}")
- } as CheckPaymentResponse
+ auth(merchantConfig)
+ }.body()
}
}
suspend fun deleteOrder(
merchantConfig: MerchantConfig,
- orderId: String
+ orderId: String,
): Response<Unit> = withContext(ioDispatcher) {
response {
httpClient.delete(merchantConfig.urlFor("private/orders/$orderId")) {
- header(Authorization, "ApiKey ${merchantConfig.apiKey}")
- } as Unit
+ auth(merchantConfig)
+ }.body()
}
}
@@ -83,41 +86,41 @@ class MerchantApi(
withContext(ioDispatcher) {
response {
httpClient.get(merchantConfig.urlFor("private/orders")) {
- header(Authorization, "ApiKey ${merchantConfig.apiKey}")
- } as OrderHistory
+ auth(merchantConfig)
+ }.body()
}
}
suspend fun giveRefund(
merchantConfig: MerchantConfig,
orderId: String,
- request: RefundRequest
+ request: RefundRequest,
): Response<RefundResponse> = withContext(ioDispatcher) {
response {
httpClient.post(merchantConfig.urlFor("private/orders/$orderId/refund")) {
- header(Authorization, "ApiKey ${merchantConfig.apiKey}")
+ auth(merchantConfig)
contentType(Json)
- body = request
- } as RefundResponse
+ setBody(request)
+ }.body()
}
}
+
+ private fun HttpRequestBuilder.auth(merchantConfig: MerchantConfig) {
+ header(Authorization, "Bearer ${merchantConfig.apiKey}")
+ }
}
fun getDefaultHttpClient(): HttpClient = HttpClient(OkHttp) {
+ expectSuccess = true
engine {
config {
retryOnConnectionFailure(true)
}
}
- install(JsonFeature) {
- serializer = getSerializer()
+ install(ContentNegotiation) {
+ json(Json {
+ encodeDefaults = false
+ ignoreUnknownKeys = true
+ })
}
}
-
-fun getSerializer() = KotlinxSerializer(
- Json {
- encodeDefaults = false
- ignoreUnknownKeys = true
- classDiscriminator = "order_status"
- }
-)
diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/OrderHistory.kt b/merchant-lib/src/main/java/net/taler/merchantlib/OrderHistory.kt
index dfd989b..b1ff5b1 100644
--- a/merchant-lib/src/main/java/net/taler/merchantlib/OrderHistory.kt
+++ b/merchant-lib/src/main/java/net/taler/merchantlib/OrderHistory.kt
@@ -18,8 +18,8 @@ package net.taler.merchantlib
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
-import net.taler.lib.common.Amount
-import net.taler.lib.common.Timestamp
+import net.taler.common.Amount
+import net.taler.common.Timestamp
@Serializable
data class OrderHistory(
diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt b/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt
index 166ca3c..9348ded 100644
--- a/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt
+++ b/merchant-lib/src/main/java/net/taler/merchantlib/Orders.kt
@@ -16,18 +16,19 @@
package net.taler.merchantlib
+import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.JsonClassDiscriminator
import net.taler.common.ContractTerms
-import net.taler.lib.android.CustomClassDiscriminator
-import net.taler.lib.common.Duration
+import net.taler.common.RelativeTime
@Serializable
data class PostOrderRequest(
@SerialName("order")
val contractTerms: ContractTerms,
@SerialName("refund_delay")
- val refundDelay: Duration? = null
+ val refundDelay: RelativeTime? = null
)
@Serializable
@@ -36,9 +37,10 @@ data class PostOrderResponse(
val orderId: String
)
+@OptIn(ExperimentalSerializationApi::class)
@Serializable
-sealed class CheckPaymentResponse: CustomClassDiscriminator {
- override val discriminator: String = "order_status"
+@JsonClassDiscriminator("order_status")
+sealed class CheckPaymentResponse {
abstract val paid: Boolean
@Serializable
diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/Refunds.kt b/merchant-lib/src/main/java/net/taler/merchantlib/Refunds.kt
index b78b571..58073fa 100644
--- a/merchant-lib/src/main/java/net/taler/merchantlib/Refunds.kt
+++ b/merchant-lib/src/main/java/net/taler/merchantlib/Refunds.kt
@@ -18,8 +18,7 @@ package net.taler.merchantlib
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
-import net.taler.lib.common.Amount
-
+import net.taler.common.Amount
@Serializable
data class RefundRequest(
/**
diff --git a/merchant-lib/src/main/java/net/taler/merchantlib/Response.kt b/merchant-lib/src/main/java/net/taler/merchantlib/Response.kt
index 1b63900..55de077 100644
--- a/merchant-lib/src/main/java/net/taler/merchantlib/Response.kt
+++ b/merchant-lib/src/main/java/net/taler/merchantlib/Response.kt
@@ -16,10 +16,8 @@
package net.taler.merchantlib
-import io.ktor.client.call.receive
-import io.ktor.client.features.ClientRequestException
-import io.ktor.client.features.ResponseException
-import io.ktor.client.features.ServerResponseException
+import io.ktor.client.call.body
+import io.ktor.client.plugins.ResponseException
import kotlinx.serialization.Serializable
class Response<out T> private constructor(
@@ -64,16 +62,15 @@ class Response<out T> private constructor(
}
private suspend fun getFailureString(failure: Failure): String = when (failure.exception) {
- is ClientRequestException -> getExceptionString(failure.exception)
- is ServerResponseException -> getExceptionString(failure.exception)
+ is ResponseException -> getExceptionString(failure.exception)
else -> failure.exception.toString()
}
private suspend fun getExceptionString(e: ResponseException): String {
- val response = e.response ?: return e.toString()
+ val response = e.response
return try {
- val error: Error = response.receive()
- "Error ${error.code}: ${error.hint}"
+ val error: Error = response.body()
+ "Error ${error.code} (${response.status.value}): ${error.hint} ${error.detail}"
} catch (ex: Exception) {
"Status code: ${response.status.value}"
}
@@ -84,6 +81,7 @@ class Response<out T> private constructor(
@Serializable
private class Error(
val code: Int?,
- val hint: String?
+ val hint: String?,
+ val detail: String? = null,
)
}