build.gradle

    // Add the Retrofit library
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")

// Add the Volley library
    implementation("com.android.volley:volley:1.2.0")

// Add the OkHttp library
    implementation("com.squareup.okhttp3:okhttp:4.9.1")
    implementation("com.github.bumptech.glide:glide:4.16.0")

AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET" /> <!-- Permissions for Android 12L (API level 32) or lower -->
  
    <application
       ...
       
        android:usesCleartextTraffic="true"
      ...
      >
        
    </application>

activity_product_details.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="<http://schemas.android.com/apk/res/android>"
    xmlns:app="<http://schemas.android.com/apk/res-auto>"
    xmlns:tools="<http://schemas.android.com/tools>"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.appbar.MaterialToolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:navigationIcon="@drawable/arrow_left"
            app:title="Product Details" />
    </com.google.android.material.appbar.AppBarLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <!-- Product Image -->
            <ImageView
                android:id="@+id/product_image"
                android:layout_width="match_parent"
                android:layout_height="250dp"
                android:scaleType="centerCrop" />

            <!-- Product Name -->
            <TextView
                android:id="@+id/product_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="18sp"
                android:textStyle="bold"
                android:paddingTop="8dp" />

            <!-- Product Description -->
            <TextView
                android:id="@+id/product_description"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:paddingTop="4dp" />

            <!-- Product Price -->
            <TextView
                android:id="@+id/product_price"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:textStyle="bold"
                android:textColor="@color/black"
                android:paddingTop="8dp" />

            <!-- Product Category -->
            <com.google.android.material.chip.Chip
                android:id="@+id/product_category"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAllCaps="true"
                android:paddingTop="4dp" />

            <!-- Date Added -->
            <TextView
                android:id="@+id/product_date"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:paddingTop="4dp"/>

            <!-- Make Order Button -->
            <com.google.android.material.button.MaterialButton
                android:id="@+id/make_order"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="12dp"
                android:text="Make Order"/>
        </LinearLayout>
    </ScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Order.java - Model

package com.example.gasswift.models;

public class Order {
    private String id;
    private String productId;
    private String type; // "product" or "refill"
    private String userId;
    private int amountPaid;
    private long timestamp;

    public Order() {
    }

    public Order(String id, String productId, String type, String userId, int amountPaid, long timestamp) {
        this.id = id;
        this.productId = productId;
        this.type = type;
        this.userId = userId;
        this.amountPaid = amountPaid;
        this.timestamp = timestamp;
    }

    public String getId() {
        return id;
    }

    public String getProductId() {
        return productId;
    }

    public String getType() {
        return type;
    }

    public String getUserId() {
        return userId;
    }

    public int getAmountPaid() {
        return amountPaid;
    }

    public long getTimestamp() {
        return timestamp;
    }
}

ProductDetailsActivity.java

package com.example.gasswift;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.bumptech.glide.Glide;
import com.example.gasswift.models.Order;
import com.example.gasswift.models.Product;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.chip.Chip;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import org.json.JSONObject;

