summaryrefslogtreecommitdiff
path: root/merchant-terminal
diff options
context:
space:
mode:
authorTorsten Grote <t@grobox.de>2020-07-22 16:53:06 -0300
committerTorsten Grote <t@grobox.de>2020-07-22 16:53:06 -0300
commita8c811f6cdf4bf1b787ebaaa9fd220588fd1ffcf (patch)
tree604cd516a904f9c7474e37a87f92018f55ca4d1b /merchant-terminal
parentb9d7d6edb7cc12e5238168c4446a28c0ae98c729 (diff)
downloadtaler-android-a8c811f6cdf4bf1b787ebaaa9fd220588fd1ffcf.tar.gz
taler-android-a8c811f6cdf4bf1b787ebaaa9fd220588fd1ffcf.tar.bz2
taler-android-a8c811f6cdf4bf1b787ebaaa9fd220588fd1ffcf.zip
[pos] migrate order posting and checking to v1 API and merchant-lib
Diffstat (limited to 'merchant-terminal')
-rw-r--r--merchant-terminal/.gitlab-ci.yml1
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/MainViewModel.kt2
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantConfig.kt5
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantRequest.kt1
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/order/Order.kt21
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/order/OrderManager.kt2
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/payment/Payment.kt2
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt113
-rw-r--r--merchant-terminal/src/main/java/net/taler/merchantpos/payment/ProcessPaymentFragment.kt6
-rw-r--r--merchant-terminal/src/main/res/values/strings.xml2
10 files changed, 65 insertions, 90 deletions
diff --git a/merchant-terminal/.gitlab-ci.yml b/merchant-terminal/.gitlab-ci.yml
index 034818c..74ac21f 100644
--- a/merchant-terminal/.gitlab-ci.yml
+++ b/merchant-terminal/.gitlab-ci.yml
@@ -3,6 +3,7 @@ merchant_test:
only:
changes:
- merchant-terminal/**/*
+ - merchant-lib/**/*
- taler-kotlin-common/**/*
- build.gradle
script: ./gradlew :merchant-terminal:check :merchant-terminal:assembleRelease
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/MainViewModel.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/MainViewModel.kt
index 2dd2c24..ce05980 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/MainViewModel.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/MainViewModel.kt
@@ -42,7 +42,7 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
val configManager = ConfigManager(app, viewModelScope, api, mapper, queue).apply {
addConfigurationReceiver(orderManager)
}
- val paymentManager = PaymentManager(configManager, queue, mapper)
+ val paymentManager = PaymentManager(app, configManager, viewModelScope, api)
val historyManager = HistoryManager(configManager, queue, mapper)
val refundManager = RefundManager(configManager, queue)
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantConfig.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantConfig.kt
index 0e707d3..0c7e3b7 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantConfig.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantConfig.kt
@@ -23,7 +23,7 @@ import net.taler.common.Amount
import net.taler.common.ContractProduct
import net.taler.common.Product
import net.taler.common.TalerUtils
-import java.util.*
+import java.util.UUID
data class Config(
val configUrl: String,
@@ -50,6 +50,9 @@ data class MerchantConfig(
}
return uriBuilder.toString()
}
+ fun convert() = net.taler.merchantlib.MerchantConfig(
+ baseUrl, instance, apiKey
+ )
}
data class Category(
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantRequest.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantRequest.kt
index 6c9c741..9cfae94 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantRequest.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/config/MerchantRequest.kt
@@ -16,7 +16,6 @@
package net.taler.merchantpos.config
-
import android.util.ArrayMap
import com.android.volley.Response
import com.android.volley.toolbox.JsonObjectRequest
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/order/Order.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/order/Order.kt
index ff6e6b7..bb75362 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/order/Order.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/order/Order.kt
@@ -17,8 +17,13 @@
package net.taler.merchantpos.order
import net.taler.common.Amount
+import net.taler.common.ContractTerms
+import net.taler.common.now
import net.taler.merchantpos.config.Category
import net.taler.merchantpos.config.ConfigProduct
+import java.net.URLEncoder
+
+private const val FULFILLMENT_PREFIX = "taler://fulfillment-success/"
data class Order(val id: Int, val currency: String, val availableCategories: Map<Int, Category>) {
val products = ArrayList<ConfigProduct>()
@@ -103,4 +108,20 @@ data class Order(val id: Int, val currency: String, val availableCategories: Map
}.toMap()
}
+ private val fulfillmentUri: String
+ get() {
+ val fulfillmentId = "${now()}-${hashCode()}"
+ return "$FULFILLMENT_PREFIX${URLEncoder.encode(summary, "UTF-8")}#$fulfillmentId"
+ }
+
+ fun toContractTerms(): ContractTerms {
+ return ContractTerms(
+ summary = summary,
+ summaryI18n = summaryI18n,
+ amount = total,
+ fulfillmentUrl = fulfillmentUri,
+ products = products.map { it.toContractProduct() }
+ )
+ }
+
}
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/order/OrderManager.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/order/OrderManager.kt
index ff2be48..46ea238 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/order/OrderManager.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/order/OrderManager.kt
@@ -113,7 +113,7 @@ class OrderManager(
@UiThread
internal fun getOrder(orderId: Int): LiveOrder {
- return orders[orderId] ?: throw IllegalArgumentException()
+ return orders[orderId] ?: throw IllegalArgumentException("Order not found: $orderId")
}
@UiThread
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/Payment.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/Payment.kt
index b7e4a4b..9200ced 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/Payment.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/Payment.kt
@@ -25,5 +25,5 @@ data class Payment(
val orderId: String? = null,
val talerPayUri: String? = null,
val paid: Boolean = false,
- val error: Boolean = false
+ val error: String? = null
)
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
index 9138740..e238284 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/PaymentManager.kt
@@ -16,42 +16,33 @@
package net.taler.merchantpos.payment
+import android.content.Context
import android.os.CountDownTimer
-import android.util.Log
import androidx.annotation.UiThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
-import com.android.volley.Request.Method.GET
-import com.android.volley.Request.Method.POST
-import com.android.volley.RequestQueue
-import com.android.volley.Response.Listener
-import com.fasterxml.jackson.databind.ObjectMapper
-import net.taler.common.Timestamp
-import net.taler.common.now
-import net.taler.merchantpos.LogErrorListener
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import net.taler.merchantlib.CheckPaymentResponse
+import net.taler.merchantlib.MerchantApi
+import net.taler.merchantlib.PostOrderResponse
+import net.taler.merchantpos.R
import net.taler.merchantpos.config.ConfigManager
-import net.taler.merchantpos.config.MerchantRequest
import net.taler.merchantpos.order.Order
-import org.json.JSONArray
-import org.json.JSONObject
-import java.net.URLEncoder
import java.util.concurrent.TimeUnit.MINUTES
import java.util.concurrent.TimeUnit.SECONDS
private val TIMEOUT = MINUTES.toMillis(2)
private val CHECK_INTERVAL = SECONDS.toMillis(1)
-private const val FULFILLMENT_PREFIX = "taler://fulfillment-success/"
class PaymentManager(
+ private val context: Context,
private val configManager: ConfigManager,
- private val queue: RequestQueue,
- private val mapper: ObjectMapper
+ private val scope: CoroutineScope,
+ private val api: MerchantApi
) {
- companion object {
- val TAG = PaymentManager::class.java.simpleName
- }
-
private val mPayment = MutableLiveData<Payment>()
val payment: LiveData<Payment> = mPayment
@@ -63,93 +54,51 @@ class PaymentManager(
}
override fun onFinish() {
- payment.value?.copy(error = true)?.let { mPayment.value = it }
+ val str = context.getString(R.string.error_timeout)
+ payment.value?.copy(error = str)?.let { mPayment.value = it }
}
}
@UiThread
fun createPayment(order: Order) {
val merchantConfig = configManager.merchantConfig!!
-
- val currency = merchantConfig.currency!!
- val summary = order.summary
- val summaryI18n = order.summaryI18n
- val now = now()
- val deadline = Timestamp(now + MINUTES.toMillis(120))
-
- mPayment.value = Payment(order, summary, currency)
-
- val fulfillmentId = "${now}-${order.hashCode()}"
- val fulfillmentUrl =
- "${FULFILLMENT_PREFIX}${URLEncoder.encode(summary, "UTF-8")}#$fulfillmentId"
- val body = JSONObject().apply {
- put("order", JSONObject().apply {
- put("amount", order.total.toJSONString())
- put("summary", summary)
- if (summaryI18n != null) put("summary_i18n", order.summaryI18n)
- // fulfillment_url needs to be unique per order
- put("fulfillment_url", fulfillmentUrl)
- put("instance", "default")
- put("wire_transfer_deadline", JSONObject(mapper.writeValueAsString(deadline)))
- put("refund_deadline", JSONObject(mapper.writeValueAsString(deadline)))
- put("products", order.getProductsJson())
- })
+ mPayment.value = Payment(order, order.summary, merchantConfig.currency!!)
+ scope.launch(Dispatchers.IO) {
+ val response = api.postOrder(merchantConfig.convert(), order.toContractTerms())
+ response.handle(::onNetworkError, ::onOrderCreated)
}
-
- Log.d(TAG, body.toString(4))
-
- val req = MerchantRequest(POST, merchantConfig, "order", null, body,
- Listener { onOrderCreated(it) },
- LogErrorListener { onNetworkError() }
- )
- queue.add(req)
- }
-
- private fun Order.getProductsJson(): JSONArray {
- val contractProducts = products.map { it.toContractProduct() }
- val productsStr = mapper.writeValueAsString(contractProducts)
- return JSONArray(productsStr)
}
- private fun onOrderCreated(orderResponse: JSONObject) {
- val orderId = orderResponse.getString("order_id")
- mPayment.value = mPayment.value!!.copy(orderId = orderId)
+ private fun onOrderCreated(orderResponse: PostOrderResponse) = scope.launch(Dispatchers.Main) {
+ mPayment.value = mPayment.value!!.copy(orderId = orderResponse.orderId)
checkTimer.start()
}
private fun checkPayment(orderId: String) {
val merchantConfig = configManager.merchantConfig!!
- val params = mapOf(
- "order_id" to orderId,
- "instance" to merchantConfig.instance
- )
-
- val req = MerchantRequest(GET, merchantConfig, "check-payment", params, null,
- Listener { onPaymentChecked(it) },
- LogErrorListener { onNetworkError() })
- queue.add(req)
+ scope.launch(Dispatchers.IO) {
+ val response = api.checkOrder(merchantConfig.convert(), orderId)
+ response.handle(::onNetworkError, ::onPaymentChecked)
+ }
}
- /**
- * Called when the /check-payment response gave a result.
- */
- private fun onPaymentChecked(checkPaymentResponse: JSONObject) {
+ private fun onPaymentChecked(response: CheckPaymentResponse) = scope.launch(Dispatchers.Main) {
val currentValue = requireNotNull(mPayment.value)
- if (checkPaymentResponse.getBoolean("paid")) {
+ if (response.paid) {
mPayment.value = currentValue.copy(paid = true)
checkTimer.cancel()
} else if (currentValue.talerPayUri == null) {
- val talerPayUri = checkPaymentResponse.getString("taler_pay_uri")
- mPayment.value = currentValue.copy(talerPayUri = talerPayUri)
+ response as CheckPaymentResponse.Unpaid
+ mPayment.value = currentValue.copy(talerPayUri = response.talerPayUri)
}
}
- private fun onNetworkError() {
- cancelPayment()
+ private fun onNetworkError(error: String) = scope.launch(Dispatchers.Main) {
+ cancelPayment(error)
}
- fun cancelPayment() {
- mPayment.value = mPayment.value!!.copy(error = true)
+ fun cancelPayment(error: String) {
+ mPayment.value = mPayment.value!!.copy(error = error)
checkTimer.cancel()
}
diff --git a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/ProcessPaymentFragment.kt b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/ProcessPaymentFragment.kt
index 9060fd3..5278a03 100644
--- a/merchant-terminal/src/main/java/net/taler/merchantpos/payment/ProcessPaymentFragment.kt
+++ b/merchant-terminal/src/main/java/net/taler/merchantpos/payment/ProcessPaymentFragment.kt
@@ -61,8 +61,8 @@ class ProcessPaymentFragment : Fragment() {
}
private fun onPaymentStateChanged(payment: Payment) {
- if (payment.error) {
- topSnackbar(requireView(), R.string.error_network, LENGTH_LONG)
+ if (payment.error != null) {
+ topSnackbar(requireView(), payment.error, LENGTH_LONG)
findNavController().navigateUp()
return
}
@@ -86,7 +86,7 @@ class ProcessPaymentFragment : Fragment() {
}
private fun onPaymentCancel() {
- paymentManager.cancelPayment()
+ paymentManager.cancelPayment(getString(R.string.error_cancelled))
findNavController().navigateUp()
topSnackbar(requireView(), R.string.payment_canceled, LENGTH_LONG)
}
diff --git a/merchant-terminal/src/main/res/values/strings.xml b/merchant-terminal/src/main/res/values/strings.xml
index b3dcd8d..4c0ba5a 100644
--- a/merchant-terminal/src/main/res/values/strings.xml
+++ b/merchant-terminal/src/main/res/values/strings.xml
@@ -64,6 +64,8 @@
<string name="refund_order_ref">Purchase reference: %1$s\n\n%2$s</string>
<string name="error_network">Network error</string>
+ <string name="error_timeout">No payment found, please try again!</string>
+ <string name="error_cancelled">Payment cancelled</string>
<string name="toast_back_to_exit">Click «back» again to exit</string>