Payments - Payment Processing & Refunds
Domain: Payments
Location: api/nextango/apps/payments/
Last Updated: 2026-07-08
Overview
The Payments app provides unified payment processing built on a gateway abstraction layer (BasePaymentGateway, GatewayRegistry). All processor communication, terminal tokens, payment sessions, webhooks, and refunds, routes through a common interface defined in gateways/base.py. Four gateways are registered: Stripe (live), Square, PayPal (Zettle), and Custom Bank, all four have complete implementations. A fifth processor_type value, 'elavon', maps to the Custom gateway. Views call get_gateway_for_processor(processor) and are never coupled to a specific processor. The processor-agnostic terminal endpoints (/payments/terminal/*) and the unified webhook receiver (/payments/webhook/<processor_type>/) replaced the old Stripe-specific POS endpoints, which were retired, not merely deprecated.
The app additionally provides payment method configuration, processing fee calculations, risk scoring, and full refund management.
Documentation Quick Links
Core Documentation
| File | Description |
|---|---|
| models.md | Payment, PaymentMethod, PaymentProcessor, Refund models |
| serializers.md | Payment API serializers and validation |
| views.md | Payment endpoints and processor webhooks |
| services.md | PaymentService, RefundService, processor integrations |
| signals.md | Payment lifecycle signals |
| webhooks.md | Payment processor webhook handling |
| examples.md | Usage examples and patterns |
Key Features
Multi-Processor Support
- Stripe integration - Card-present (Terminal SDK) and webhooks, live with
STRIPE_API_KEYandSTRIPE_WEBHOOK_SECRET - Square integration - Card and mobile payments, activate with
SQUARE_ACCESS_TOKENand related vars - PayPal/Zettle integration - Device-initiated POS payments, activate with
PAYPAL_ZETTLE_*vars - Custom processor - Card-present gateway via
BANK_GATEWAY_*vars, activate withBANK_GATEWAY_API_KEY,BANK_GATEWAY_BASE_URL,BANK_GATEWAY_WEBHOOK_SECRET,BANK_GATEWAY_MERCHANT_ID - Processor failover - Automatic fallback to backup processor
- Unified interface - Consistent API across all processors
Payment Processing
- Multiple payment types - Cash, card, gift card, store credit, mobile
- Split payments - Multiple payment methods per transaction
- Payment authorization - Auth-capture workflow support
- Payment capture - Capture authorized payments
- Payment void - Void payments before settlement
- Processing fees - Automatic fee calculation per processor
Payment Methods
- Store-specific methods - Configure payment methods per store
- Active/inactive status - Enable/disable payment methods
- Method configuration - Processor settings per method
- Default methods - Store default payment methods
- Validation rules - Payment method validation
Refund Management
- Full refunds - Complete payment refund
- Partial refunds - Refund portion of payment
- Refund reasons - Track refund justification
- Processor refunds - Automatic processor refund calls
- Refund status tracking - Pending, processing, completed, failed
- Refund audit trail - Complete refund history
Risk & Security
- Risk scoring - Fraud detection and risk assessment
- Payment validation - Amount, method, customer validation
- Processor security - Secure API communication
- PCI compliance - Payment card data handling
- Webhook verification - Secure processor webhook handling
Cash Drawer Integration
- Cash tracking - Cash payment recording
- Drawer reconciliation - Cash drawer integration
- Cash variance - Track cash discrepancies
- Cash reports - Cash flow reporting
API Endpoints
Payments is mounted twice, see Views, root mount for the full grounding. No endpoint carries an /api/ prefix.
Payments
| Endpoint | Method | Description |
|---|---|---|
/payments/payments/ | GET, POST | List, create payments |
/payments/payments/{id}/ | GET, PUT, PATCH, DELETE | Individual payment operations |
/payments/payments/{id}/process_refund/ | POST | Create and process a refund for this payment |
/payments/payments/by_transaction/ | GET | Payments for a transaction |
/payments/payments/summary/ | GET | Aggregate payment statistics |
Payment Methods
| Endpoint | Method | Description |
|---|---|---|
/payment-methods/, /payments/methods/ | GET, POST, PUT, PATCH, DELETE | Payment method CRUD |
/payment-methods/by_store/ | GET | Payment methods available at a store, POS startup endpoint |
/payment-methods/{id}/available_stores/ | GET | Stores where a method is available |
/payment-methods/{id}/payments_summary/ | GET | Aggregate stats for one method |
Payment Processors
| Endpoint | Method | Description |
|---|---|---|
/payment-processors/, /payments/processors/ | GET, POST, PUT, PATCH, DELETE | Processor configuration |
/payment-processors/{id}/test_connection/ | POST | Test the processor's live gateway credentials |
/payment-processors/{id}/payment_methods/ | GET | Active methods for this processor |
Refunds
| Endpoint | Method | Description |
|---|---|---|
/refunds/, /payments/refunds/ | GET, POST, PUT, PATCH, DELETE | Refund CRUD |
/payments/refunds/{id}/process/ | POST | Process a pending refund |
/payments/refunds/by_payment/ | GET | Refunds for a payment |
/payments/refunds/summary/ | GET | Aggregate refund statistics |
Terminal, confirmation, and webhooks
| Endpoint | Method | Description |
|---|---|---|
/payments/terminal/connection-token/ | POST | Processor-agnostic terminal SDK token |
/payments/terminal/create-payment/ | POST | Processor-agnostic payment session |
/payments/confirm/ | POST | Post-3DS challenge verification |
/payments/webhook/<processor_type>/ | POST | Unified webhook receiver, Square/PayPal/Custom Bank |
/payments/webhook/stripe/ | GET, POST | Stripe-specific webhook receiver |
The legacy direct-Stripe POS endpoints (stripe/connection-token/, stripe/create-payment-intent/) were retired in commit-tagged work W5-P5-A (2026-05-09) and no longer exist. The terminal endpoints above replace them.
Full endpoint documentation: views.md
Gateway Implementation Status
| Gateway | Status | Description |
|---|---|---|
| Stripe | Live | Stripe Terminal SDK (POS), webhook HMAC-SHA256, refund processing. Activate with STRIPE_API_KEY, STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET |
| Square | Complete | Square Connect v2 API, all gateway methods implemented. Activate with env vars (SQUARE_ACCESS_TOKEN, SQUARE_LOCATION_ID, SQUARE_APPLICATION_ID, SQUARE_ENVIRONMENT) |
| PayPal | Complete | Zettle OAuth, device-initiated, all gateway methods implemented. Activate with env vars (PAYPAL_ZETTLE_CLIENT_ID, PAYPAL_ZETTLE_CLIENT_SECRET, PAYPAL_WEBHOOK_ID) |
| Custom Bank | Complete | HTTP to BANK_GATEWAY_BASE_URL, all gateway methods implemented. Activate with env vars (BANK_GATEWAY_API_KEY, BANK_GATEWAY_BASE_URL, BANK_GATEWAY_WEBHOOK_SECRET, BANK_GATEWAY_MERCHANT_ID) |
Mock Payment Processors
The MOCK_PAYMENT_PROCESSORS setting controls whether the gateways contact external APIs. It applies to all four gateways, Stripe included.
# settings/test.py or per-test override
MOCK_PAYMENT_PROCESSORS = True
When True, gateway methods return deterministic mock responses instead of calling out. This is designed for:
- Automated test suites (CI/CD pipelines)
- Local development without live credentials
- Integration tests that must not make external API calls
When False (default), the gateways use the configured credentials and contact real external APIs. Stripe additionally has its own sandbox mode via a test-mode STRIPE_API_KEY when the mock flag is off.
Note: Stripe is live. Square, PayPal, and Custom gateway logic is complete, live credentials are needed to activate external API calls.
Architecture Highlights
Payment Gateway Layer
Abstract gateway pattern replacing direct processor calls:
# All views use this, never reference StripeGateway directly
from payments.gateways import get_gateway_for_processor
gateway = get_gateway_for_processor(processor) # processor.processor_type = "stripe"
token = gateway.get_connection_token()
session = gateway.create_payment_session(amount_cents=1999, currency="usd")
Read more: services.md, models.md
Payment status values
TransactionPayment.status is one of succeeded, pending, or failed. POS-originated payments (cash, and terminal payments already confirmed by the card reader) are created directly with status='succeeded'. Card-not-present payments requiring a 3DS challenge go through PAYMENT_REQUIRES_ACTION on the parent SaleTransaction while StripeConfirmPaymentView awaits the challenge outcome, see Views.
Read more: models.md
Service Layer Architecture
Payment logic is centralized in PaymentService (fee calculation, applying payments to transactions, POS payment-type resolution) and RefundService (refund creation, processor routing, cumulative-amount validation). Processor selection and instantiation runs through the gateway registry (get_gateway_for_processor()), not a separate factory service class.
Read more: services.md
Webhook Processing
Secure processor webhook handling:
- Signature verification
- Idempotent processing
- Event type routing
- Error handling and retry
Read more: webhooks.md
Getting Started
1. Understand the Models
Start with models.md to understand:
TransactionPaymentmodel (amount,payment_method,status,processing_fee,net_amount)PaymentMethodmodel (name,method_type,processor,is_active,configuration)PaymentProcessormodel (name,processor_type,configuration, fee fields)Refundmodel (payment,amount,reason,status)
2. Review Payment Service
Read services.md to understand:
- Payment processing workflow
- Processor selection logic
- Fee calculation
- Risk scoring
- Refund processing
3. Explore Payment Flows
Check views.md to learn:
- Payment creation and processing
- Authorization and capture flow
- Refund request handling
- Payment method management
4. Study Processor Integration
Review services.md for:
- Stripe integration details
- Square integration details
- PayPal integration details
- Custom processor implementation
Related Domains
- Transactions - Transaction payment integration
- Stores - Store payment configuration
- Users - Employee payment processing
- POS Gateway - POS payment processing
- Integrations - Payment synchronization
Key Architectural Decisions
- Unified processor interface - Consistent API across all payment processors
- Mock implementations - Development-ready processor mocks
- Multi-processor support - Support multiple processors simultaneously
- Store-specific methods - Configure payment methods per store
- Risk scoring - Built-in fraud detection and risk assessment
- Fee calculation - Automatic processing fee calculation
- Webhook security - Signature verification for processor webhooks
Common Use Cases
- Card payment - Process credit/debit card payment via Stripe/Square
- Cash payment - Record cash payment and update cash drawer
- Split payment - Process transaction with multiple payment methods
- Gift card - Validate and process gift card payment
- Store credit - Apply customer store credit to transaction
- Refund processing - Process full or partial refund
- Payment void - Void payment before settlement
- Method configuration - Set up payment methods for store
- Processor failover - Automatic fallback to backup processor
Service Methods
PaymentService
calculate_processing_fee(amount, payment_method)- Percentage plus fixed fee from the method's processorapply_payment_to_transaction(transaction_id, payment_method_id, tendered_amount, metadata=None)- The primary POS payment method, supports partial and split paymentsprocess_payment(transaction_id, payment_method_id, amount, metadata=None)- Legacy path, kept for backward compatibilityprocess_payment_with_pos_type(transaction_id, payment_type, amount, store_id=None, metadata=None)- Resolves legacy POS string types (cash,card,check) to aPaymentMethod
RefundService
process_refund(payment, amount, reason='', metadata=None, sales_return=None)- Returns a 3-tuple(success, refund, message), validates against cumulative refunded amount
PaymentMethodService
resolve_pos_payment_type(payment_type, store_id=None)- Legacy POS string resolutionget_available_methods_for_store(store_id)- Store-scoped or global-availability methodsvalidate_method_for_transaction(payment_method_id, amount, store_id=None)- Active status, min/max amount, store availability
Full documentation: services.md
Next Steps
- Start with models.md - Understand the data structure
- Then services.md - Learn payment processing logic
- Review views.md - Explore API endpoints
- Check webhooks.md - See webhook processing
- Study serializers.md - Understand validation
- Review signals.md - See payment automation