upi-rs: Type-Safe UPI Payment Integration
A production-ready, type-safe, asynchronous, and provider-agnostic Rust crate for integrating UPI (Unified Payments Interface) payment processing into your applications.
Philosophy
"Parse, don't validate." This crate enforces type safety at compile time, ensuring that illegal states (like negative amounts or invalid VPAs) are unrepresentable in the type system.
Features
β¨ Type-Safe Domain Models: Invalid payment data cannot be constructed
π Provider Agnostic: Swap payment providers without changing your code
β‘ Async-First: Built on tokio for modern async Rust
π Cryptographic Verification: Constant-time HMAC-SHA256 signature verification
π¦ Zero-Cost Abstractions: Efficient implementations with minimal overhead
π§ͺ Comprehensive Testing: Unit tests for all components
Installation
Add this to your Cargo.toml:
[]
= "0.1"
= { = "1.32", = ["full"] }
Quick Start
1. Create Domain Objects
use ;
// UPI address - validated at construction time
let vpa = new?;
// Monetary amount - stored in Paise (1 INR = 100 Paise)
let amount = from_inr?;
2. Initialize a Provider
use RazorpayProvider;
let provider = new;
3. Process Payments
use PaymentRequest;
let request = new;
match provider.create_payment.await
4. Verify Webhooks
if provider.verify_webhook
Type Safety Examples
VPA Validation
VPAs are validated using a regex pattern to ensure format correctness:
use Vpa;
// β
Valid VPAs
new?;
new?;
new?;
// β Invalid VPAs (compile-time rejection)
new?; // Missing @
new?; // Invalid character
new?; // Missing username
Amount Validation
Amounts are stored internally in Paise to avoid floating-point precision issues:
use Amount;
// β
Valid amounts
from_inr?;
from_inr?;
from_inr?;
// β Invalid amounts (type-level rejection)
from_inr?; // Zero amount
from_inr?; // Negative
from_inr?; // Too many decimals
Module Overview
| Module | Purpose |
|---|---|
types |
Domain types with strict validation (Vpa, Amount) |
error |
Unified error type for all operations |
security |
Cryptographic verification (HMAC-SHA256) |
traits |
Provider abstraction layer |
providers |
Concrete gateway implementations (Razorpay, etc.) |
Architecture
βββββββββββββββββββββββββββββββββββββββββββ
β Your Application β
ββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββ
β UpiProvider Trait (Abstraction) β
βββββββββββββββββββββββββββββββββββββββββββ€
β β’ create_payment() β
β β’ verify_webhook() β
ββββββββββββββ¬βββββββββββββββββββββββββββββ
β
ββββββββββΌβββββββββ
βΌ βΌ βΌ
ββββββββββ ββββββββββ ββββββββββ
βRazorpayβ βCashfreeβ βCustom β
βProviderβ βProviderβ βProviderβ
ββββββββββ ββββββββββ ββββββββββ
Error Handling
The crate provides a unified error type with descriptive messages:
use UpiError;
match create_payment.await
Testing
Run the comprehensive test suite:
# Unit tests
# Documentation tests
# Strict linting
# Code formatting
Example
See examples/simple_payment.rs for a complete working example:
Security Considerations
- API Keys: Never hardcode API keys. Use environment variables or secure vaults.
- HTTPS Only: All API communications use HTTPS/TLS.
- Constant-Time Comparison: Webhook signatures are verified using constant-time comparison to prevent timing attacks.
- Secret Management: API secrets are wrapped in
secrecy::Secretto prevent accidental leakage in debug output.
Roadmap
- Additional provider implementations (Cashfree, PhonePe, PayU)
- Request signing for enhanced security
- Webhook server utilities
- Retry policies and circuit breakers
- Rate limiting support
- Detailed audit logging
Contributing
Contributions are welcome! Please ensure:
- All tests pass:
cargo test - Code is formatted:
cargo fmt - No clippy warnings:
cargo clippy -- -D warnings - Documentation is complete for all public APIs
License
Licensed under the MIT License (LICENSE or http://opensource.org/licenses/MIT).
Disclaimer
This crate is provided as-is for integration purposes. Always test thoroughly with real payment credentials in a staging environment before deploying to production. Consult with your payment provider's documentation for specific integration details and compliance requirements.
Support
For issues, questions, or feature requests, please open an issue on GitHub.
Made with β€οΈ for the Rust payments ecosystem