The Payment Limits feature provides configurable minimum and maximum thresholds for payment amounts as a security measure. This helps prevent:
- Accidental overpayments
- Fraudulent transactions
- System abuse
- Processing errors
Payment limits are configured via environment variables in the .env file:
# Minimum payment amount in XLM/USDC (default: 0.01)
MIN_PAYMENT_AMOUNT=0.01
# Maximum payment amount in XLM/USDC (default: 100000)
MAX_PAYMENT_AMOUNT=100000- Minimum: 0.01 XLM/USDC
- Maximum: 100,000 XLM/USDC
The system validates that:
MIN_PAYMENT_AMOUNTmust be a positive number (> 0)MAX_PAYMENT_AMOUNTmust be greater thanMIN_PAYMENT_AMOUNT- If validation fails, the application will not start and will throw a configuration error
When a payment transaction is verified via the /api/payments/verify endpoint:
- The transaction is fetched from the Stellar network
- The payment amount is extracted and normalized
- Payment limit validation is performed
- If the amount is outside the configured limits, the transaction is rejected with an appropriate error code
When creating a payment intent via the /api/payments/intent endpoint:
- The student's fee amount is retrieved
- The fee amount is validated against payment limits
- If the fee amount is outside limits, the intent creation is rejected
During automatic payment synchronization:
- Recent transactions are fetched from the Stellar network
- Each payment amount is validated against limits
- Payments outside limits are skipped and not recorded
Retrieve the current payment limit configuration.
Endpoint: GET /api/payments/limits
Response:
{
"min": 0.01,
"max": 100000,
"message": "Payment amounts must be between 0.01 and 100000"
}The payment instructions endpoint now includes payment limits information.
Endpoint: GET /api/payments/instructions/:studentId
Response:
{
"walletAddress": "GXXX...",
"memo": "STUDENT123",
"acceptedAssets": [...],
"paymentLimits": {
"min": 0.01,
"max": 100000
},
"note": "Include the payment intent memo exactly when sending payment to ensure your fees are credited."
}When a payment is rejected due to limit violations, the following error codes are returned:
| Code | Description | HTTP Status |
|---|---|---|
AMOUNT_TOO_LOW |
Payment amount is below the minimum allowed | 400 |
AMOUNT_TOO_HIGH |
Payment amount exceeds the maximum allowed | 400 |
INVALID_AMOUNT |
Payment amount is not a valid number or is zero/negative | 400 |
{
"error": "Payment amount 0.005 is below the minimum allowed amount of 0.01",
"code": "AMOUNT_TOO_LOW"
}The core validation logic is implemented in backend/src/utils/paymentLimits.js:
function validatePaymentAmount(amount) {
// Validates that amount is:
// 1. A valid number
// 2. Greater than zero
// 3. Within configured min/max limits
// Returns: { valid: boolean, error?: string, code?: string }
}Payment limit validation is integrated at three key points:
stellarService.verifyTransaction()- Validates amounts during transaction verificationpaymentController.createPaymentIntent()- Validates fee amounts during intent creationstellarService.syncPayments()- Validates amounts during automatic synchronization
- Fraud Prevention: Limits help detect and prevent fraudulent transactions that may attempt to exploit the system
- Error Detection: Catches accidental overpayments or data entry errors
- Resource Protection: Prevents system abuse through extremely large or small transactions
- Compliance: Helps meet regulatory requirements for transaction monitoring
- Set Realistic Limits: Configure limits based on your actual fee structure
- Monitor Rejections: Track rejected payments to identify potential issues
- Regular Review: Periodically review and adjust limits as needed
- Document Changes: Keep a record of limit changes for audit purposes
Comprehensive tests are available in tests/payment-limits.test.js.
Run tests with:
npm test tests/payment-limits.test.js- Valid amounts within limits
- Amounts below minimum
- Amounts above maximum
- Edge cases (zero, negative, NaN, non-numeric)
- Boundary values (exactly at min/max)
Payments rejected due to limit violations are recorded in the database with:
- Status:
failed - Student ID:
unknown(if not identifiable) - Amount:
0
This provides an audit trail for security analysis.
- Rejection Rate: Track the percentage of payments rejected due to limits
- Rejection Reasons: Monitor which limit (min/max) is triggered most often
- Temporal Patterns: Identify if rejections cluster at certain times
- Student Impact: Track if specific students are repeatedly affected
If you're adding payment limits to an existing deployment:
- Review Existing Data: Analyze current payment amounts to set appropriate limits
- Set Conservative Limits: Start with wider limits and tighten gradually
- Communicate Changes: Notify users about the new limits
- Monitor Impact: Watch for increased rejections after deployment
- Adjust as Needed: Fine-tune limits based on real-world usage
Issue: Application won't start after adding payment limits
- Cause: Invalid configuration (e.g., max < min)
- Solution: Check
.envfile and ensureMAX_PAYMENT_AMOUNT > MIN_PAYMENT_AMOUNT
Issue: Valid payments are being rejected
- Cause: Limits set too restrictively
- Solution: Review and adjust
MIN_PAYMENT_AMOUNTandMAX_PAYMENT_AMOUNT
Issue: Payment intent creation fails for existing students
- Cause: Student fee amounts exceed new limits
- Solution: Either adjust limits or update student fee amounts
Potential improvements to the payment limits feature:
- Per-Asset Limits: Different limits for XLM vs USDC
- Dynamic Limits: Adjust limits based on student grade level or program
- Rate Limiting: Limit number of payments per time period
- Admin Interface: UI for managing limits without redeployment
- Alerts: Notify admins when limits are frequently triggered