diff --git a/app/src/main/java/com/test/cardreadtest/payment/PaymentActivity.java b/app/src/main/java/com/test/cardreadtest/payment/PaymentActivity.java index 08d1858..97940d2 100644 --- a/app/src/main/java/com/test/cardreadtest/payment/PaymentActivity.java +++ b/app/src/main/java/com/test/cardreadtest/payment/PaymentActivity.java @@ -2,20 +2,19 @@ package com.test.cardreadtest.payment; import static android.content.Intent.getIntent; -import android.app.Application; import android.content.Intent; import android.os.Bundle; import android.util.Log; +import android.view.View; -import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; -import androidx.databinding.DataBindingUtil; import androidx.lifecycle.ViewModelProvider; import com.test.cardreadtest.R; import com.test.cardreadtest.databinding.ActivityPaymentBinding; import com.test.cardreadtest.posAPI.ConnectionServiceCallback; import com.test.cardreadtest.posAPI.POSManager; +import com.test.cardreadtest.posAPI.PaymentResult; import com.test.cardreadtest.posAPI.PaymentServiceCallback; import com.test.cardreadtest.utils.TRACE; @@ -24,9 +23,6 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.List; - -//import me.goldze.mvvmhabit.utils.ToastUtils; - public class PaymentActivity extends AppCompatActivity { private static final String TAG = "PaymentActivity"; private String amount; @@ -39,81 +35,101 @@ public class PaymentActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Simple DataBinding inflation - NO third-party dependencies binding = ActivityPaymentBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - // Use standard ViewModelProvider viewModel = new ViewModelProvider(this).get(PaymentViewModel.class); binding.setViewModel(viewModel); + binding.setLifecycleOwner(this); initData(); + setupClickListeners(); + } + + private void setupClickListeners() { + binding.btnCancel.setOnClickListener(v -> { + Log.d(TAG, "Cancel button clicked"); + cancelTransactionAndFinish(); + }); + + binding.btnBack.setOnClickListener(v -> { + Log.d(TAG, "Back button clicked"); + cancelTransactionAndFinish(); + }); + } + + private void cancelTransactionAndFinish() { + POSManager.getInstance().cancelTransaction(); + finish(); } /** * Initialize payment activity data - * Sets up initial UI state and starts transaction */ public void initData() { paymentServiceCallback = new PaymentCallback(); - // Get intent data Intent intent = getIntent(); amount = intent.getStringExtra("amount"); + deviceAddress = intent.getStringExtra("deviceAddress"); - // For testing, use default values if not provided if (amount == null) amount = "1.00"; + if (deviceAddress == null) deviceAddress = "UART"; - viewModel.displayAmount(amount);//display to UI + viewModel.displayAmount(amount); + viewModel.setStatus("Initializing..."); startTransaction(); } /** * Start payment transaction in background thread - * Handles device connection and transaction initialization */ private void startTransaction() { new Thread(() -> { - // Initialize POSManager if not already done POSManager.init(getApplicationContext()); + viewModel.setWaitingStatus(true); + if(!POSManager.getInstance().isDeviceReady()){ POSManager.getInstance().connect(deviceAddress, new ConnectionServiceCallback() { @Override public void onRequestNoQposDetected() { - runOnUiThread(() -> Log.d(TAG, "No device detected")); + runOnUiThread(() -> { + viewModel.setStatus("No device detected"); + viewModel.setWaitingStatus(false); + }); } @Override public void onRequestQposConnected() { - runOnUiThread(() -> Log.d(TAG, "Device connected")); + runOnUiThread(() -> { + viewModel.setStatus("Device connected"); + }); } @Override public void onRequestQposDisconnected() { runOnUiThread(() -> { - Log.d(TAG, "Device disconnected"); - finish(); + viewModel.setStatus("Device disconnected"); + viewModel.setWaitingStatus(false); }); } }); } - // Start transaction with callback POSManager.getInstance().startTransaction(amount, paymentServiceCallback); }).start(); } /** * Inner class to handle payment callbacks - * Implements all payment related events and UI updates */ private class PaymentCallback implements PaymentServiceCallback { @Override public void onRequestWaitingUser() { runOnUiThread(() -> { viewModel.setWaitingStatus(true); - Log.d(TAG, "Please insert/swipe/tap card"); + viewModel.setStatus("Please insert/swipe/tap card"); }); } @@ -127,7 +143,6 @@ public class PaymentActivity extends AppCompatActivity { @Override public void onRequestSelectEmvApp(ArrayList appList) { TRACE.d("onRequestSelectEmvApp():" + appList.toString()); - // Auto-select first app for testing if (!appList.isEmpty()) { POSManager.getInstance().selectEmvApp(0); } @@ -154,29 +169,53 @@ public class PaymentActivity extends AppCompatActivity { } @Override - public void onTransactionCompleted(com.test.cardreadtest.posAPI.PaymentResult result) { + public void onTransactionCompleted(PaymentResult result) { runOnUiThread(() -> { - Log.d(TAG, "Transaction completed: " + result.getTransactionType()); - // Display basic card info for testing + viewModel.setWaitingStatus(false); + viewModel.showTransactionResults(true); + + String transactionType = result.getTransactionType() != null ? result.getTransactionType() : "Unknown"; + viewModel.setTransactionResult(transactionType); + viewModel.setStatus("Transaction Completed"); + + // Display card information if available + StringBuilder cardDetails = new StringBuilder(); if (result.getMaskedPAN() != null) { - Log.d(TAG, "Card: " + result.getMaskedPAN()); + cardDetails.append("PAN: ").append(result.getMaskedPAN()).append(" "); } -// finish(); + if (result.getCardHolderName() != null) { + cardDetails.append("Name: ").append(result.getCardHolderName()).append(" "); + } + if (result.getExpiryDate() != null) { + cardDetails.append("Exp: ").append(result.getExpiryDate()); + } + + if (cardDetails.length() > 0) { + viewModel.setCardInfo(cardDetails.toString()); + } else { + viewModel.setCardInfo("No card details available"); + } + + Log.d(TAG, "Transaction completed: " + transactionType); + Log.d(TAG, "Card info: " + cardDetails.toString()); }); } @Override public void onTransactionFailed(String errorMessage, String data) { runOnUiThread(() -> { - Log.d(TAG, "Transaction failed: " + errorMessage); - finish(); + viewModel.setWaitingStatus(false); + viewModel.setTransactionResult("Failed"); + viewModel.setStatus("Error: " + errorMessage); + viewModel.setCardInfo("Transaction failed"); + + Log.d(TAG, "Transaction failed: " + errorMessage); }); } @Override public void onRequestOnlineProcess(final String tlv) { TRACE.d("onRequestOnlineProcess" + tlv); - // For testing, just send success response POSManager.getInstance().sendOnlineProcessResult("8A023030"); } @@ -188,9 +227,7 @@ public class PaymentActivity extends AppCompatActivity { @Override public void onBackPressed() { - // Cancel transaction and go back - POSManager.getInstance().cancelTransaction(); - super.onBackPressed(); + cancelTransactionAndFinish(); } @Override diff --git a/app/src/main/java/com/test/cardreadtest/payment/PaymentViewModel.java b/app/src/main/java/com/test/cardreadtest/payment/PaymentViewModel.java index 0793973..b672cf8 100644 --- a/app/src/main/java/com/test/cardreadtest/payment/PaymentViewModel.java +++ b/app/src/main/java/com/test/cardreadtest/payment/PaymentViewModel.java @@ -1,19 +1,69 @@ package com.test.cardreadtest.payment; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; public class PaymentViewModel extends ViewModel { + private MutableLiveData amount = new MutableLiveData<>("Amount: --"); + private MutableLiveData status = new MutableLiveData<>("Status: Ready"); + private MutableLiveData transactionResult = new MutableLiveData<>("Transaction: Waiting..."); + private MutableLiveData cardInfo = new MutableLiveData<>("Card: --"); + private MutableLiveData showProgress = new MutableLiveData<>(false); + private MutableLiveData showResults = new MutableLiveData<>(false); + public PaymentViewModel() { super(); } - public void displayAmount(String amount) { - // For testing - System.out.println("Amount to display: " + amount); + public MutableLiveData getAmount() { + return amount; + } + + public MutableLiveData getStatus() { + return status; + } + + public MutableLiveData getTransactionResult() { + return transactionResult; + } + + public MutableLiveData getCardInfo() { + return cardInfo; + } + + public MutableLiveData getShowProgress() { + return showProgress; + } + + public MutableLiveData getShowResults() { + return showResults; + } + + public void displayAmount(String amountValue) { + amount.postValue("Amount: $" + amountValue); + } + + public void setStatus(String statusText) { + status.postValue("Status: " + statusText); + } + + public void setTransactionResult(String result) { + transactionResult.postValue("Transaction: " + result); + } + + public void setCardInfo(String cardDetails) { + cardInfo.postValue("Card: " + cardDetails); } public void setWaitingStatus(boolean waiting) { - System.out.println("Waiting status: " + waiting); + showProgress.postValue(waiting); + if (waiting) { + setStatus("Please insert/swipe/tap card"); // Already uses postValue internally + } } -} \ No newline at end of file + + public void showTransactionResults(boolean show) { + showResults.postValue(show); + } +} diff --git a/app/src/main/res/layout/activity_payment.xml b/app/src/main/res/layout/activity_payment.xml index 37caac9..a218d8d 100644 --- a/app/src/main/res/layout/activity_payment.xml +++ b/app/src/main/res/layout/activity_payment.xml @@ -1,49 +1,121 @@ + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:view="http://schemas.android.com/apk/res/android"> - + + - - + + + + + + + + android:layout_gravity="center" + android:layout_marginBottom="20dp" /> -