PayRail
PayRail is a provider-neutral Rust payment library for accepting payments through Stripe, PayPal, crypto providers, and Mobile Money providers such as Lipila.
The public API exposes PayRail payment concepts instead of provider-specific SDK types. First-party providers are internal modules behind feature flags so applications only compile the payment rails they need while depending on one public crate.
Crate
payrail is the only public crate. It contains provider-neutral domain types, idempotency,
webhook abstractions, route configuration, and first-party providers behind Cargo features.
Planned first-party extension points include additional Mobile Money providers, Mobile Money aggregators, and crypto providers such as Circle, Coinbase, Bridge, and Binance.
Installation
[]
= { = "0.1", = ["stripe", "paypal", "lipila"] }
The default TLS backend is Rustls. Do not enable all providers unless the application uses them.
Common feature flags:
stripe: Stripe hosted and embedded Checkout, status, refunds, and webhooks.paypal: PayPal Orders, OAuth, capture, and webhooks.lipila: Lipila Zambia Mobile Money. This also enablesmobile-money.mobile-money: shared Mobile Money types and helpers.all-providers: all first-party providers.rustls: Rustls TLS backend.native-tls: native TLS backend.
Quickstart
use ;
use StripeConfig;
use SecretString;
async
Stripe Embedded Checkout
Hosted Checkout remains the default. For an on-site Stripe Payment Element flow, request
CheckoutUiMode::Elements and pass the returned client secret to Stripe.js.
use ;
let request = builder
.amount
.reference?
.payment_method
.checkout_ui_mode
.return_url?
.idempotency_key?
.build?;
let session = client.create_payment.await?;
if let Some = session.next_action
Routing Extensions
Routes use PayRail's built-in provider identifiers and dispatch through concrete connector fields. There is no trait-object connector registry in the library hot path.
Route configuration and connector availability are separate:
- Implemented connectors today: Stripe, PayPal, and Lipila.
- Reserved crypto route targets: Circle, Coinbase, Bridge, and Binance. These are modeled provider
IDs, but payments routed to them return
ConnectorNotConfigureduntil first-party connectors are implemented and configured. - Reserved Mobile Money and aggregator route targets: MTN MoMo, M-Pesa, Airtel Money, Orange Money,
Flutterwave, and Paystack. These are modeled provider IDs, but payments routed to them return
ConnectorNotConfigureduntil first-party connectors are implemented and configured. PaymentProvider::Other(...)is metadata for normalized provider references and events. It is not a runtime routing extension point.
Mobile Money Routing
Lipila is the default Zambia Mobile Money route. Applications can override or add country routes only to modeled built-in providers. Do not route a country to a provider unless that provider connector supports the country.
use ;
let client = builder
.mobile_money_route
.build?;
Crypto Routing
Stripe-hosted USDC Checkout remains the default stablecoin route for compatibility. Other stablecoins, including USDT, require explicit routing so unsupported assets or networks do not accidentally route to a provider that cannot process them.
use ;
let client = builder
.crypto_route
.crypto_asset_route
.crypto_asset_network_route
.build?;
let method = usdc_on;
let usdt = stablecoin_usdt;
Crypto route precedence is asset + network, then asset, then network, then default crypto route.
Future stablecoins can be supported without changing core by using StablecoinAsset::Other(symbol)
and CryptoAsset::Other(symbol) with an explicit asset route. Stablecoins that become broadly
supported can be promoted to first-class enum variants with matching routing and provider tests.
The example above configures route selection only. It is useful for validating routing behavior and for future connector work, but successful payment execution requires the selected provider connector to exist and be configured.
Contributing Providers
Provider extensions are implemented inside PayRail as feature-gated first-party modules so the
facade can keep static dispatch and avoid runtime trait-object routing. New providers must add a
BuiltinProvider route target when needed, keep secret configuration in secrecy::SecretString,
verify webhooks before parsing, and include mocked backend integration tests for provider
operations.
Use the provider contribution template:
Security Posture
- PayRail never handles raw card numbers; card payments use provider-hosted or provider-secure flows.
- API keys and webhook secrets use
secrecy::SecretString. - Webhook verification uses raw request bodies and constant-time comparison where applicable.
- Public response types do not expose raw provider response bodies or raw webhook payloads by default.
- Errors expose only normalized or redacted provider diagnostics.
- Sandbox/live tests are gated by explicit environment variables and never run by default.
Testing and Quality Gates
Required before release candidates:
The workspace release gate is 90% line coverage. Core and security-sensitive modules target 95%+ line coverage, with branch coverage tracked where tooling permits.
Provider Limitations
- Stripe stablecoin support is delegated to Stripe-supported Checkout flows.
- Stripe card payments support hosted Checkout by default and embedded Checkout Sessions with
CheckoutUiMode::Elements. - General crypto payments use provider-neutral
PaymentMethod::cryptoand explicit route registration for modeled providers such as Circle, Coinbase, Bridge, or Binance once their first-party connectors exist. - PayRail does not custody private keys, seed phrases, or raw wallet credentials.
- PayPal refunds are not implemented in v1.
- Lipila v1 exposes Zambia Mobile Money collections only.
- MTN MoMo, M-Pesa, Airtel Money, Orange Money, Flutterwave, and Paystack are modeled route targets, but their first-party connectors are not implemented yet.
License
Licensed under either of:
- Apache License, Version 2.0
- MIT license