# Wallet Management API - Quick Reference ## Authentication All wallet endpoints require JWT authentication. Include the token in the Authorization header: ``` Authorization: Bearer ``` The `partner_id` is automatically extracted from the JWT token - you don't need to provide it in the request body. ## Base URL ``` http://localhost:8000/wallet ``` ## Endpoints ### 1. Create Wallet **POST** `/wallet/create` Create a new wallet for the authenticated service professional. **Headers:** ``` Authorization: Bearer Content-Type: application/json ``` **Request:** ```json { "initial_balance": 5000.00, "currency": "INR" } ``` **Response:** ```json { "success": true, "message": "Wallet created successfully", "data": { "wallet_id": "550e8400-e29b-41d4-a716-446655440000", "partner_id": "staff_123", "balance": 5000.00, "currency": "INR", "status": "active", "last_transaction_at": null, "created_at": "2024-01-20T10:00:00", "updated_at": "2024-01-20T10:00:00" } } ``` --- ### 2. Get My Wallet **GET** `/wallet/me` Retrieve complete wallet information for the authenticated user. **Headers:** ``` Authorization: Bearer ``` **Response:** ```json { "success": true, "message": "Wallet retrieved successfully", "data": { "wallet_id": "550e8400-e29b-41d4-a716-446655440000", "partner_id": "staff_123", "balance": 5000.00, "currency": "INR", "status": "active", "last_transaction_at": "2024-01-20T10:30:00", "created_at": "2024-01-20T10:00:00", "updated_at": "2024-01-20T10:30:00" } } ``` --- ### 3. Get My Balance **GET** `/wallet/balance` Quick endpoint to check current balance for the authenticated user. **Headers:** ``` Authorization: Bearer ``` **Response:** ```json { "success": true, "message": "Balance retrieved successfully", "data": { "partner_id": "staff_123", "balance": 5000.00, "currency": "INR", "status": "active" } } ``` --- ### 4. Create Transaction **POST** `/wallet/transaction` Add or deduct money from the authenticated user's wallet. **Headers:** ``` Authorization: Bearer Content-Type: application/json ``` **Credit Transaction (Add Money):** ```json { "transaction_type": "credit", "amount": 1000.00, "reference_type": "topup", "reference_id": "TOPUP-2024-001", "description": "Wallet recharge via UPI", "metadata": { "payment_method": "upi", "upi_id": "user@paytm", "transaction_ref": "UPI123456" } } ``` **Debit Transaction (Deduct Money):** ```json { "transaction_type": "debit", "amount": 500.00, "reference_type": "order", "reference_id": "ORDER-123", "description": "Payment for order ORDER-123" } ``` **Response:** ```json { "success": true, "message": "Transaction completed successfully", "data": { "transaction_id": "660e8400-e29b-41d4-a716-446655440000", "wallet_id": "550e8400-e29b-41d4-a716-446655440000", "partner_id": "staff_123", "transaction_type": "credit", "amount": 1000.00, "balance_after": 6000.00, "reference_type": "topup", "reference_id": "TOPUP-2024-001", "description": "Wallet recharge via UPI", "metadata": { "payment_method": "upi", "upi_id": "user@paytm" }, "created_at": "2024-01-20T10:30:00" } } ``` **Transaction Types:** - `credit` - Add money - `debit` - Deduct money **Reference Types:** - `order` - Payment for orders - `refund` - Refund from cancelled orders - `topup` - Manual wallet recharge - `commission` - Commission earnings - `withdrawal` - Money withdrawal --- ### 5. List My Transactions **POST** `/wallet/transactions/list` Get transaction history for the authenticated user with filters. **Headers:** ``` Authorization: Bearer Content-Type: application/json ``` **Request:** ```json { "transaction_type": "credit", "reference_type": "topup", "start_date": "2024-01-01T00:00:00", "end_date": "2024-12-31T23:59:59", "limit": 20, "offset": 0 } ``` **Response:** ```json { "success": true, "message": "Transactions retrieved successfully", "data": { "transactions": [ { "transaction_id": "660e8400-e29b-41d4-a716-446655440000", "wallet_id": "550e8400-e29b-41d4-a716-446655440000", "partner_id": "staff_123", "transaction_type": "credit", "amount": 1000.00, "balance_after": 6000.00, "reference_type": "topup", "reference_id": "TOPUP-2024-001", "description": "Wallet recharge", "metadata": {}, "created_at": "2024-01-20T10:30:00" } ], "pagination": { "limit": 20, "offset": 0, "total": 45 } } } ``` --- ## Admin Endpoints ### 6. [Admin] Get Wallet by Partner ID **GET** `/wallet/admin/{partner_id}` Admin endpoint to retrieve any wallet by partner ID. **Headers:** ``` Authorization: Bearer ``` **Response:** Same as "Get My Wallet" --- ### 7. [Admin] Update Wallet Status **PATCH** `/wallet/admin/{partner_id}/status?status={status}` Admin endpoint to change wallet status. **Headers:** ``` Authorization: Bearer ``` **Query Parameters:** - `status` - New status: `active` | `suspended` | `closed` **Example:** ``` PATCH /wallet/admin/staff_123/status?status=suspended ``` **Status Values:** - `active` - Normal operation (default) - `suspended` - Temporarily disabled, no transactions allowed - `closed` - Permanently disabled --- ## Error Responses ### Unauthorized (Missing/Invalid Token) ```json { "detail": "Authorization header missing" } ``` **Status Code:** 401 ### Wallet Not Found ```json { "detail": "Wallet not found. Please create a wallet first." } ``` **Status Code:** 404 ### Wallet Already Exists ```json { "detail": "Wallet already exists for partner_id: staff_123" } ``` **Status Code:** 400 ### Insufficient Balance ```json { "detail": "Insufficient balance. Current: 100.00, Required: 500.00" } ``` **Status Code:** 400 ### Wallet Not Active ```json { "detail": "Wallet is not active. Current status: suspended" } ``` **Status Code:** 400 --- ## cURL Examples ### Create Wallet ```bash curl -X POST "http://localhost:8000/wallet/create" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "initial_balance": 5000.00 }' ``` ### Get My Balance ```bash curl "http://localhost:8000/wallet/balance" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" ``` ### Add Money (Credit) ```bash curl -X POST "http://localhost:8000/wallet/transaction" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "transaction_type": "credit", "amount": 1000.00, "reference_type": "topup", "description": "Wallet top-up" }' ``` ### Deduct Money (Debit) ```bash curl -X POST "http://localhost:8000/wallet/transaction" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "transaction_type": "debit", "amount": 500.00, "reference_type": "order", "reference_id": "ORDER-123", "description": "Payment for order" }' ``` ### List My Transactions ```bash curl -X POST "http://localhost:8000/wallet/transactions/list" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "limit": 20, "offset": 0 }' ``` --- ## JWT Token Structure Your JWT token should contain the following claims: ```json { "partner_id": "staff_123", "user_id": "staff_123", "merchant_id": "merchant_456", "role": "service_professional", "email": "staff@example.com", "phone": "+919876543210", "exp": 1234567890 } ``` The API will extract `partner_id` from the token. If `partner_id` is not present, it will fall back to `user_id` or `staff_id`. --- ## Security Notes 1. **JWT Authentication**: All endpoints require valid JWT token 2. **Encrypted Balance**: Wallet balance is encrypted in the database using AES encryption 3. **Partner Isolation**: Users can only access their own wallet data 4. **Admin Endpoints**: Admin endpoints should verify admin role (TODO: implement role check) 5. **Rate Limiting**: Implement rate limiting in production to prevent abuse --- ## Integration Example ### Order Payment with Wallet ```python from app.wallet.services.service import WalletService from app.wallet.schemas.schema import WalletTransactionRequest from app.dependencies.auth import get_partner_id # In your order endpoint @router.post("/orders/create") async def create_order( order_data: OrderCreateRequest, db: AsyncSession = Depends(get_db), token_data: dict = Depends(verify_token) ): partner_id = get_partner_id(token_data) # Create order order = await create_order_logic(order_data, partner_id) # If payment mode is wallet, debit the wallet if order_data.payment_mode == "wallet": try: transaction = await WalletService.create_transaction( db, partner_id, WalletTransactionRequest( transaction_type="debit", amount=order.net_amount, reference_type="order", reference_id=str(order.order_id), description=f"Payment for order {order.order_number}", metadata={ "order_number": order.order_number, "items_count": len(order.items) } ) ) order.payment_status = "paid" await db.commit() except ValueError as e: # Handle insufficient balance raise HTTPException(status_code=400, detail=str(e)) return order ``` ### Refund to Wallet ```python # When cancelling an order @router.post("/orders/{order_id}/cancel") async def cancel_order( order_id: UUID, db: AsyncSession = Depends(get_db), token_data: dict = Depends(verify_token) ): partner_id = get_partner_id(token_data) # Get order order = await get_order_by_id(order_id, partner_id) # Refund to wallet if paid via wallet if order.payment_mode == "wallet" and order.payment_status == "paid": transaction = await WalletService.create_transaction( db, partner_id, WalletTransactionRequest( transaction_type="credit", amount=order.net_amount, reference_type="refund", reference_id=str(order.order_id), description=f"Refund for cancelled order {order.order_number}" ) ) # Cancel order order.order_status = "cancelled" order.payment_status = "refunded" await db.commit() return order ```