showing results ok

This commit is contained in:
ahmeddatexpay 2025-09-24 19:06:41 +03:00
parent 7ad09b2b5f
commit 2f8234e241
3 changed files with 220 additions and 61 deletions

View File

@ -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<String> 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(() -> {
viewModel.setWaitingStatus(false);
viewModel.setTransactionResult("Failed");
viewModel.setStatus("Error: " + errorMessage);
viewModel.setCardInfo("Transaction failed");
Log.d(TAG, "Transaction failed: " + errorMessage);
finish();
});
}
@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

View File

@ -1,19 +1,69 @@
package com.test.cardreadtest.payment;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class PaymentViewModel extends ViewModel {
private MutableLiveData<String> amount = new MutableLiveData<>("Amount: --");
private MutableLiveData<String> status = new MutableLiveData<>("Status: Ready");
private MutableLiveData<String> transactionResult = new MutableLiveData<>("Transaction: Waiting...");
private MutableLiveData<String> cardInfo = new MutableLiveData<>("Card: --");
private MutableLiveData<Boolean> showProgress = new MutableLiveData<>(false);
private MutableLiveData<Boolean> showResults = new MutableLiveData<>(false);
public PaymentViewModel() {
super();
}
public void displayAmount(String amount) {
// For testing
System.out.println("Amount to display: " + amount);
public MutableLiveData<String> getAmount() {
return amount;
}
public MutableLiveData<String> getStatus() {
return status;
}
public MutableLiveData<String> getTransactionResult() {
return transactionResult;
}
public MutableLiveData<String> getCardInfo() {
return cardInfo;
}
public MutableLiveData<Boolean> getShowProgress() {
return showProgress;
}
public MutableLiveData<Boolean> 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
}
}
public void showTransactionResults(boolean show) {
showResults.postValue(show);
}
}

View File

@ -1,49 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
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">
<data>
<variable
name="viewModel"
type="com.test.cardreadtest.payment.PaymentViewModel" />
<variable name="viewModel" type="com.test.cardreadtest.payment.PaymentViewModel"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="20dp">
<!-- Header -->
<TextView
android:id="@+id/tvAmount"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Amount: Testing..."
android:text="Payment Transaction"
android:textSize="24sp"
android:layout_marginBottom="30dp"
tools:text="Amount: $1.00" />
<TextView
android:id="@+id/tvStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Status: Ready"
android:textSize="18sp"
android:textStyle="bold"
android:gravity="center"
android:layout_marginBottom="20dp" />
<!-- Amount Section -->
<TextView
android:id="@+id/tvAmount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.amount}"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginBottom="10dp"
tools:text="Amount: $5.00" />
<!-- Status Section -->
<TextView
android:id="@+id/tvStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.status}"
android:textSize="16sp"
android:layout_marginBottom="20dp"
tools:text="Status: Processing..." />
<!-- Progress Bar -->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
android:layout_gravity="center"
android:layout_marginBottom="20dp" />
<!-- Transaction Results Section (Visible when transaction completes) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/design_default_color_primary"
android:padding="16dp"
android:layout_marginBottom="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Transaction Results"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold"
android:layout_marginBottom="10dp" />
<TextView
android:id="@+id/tvTransactionResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.transactionResult}"
android:textColor="@android:color/white"
android:textSize="16sp"
android:layout_marginBottom="5dp"
tools:text="Transaction: Approved" />
<TextView
android:id="@+id/tvCardInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.cardInfo}"
android:textColor="@android:color/white"
android:textSize="14sp"
tools:text="Card: ****1234 Exp: 12/25" />
</LinearLayout>
<!-- Buttons Section -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/btnCancel"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Cancel Transaction"
android:layout_marginTop="30dp" />
android:layout_weight="1"
android:text="Cancel"
android:layout_marginEnd="10dp" />
<Button
android:id="@+id/btnBack"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Back to Main"
android:layout_marginStart="10dp" />
</LinearLayout>
</LinearLayout>
</layout>