Using ZarinPal Gateway with Payman
This section guides you on how to integrate the ZarinPal payment gateway using the Payman Python package. You will find examples for both asynchronous and synchronous usage to fit different application needs.
Quick Start Guide for ZarinPal Integration
Follow these simple steps to integrate ZarinPal payment gateway with Payman:
1. Initialize the Gateway
Import Payman
and create an instance with your merchant ID:
Note: Sandbox Mode for Development
When developing or testing your integration with ZarinPal, you should use sandbox mode to avoid real transactions. To enable sandbox mode:
- Use a randomly generated UUID (version 4) as your
merchant_id
. - Set the
sandbox=True
flag when creating thePayman
instance:
2. Create a Payment Request
Prepare and send a payment request to ZarinPal with the desired amount and callback URL.
amount = 10000 # IRR
payment_response = pay.payment(
amount=amount,
callback_url="https://example.com/callback",
description="Test Payment"
)
authority = payment_response.authority
print(f"Payment Authority: {authority}")
3. Redirect User to Payment URL
Use the authority code returned by the payment request to generate a URL and redirect your user there to complete the payment.
payment_redirect_url = pay.get_payment_redirect_url(authority=authority)
print(payment_redirect_url)
4. Receive Callback
After payment, ZarinPal will redirect the user back to your callback_url
with payment result parameters via a GET
request.
The two key query parameters are:
Authority
: A unique identifier for the payment session.Status
: Indicates whether the user successfully completed the payment ("OK") or canceled/failed it ("NOK").
from payman.gateways.zarinpal.models import CallbackParams
# This is a simulated example. In real use, extract these from the HTTP request:
callback = CallbackParams(authority="...", status="OK") # CallbackParams uses alias for `Authority` and `Status`
GET
request.
For a better understanding, see the FastAPI example code
Example callback URL:
https://example.com/callback?Authority=A00000000000000000000000000123456789&Status=OK
5. Verify Payment
Once the user is redirected back to your app, use the received authority
code to verify the payment with ZarinPal.
verify_response = pay.verify(authority=authority, amount=amount)
ref_id = verify_response.ref_id
print(f"Ref ID: {ref_id}")
NOTE: Payman supports both sync and async code. All gateway methods like
payment()
andverify()
can be called with or withoutawait
, depending on your application's architecture.
Flexible Input Support
All Payman
methods such as payment(...)
and verify(...)
accept input in three flexible formats:
- ✅ Pydantic model
- ✅ Plain dictionary
- ✅ Keyword arguments (
kwargs
)
This allows you to choose the most convenient style for your use case.
Example: payment(...)
in all supported formats
from payman import Payman
from payman.gateways.zarinpal.models import PaymentRequest
pay = Payman("zarinpal", merchant_id="...")
# 1. Using a Pydantic model
resp1 = pay.payment(PaymentRequest(
amount=10_000,
callback_url="https://site.com/callback",
description="Test A"
))
# ✅ 2. Using a dictionary
resp2 = pay.payment({
"amount": 10_000,
"callback_url": "https://site.com/callback",
"description": "Test B"
})
# ✅ 3. Using keyword arguments
resp3 = pay.payment(
amount=10_000,
callback_url="https://site.com/callback",
description="Test C"
)
Input Validation with Pydantic
Regardless of how you provide input—whether as a Pydantic model, a plain dictionary, or keyword arguments (kwargs
)—all data is strictly validated using Pydantic.
This means:
-
Field types are enforced (e.g., amount must be an int)
-
Required fields are checked
-
Invalid or malformed values raise immediate validation errors
-
You get clear and informative pydantic.ValidationError exceptions when something is wrong
This design gives you full flexibility while ensuring that all inputs are consistently validated behind the scenes.