import java.io.IOException;
import java.util.Objects;
import java.util.regex.Pattern;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class ProductDetailsActivity extends AppCompatActivity {

    private ImageView productImage;
    private TextView productName, productDescription, productPrice, productDate;
    private Chip productCategory;
    private MaterialButton makeOrderButton;

    private DatabaseReference databaseReference;
    private String productId;
    private int productAmount;
    private String appName="Gas Swift - by Linda";

    private static final String API_URL = "<https://api-mpesa.kuwesakenya.com/pay>";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_product_details);

        initializeUI();
        retrieveProductId();
        fetchProductDetails();

        makeOrderButton.setOnClickListener(v -> showPaymentDialog());
    }

    /**
     * Initializes UI components.
     */
    private void initializeUI() {
        productImage = findViewById(R.id.product_image);
        productName = findViewById(R.id.product_name);
        productDescription = findViewById(R.id.product_description);
        productPrice = findViewById(R.id.product_price);
        productCategory = findViewById(R.id.product_category);
        productDate = findViewById(R.id.product_date);
        makeOrderButton = findViewById(R.id.make_order);

        MaterialToolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setNavigationOnClickListener(v -> finish());

        databaseReference = FirebaseDatabase.getInstance().getReference("products");
    }

    /**
     * Retrieves the product ID from the intent.
     */
    private void retrieveProductId() {
        productId = getIntent().getStringExtra("productId");
        if (productId == null) {
            showToast("Error: Product not found");
            finish();
        }
    }

    /**
     * Fetches product details from Firebase.
     */
    private void fetchProductDetails() {
        databaseReference.child(productId).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.exists()) {
                    Product product = snapshot.getValue(Product.class);
                    if (product != null) {
                        updateUIWithProductDetails(product);
                    }
                } else {
                    showToast("Product not found");
                    finish();
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                showToast("Failed to load product");
            }
        });
    }

    /**
     * Updates UI with product details.
     */
    private void updateUIWithProductDetails(Product product) {
        productName.setText(product.getName());
        productDescription.setText(product.getDescription());
        productPrice.setText("Price: KSh. " + product.getPrice());
        productCategory.setText(product.getCategory());
        productDate.setText("Added on: " + product.getFormattedDate());

        try {
            productAmount = Integer.parseInt(product.getPrice());
        } catch (NumberFormatException e) {
            productAmount = 0;
        }

        Glide.with(this)
                .load(product.getImageUrl())
                .placeholder(R.drawable.placeholder)
                .into(productImage);
    }

    /**
     * Displays a dialog for the user to enter their phone number.
     */
    private void showPaymentDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Enter Phone Number");

        // Create EditText programmatically
        final EditText input = new EditText(this);
        input.setInputType(InputType.TYPE_CLASS_PHONE);
        input.setHint("07********");

        // Set padding for better UI
        int padding = (int) (16 * getResources().getDisplayMetrics().density);
        input.setPadding(padding, padding, padding, padding);
        input.setPadding(padding, padding, padding, padding);

        builder.setView(input);

        builder.setPositiveButton("Pay", (dialog, which) -> {
            String phoneNumber = input.getText().toString().trim();
            if (isValidPhoneNumber(phoneNumber)) {
                makePayment(formatPhoneNumber(phoneNumber));
            } else {
                showToast("Invalid phone number! Use format 07********");
            }
        });

        builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
        builder.show();
    }

    /**
     * Validates if the phone number is in the format 07********.
     */
    private boolean isValidPhoneNumber(String phoneNumber) {
        return Pattern.matches("^07\\\\d{8}$", phoneNumber);
    }

    /**
     * Converts phone number to international format (2547********).
     */
    private String formatPhoneNumber(String phoneNumber) {
        return "254" + phoneNumber.substring(1);
    }

    /**
     * Initiates the payment request.
     */
    private void makePayment(String phoneNumber) {
        ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Processing payment...");
        progressDialog.setCancelable(false);
        progressDialog.show();

        new Thread(() -> {
            try {
                OkHttpClient client = new OkHttpClient();

                // Create JSON request payload
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("phoneNumber", phoneNumber);
                jsonObject.put("amount", productAmount);
                jsonObject.put("accountReference", appName);
                jsonObject.put("transactionDesc", "Payment for " + productName.getText().toString());

                RequestBody body = RequestBody.create(jsonObject.toString(), MediaType.get("application/json"));

                Request request = new Request.Builder()
                        .url(API_URL)
                        .post(body)
                        .addHeader("Content-Type", "application/json")
                        .build();

                Response response = client.newCall(request).execute();

                if (response.isSuccessful()) {
                    String responseData = Objects.requireNonNull(response.body()).string();
                    Log.d("PaymentResponse", responseData);

                    // Generate a unique order ID
                    String orderId = FirebaseDatabase.getInstance().getReference("orders").push().getKey();

                    // Create and save order in Firebase
                    if (orderId != null) {
                        saveOrderToFirebase(orderId, phoneNumber);
                    }

                    runOnUiThread(() -> {
                        progressDialog.dismiss();
                        paymentComplete(responseData);
                    });
                } else {
                    runOnUiThread(() -> {
                        progressDialog.dismiss();
                        paymentFailed("Error: " + response.message());
                    });
                }

            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() -> {
                    progressDialog.dismiss();
                    paymentFailed("Payment failed: " + e.getMessage());
                });
            }
        }).start();
    }
    private void saveOrderToFirebase(String orderId, String phoneNumber) {
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        if (user == null) {
            showToast("User not logged in!");
            return;
        }

        String userId = user.getUid();
        DatabaseReference ordersRef = FirebaseDatabase.getInstance().getReference("orders");

        // Create an order object
        Order order = new Order(orderId, productId, "product", userId, productAmount, System.currentTimeMillis());

        // Save order to Firebase
        ordersRef.child(orderId).setValue(order)
                .addOnSuccessListener(aVoid -> showToast("Order saved successfully!"))
                .addOnFailureListener(e -> showToast("Failed to save order: " + e.getMessage()));
    }

    /**
     * Handles successful payment response.
     */
    private void paymentComplete(String responseData) {
        showToast("Payment Successful: " + responseData);
    }

    /**
     * Handles failed payment response.
     */
    private void paymentFailed(String errorMessage) {
        showToast(errorMessage);
    }

    /**
     * Displays a toast message.
     */
    private void showToast(String message) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}