From eb9594079589a0126c3fb5f9a2f6ecd56950eebc Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 20 Aug 2019 22:56:16 +0200 Subject: prototype of payment request flow --- .idea/dictionaries/dold.xml | 7 ++ app/build.gradle | 28 ++++++- app/src/main/AndroidManifest.xml | 6 +- app/src/main/ic_taler_logo-web.png | Bin 0 -> 25951 bytes .../java/net/taler/merchantpos/CreatePayment.kt | 81 +++++++++++++++++++-- .../java/net/taler/merchantpos/MainActivity.kt | 49 +++++++------ .../java/net/taler/merchantpos/MerchantConfig.kt | 16 ++++ .../java/net/taler/merchantpos/MerchantHistory.kt | 77 ++++++++++++++++++++ .../taler/merchantpos/MerchantInternalRequest.kt | 25 +++++++ .../java/net/taler/merchantpos/MerchantSettings.kt | 31 ++++++++ .../net/taler/merchantpos/PosTerminalViewModel.kt | 15 ++++ .../java/net/taler/merchantpos/ProcessPayment.kt | 60 ++++++++++++++- .../main/res/drawable/ic_history_black_24dp.xml | 9 +++ .../main/res/drawable/ic_launcher_background.xml | 10 +-- app/src/main/res/drawable/ic_move_money_24dp.xml | 9 +++ .../main/res/layout/fragment_merchant_history.xml | 32 ++++++++ .../main/res/layout/fragment_merchant_settings.xml | 15 ++++ .../main/res/layout/fragment_process_payment.xml | 60 +++++++++++++-- app/src/main/res/layout/history_row.xml | 7 ++ app/src/main/res/layout/nav_header_main.xml | 6 +- app/src/main/res/menu/activity_main_drawer.xml | 30 ++------ .../main/res/mipmap-anydpi-v26/ic_taler_logo.xml | 5 ++ .../res/mipmap-anydpi-v26/ic_taler_logo_round.xml | 5 ++ .../res/mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 4307 bytes app/src/main/res/mipmap-hdpi/ic_taler_logo.png | Bin 0 -> 2347 bytes .../main/res/mipmap-hdpi/ic_taler_logo_round.png | Bin 0 -> 3638 bytes .../res/mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 2625 bytes app/src/main/res/mipmap-mdpi/ic_taler_logo.png | Bin 0 -> 1532 bytes .../main/res/mipmap-mdpi/ic_taler_logo_round.png | Bin 0 -> 2240 bytes .../res/mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 6077 bytes app/src/main/res/mipmap-xhdpi/ic_taler_logo.png | Bin 0 -> 3336 bytes .../main/res/mipmap-xhdpi/ic_taler_logo_round.png | Bin 0 -> 5273 bytes .../res/mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 10228 bytes app/src/main/res/mipmap-xxhdpi/ic_taler_logo.png | Bin 0 -> 5422 bytes .../main/res/mipmap-xxhdpi/ic_taler_logo_round.png | Bin 0 -> 8454 bytes .../res/mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 14083 bytes app/src/main/res/mipmap-xxxhdpi/ic_taler_logo.png | Bin 0 -> 7786 bytes .../res/mipmap-xxxhdpi/ic_taler_logo_round.png | Bin 0 -> 12377 bytes app/src/main/res/navigation/nav_graph.xml | 14 +++- 39 files changed, 520 insertions(+), 77 deletions(-) create mode 100644 .idea/dictionaries/dold.xml create mode 100644 app/src/main/ic_taler_logo-web.png create mode 100644 app/src/main/java/net/taler/merchantpos/MerchantConfig.kt create mode 100644 app/src/main/java/net/taler/merchantpos/MerchantHistory.kt create mode 100644 app/src/main/java/net/taler/merchantpos/MerchantInternalRequest.kt create mode 100644 app/src/main/java/net/taler/merchantpos/MerchantSettings.kt create mode 100644 app/src/main/java/net/taler/merchantpos/PosTerminalViewModel.kt create mode 100644 app/src/main/res/drawable/ic_history_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_move_money_24dp.xml create mode 100644 app/src/main/res/layout/fragment_merchant_history.xml create mode 100644 app/src/main/res/layout/fragment_merchant_settings.xml create mode 100644 app/src/main/res/layout/history_row.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_taler_logo.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_taler_logo_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_taler_logo.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_taler_logo_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_taler_logo.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_taler_logo_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_taler_logo.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_taler_logo_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_taler_logo.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_taler_logo_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_taler_logo.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_taler_logo_round.png diff --git a/.idea/dictionaries/dold.xml b/.idea/dictionaries/dold.xml new file mode 100644 index 0000000..192913d --- /dev/null +++ b/.idea/dictionaries/dold.xml @@ -0,0 +1,7 @@ + + + + snackbar + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 0316543..22225ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' @@ -21,11 +22,18 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } + + kotlinOptions { + jvmTarget = "1.8" + } } dependencies { - def nav_version = "2.1.0-rc01" - implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.0.2' @@ -37,9 +45,25 @@ dependencies { androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation "androidx.recyclerview:recyclerview:1.1.0-beta02" + + + def nav_version = "2.1.0-rc01" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version" // HTTP Requests implementation 'com.android.volley:volley:1.1.1' + + // QR codes + implementation 'com.google.zxing:core:3.4.0' + + // ViewModel and LiveData + def lifecycle_version = "2.0.0" + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" + kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" + + // JSON literals and parsing + implementation 'com.beust:klaxon:5.0.11' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2a203e5..52f77ef 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools" package="net.taler.merchantpos"> + android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> + + \ No newline at end of file diff --git a/app/src/main/ic_taler_logo-web.png b/app/src/main/ic_taler_logo-web.png new file mode 100644 index 0000000..e3b8075 Binary files /dev/null and b/app/src/main/ic_taler_logo-web.png differ diff --git a/app/src/main/java/net/taler/merchantpos/CreatePayment.kt b/app/src/main/java/net/taler/merchantpos/CreatePayment.kt index aac8db3..330b9e8 100644 --- a/app/src/main/java/net/taler/merchantpos/CreatePayment.kt +++ b/app/src/main/java/net/taler/merchantpos/CreatePayment.kt @@ -7,6 +7,16 @@ import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Button +import androidx.lifecycle.ViewModelProviders +import androidx.navigation.fragment.findNavController +import com.android.volley.Request +import com.android.volley.RequestQueue +import com.android.volley.Response +import com.android.volley.VolleyError +import com.android.volley.toolbox.Volley +import org.json.JSONObject +import com.google.android.material.snackbar.Snackbar // TODO: Rename parameter arguments, choose names that match @@ -28,6 +38,8 @@ class CreatePayment : Fragment() { private var param1: String? = null private var param2: String? = null private var listener: OnFragmentInteractionListener? = null + private lateinit var queue: RequestQueue + private lateinit var model: PosTerminalViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -35,6 +47,63 @@ class CreatePayment : Fragment() { param1 = it.getString(ARG_PARAM1) param2 = it.getString(ARG_PARAM2) } + + model = activity?.run { + ViewModelProviders.of(this)[PosTerminalViewModel::class.java] + } ?: throw Exception("Invalid Activity") + + queue = Volley.newRequestQueue(context) + } + + private fun onRequestPayment() { + val amount = "TESTKUDOS:10.00" + model.activeAmount = amount + var order = JSONObject().also { + it.put("amount", amount) + it.put("summary", "hello world") + it.put("fulfillment_url", "https://example.com") + it.put("instance", "default") + } + + var reqBody = JSONObject().also { it.put("order", order) } + + var req = MerchantInternalRequest( + Request.Method.POST, + model.merchantConfig!!, + "order", + null, + reqBody, + Response.Listener { onOrderCreated(it) }, + Response.ErrorListener { onNetworkError(it) }) + + queue.add(req) + + } + + private fun onNetworkError(volleyError: VolleyError?) { + val mySnackbar = Snackbar.make(view!!, "Network Error", Snackbar.LENGTH_SHORT) + mySnackbar.show() + } + + private fun onOrderCreated(orderResponse: JSONObject) { + val merchantConfig = model.merchantConfig!! + val orderId = orderResponse.getString("order_id") + val params = mapOf("order_id" to orderId, "instance" to merchantConfig.instance) + model.activeOrderId = orderId + + var req = MerchantInternalRequest(Request.Method.GET, model.merchantConfig!!, "check-payment", params, null, + Response.Listener { onCheckPayment(it) }, Response.ErrorListener { onNetworkError(it) }) + queue.add(req) + } + + private fun onCheckPayment(checkPaymentResponse: JSONObject) { + if (checkPaymentResponse.getBoolean("paid")) { + val mySnackbar = Snackbar.make(view!!, "Already paid?!", Snackbar.LENGTH_SHORT) + mySnackbar.show() + return + } + model.activeContractUri = checkPaymentResponse.getString("contract_url") + findNavController().navigate(R.id.action_createPayment_to_processPayment) } override fun onCreateView( @@ -42,12 +111,12 @@ class CreatePayment : Fragment() { savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_create_payment, container, false) - } - - // TODO: Rename method, update argument and hook method into UI event - fun onButtonPressed(uri: Uri) { - listener?.onFragmentInteraction(uri) + val view = inflater.inflate(R.layout.fragment_create_payment, container, false) + val requestPaymentButton = view.findViewById