Skip to main content

Crate iran_pay

Crate iran_pay 

Source
Expand description

§iran-pay

Unified async SDK for Iranian payment gateways. One Gateway trait, six production drivers (ZarinPal, IDPay, NextPay, Pay.ir, Zibal, Vandar), shared strongly-typed request/response/error types, an in-memory mock gateway, security helpers (HMAC verification, constant-time compare, amount-mismatch guard), and per-provider API-version pinning. See VERSIONING.md for the upgrade policy.

§At a glance

use iran_pay::{Amount, Gateway, StartRequest, VerifyRequest};
use iran_pay::providers::ZarinPal;

let gateway = ZarinPal::new("YOUR-MERCHANT-UUID").sandbox();

// 1. Initiate the payment.
let start = gateway.start_payment(&StartRequest::builder()
    .amount(Amount::toman(50_000))
    .description("Pro subscription — May 2026")
    .callback_url("https://example.com/payment/callback")
    .order_id("ORD-12345")
    .build()).await?;

// 2. Redirect the user to `start.payment_url`.
println!("Send user to: {}", start.payment_url);

// 3. After they return, verify.  Pass the same amount back in to
//    catch tampering with the callback query string.
let verified = gateway.verify_payment(&VerifyRequest {
    authority: start.authority,
    amount: Amount::toman(50_000),
}).await?;

println!("Paid! Transaction ID = {}", verified.transaction_id);

§Why a trait?

Iranian e-commerce apps often switch gateways (or run several in parallel for redundancy / fee optimisation). Code your checkout against dyn Gateway or impl Gateway and you can swap providers with one line of configuration.

fn select_gateway(provider: &str) -> Box<dyn Gateway> {
    match provider {
        "zarinpal" => Box::new(ZarinPal::new(env::var("ZP_ID").unwrap())),
        "idpay"    => Box::new(IDPay::new(env::var("IDPAY_KEY").unwrap())),
        "nextpay"  => Box::new(NextPay::new(env::var("NEXTPAY_KEY").unwrap())),
        "payir"    => Box::new(PayIr::new(env::var("PAYIR_KEY").unwrap())),
        _ => unreachable!(),
    }
}

§Sandbox / test mode

Every provider exposes .sandbox() to flip to its test endpoint. No real money moves. Use this in CI and for local development.

§Mock gateway

For unit tests of your code, use mock::MockGateway — it implements Gateway without any network I/O, and lets you script success / failure responses programmatically.

§Cargo features

FeatureDefaultWhat it enables
zarinpalThe providers::ZarinPal driver
idpayThe providers::IDPay driver
nextpayThe providers::NextPay driver
payirThe providers::PayIr driver
zibalThe providers::Zibal driver
vandarThe providers::Vandar driver
validatorsRe-export parsitext’s Iranian validators
rustls-tlsUse rustls for HTTPS (no system OpenSSL)
native-tlsUse the platform TLS library

Disabling all provider features still gives you the trait, types, mock, and security helpers — useful if you build your own driver against this abstraction.

Modules§

mock
MockGateway — a no-network Gateway for unit-testing your own code.
prelude
Re-exports of the most commonly used types.
providers
Concrete Gateway drivers.
security
Security helpers for handling payment callbacks and webhooks.
validatorsvalidators
Re-exports of parsitext’s Iranian validators (gated by the validators Cargo feature, on by default).

Structs§

Amount
A monetary amount, stored internally in Rials.
RefundRequest
Inputs for Gateway::refund_payment.
RefundResponse
Output of Gateway::refund_payment.
StartRequest
Inputs for Gateway::start_payment.
StartRequestBuilder
Step-builder for StartRequest.
StartResponse
Output of Gateway::start_payment.
VerifyRequest
Inputs for Gateway::verify_payment.
VerifyResponse
Output of Gateway::verify_payment.

Enums§

Currency
The two Iranian currency units.
Error
Errors returned by gateway drivers.

Traits§

Gateway
Common interface for every Iranian payment gateway driver.

Type Aliases§

Result
Crate-wide Result alias.