A modern Flutter clothing store application demonstrating the integration of the PayChangu payment gateway.
- Features
- Screenshots & Demo
- Tech Stack
- Getting Started
- Project Structure
- Backend Integration
- PayChangu Integration Details
- Dependencies
- Interactive Intro Screen: Custom animations using shimmers, text splitting, and masking effects.
- Home Page:
- Search functionality.
- "New Arrival" banner with promotional offers.
- Grid view of available products.
- Product Catalog: Diverse range of products including T-shirts, Hoodies, Suits, Dresses, and Accessories.
- Backend Integration: Uses Supabase for backend services.
- Payment Integration: Includes payment processing screens (PayChangu).
PayChangu Mobile payment options: 
- Framework: Flutter
- Language: Dart
- Backend: Supabase
- State Management:
setState/AnimationController(Custom animations) - Environment Management:
flutter_dotenv
- Flutter SDK installed.
- An IDE (Android Studio or VS Code) with Flutter plugins.
- A Supabase project set up.
-
Clone the repository
git clone https://github.com/SentinalX1/Outfit.git cd outfit -
Install Dependencies
flutter pub get
-
Environment Setup Create a
.envfile in the root directory and add your Supabase credentials:SUPABASE_URL=your_supabase_url SUPABASE_ANON_KEY=your_supabase_anon_key
Note: Make sure
.envis added to your assets inpubspec.yaml(already configured). -
Run the App
flutter run
lib/
βββ data/ # Data models and mock data (e.g., product.dart)
βββ screens/ # UI Screens
β βββ intro/ # Animated intro screen implementation
β βββ home.dart # Main home dashboard
β βββ product_detail.dart
β βββ ...
βββ services/ # Service classes
βββ widgets/ # Reusable widgets
βββ main.dart # Entry point and Supabase initialization
The backend logic, specifically for secure payment processing, is handled via Supabase Edge Functions (Deno). This ensures sensitive keys like the PAYCHANGU_SECRET are never exposed to the client application.
This function handles CORS, retrieves the secret key from environment variables, and proxies the request to the PayChangu API.
import { serve } from "https://deno.land/std@0.178.0/http/server.ts";
// Define the handler function for the Edge Function.
serve(async (req) => {
// --- CORS Handling (Important for browser/Flutter web compatibility) ---
if (req.method === 'OPTIONS') {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
}
});
}
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Content-Type': 'application/json'
};
try {
// 1. Retrieve the secret key securely from the environment variables.
const paychanguSecretKey = Deno.env.get('PAYCHANGU_SECRET');
if (!paychanguSecretKey) {
console.error("PAYCHANGU_SECRET environment variable is not set.");
return new Response(JSON.stringify({
error: "Server configuration error: Secret key missing."
}), {
status: 500,
headers
});
}
// Assume the client sends the necessary payload (e.g., amount, currency, reference)
const clientPayload = await req.json();
// 2. Prepare the request to the external Paychangu API
const paychanguApiUrl = "https://api.paychangu.com/payment"; // <-- Paychangu Initiate Transaction Endpoint
const apiResponse = await fetch(paychanguApiUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
// 3. Use the secret key for authentication on the server-side
"Authorization": `Bearer ${paychanguSecretKey}`
},
body: JSON.stringify(clientPayload)
});
// 4. Handle response from the Paychangu API
if (!apiResponse.ok) {
const errorText = await apiResponse.text();
console.error(`Paychangu API Error: ${apiResponse.status} - ${errorText}`);
return new Response(JSON.stringify({
error: "External API failure",
details: errorText,
status: apiResponse.status
}), {
status: 502,
headers
});
}
// 5. Forward the successful response back to the client
const data = await apiResponse.json();
return new Response(JSON.stringify(data), {
status: 200,
headers
});
} catch (error) {
console.error("Function execution error:", error.message);
return new Response(JSON.stringify({
error: "Internal server error."
}), {
status: 500,
headers
});
}
});This project specifically demonstrates the integration of the PayChangu payment gateway.
- SDK Usage: This project does not use the official PayChangu SDK. It integrates directly with the PayChangu API via the Supabase Edge Function shown above.
- Return & Callback URLs:
- There is currently no live server hosted to handle the
return_urlorcallback_urlredirects. - Behavior: Once a payment is completed successfully in the WebView, the browser may redirect to an unreachable website (since the domain is not live).
- Verification: Despite the "site unreachable" error, the payment transaction does succeed. The transaction reference (
tx-ref) is generated and passed correctly, and the payment is processed on the gateway side.
- There is currently no live server hosted to handle the
Key packages used in this project:
supabase_flutter: For backend database and auth.flutter_dotenv: To manage environment variables securely.shimmer: For loading effects.webview_flutter: For displaying web content (payments).




