---
title: "ZarinPal Payment"
description: "ZarinPal is Iran's most widely used online payment gateway, processing card payments for millions of Iranian shoppers."
url: "https://docs.j2commerce.com/v6/payment-methods/zarinpal"
markdown_url: "https://docs.j2commerce.com/v6/payment-methods/zarinpal.md"
last_updated: "2026-10-23T02:33:38+00:00"
version: "J2Commerce 6"
breadcrumbs:
  - title: "Home"
    url: "https://docs.j2commerce.com/"
  - title: "J2Commerce 6"
    url: "https://docs.j2commerce.com/v6"
  - title: "Payment Methods"
    url: "https://docs.j2commerce.com/v6/payment-methods"
  - title: "ZarinPal Payment"
    url: "https://docs.j2commerce.com/v6/payment-methods/zarinpal"
---

# ZarinPal Payment

ZarinPal is Iran's most widely used online payment gateway, processing card payments for millions of Iranian shoppers. When a customer chooses ZarinPal at checkout, they are redirected to the ZarinPal secure payment page, complete their transaction there, and are then returned to your store with a confirmed result.

This plugin is a separate add-on available from the [ZarinPal](https://www.j2commerce.com/extensions/payment-plugins/zarinpal). It is not included with the core J2Commerce 6 component.

## Prerequisites

Before configuring this plugin, make sure you have:

- A ZarinPal merchant account at [zarinpal.com](https://www.zarinpal.com)
- Your **Merchant ID** — a UUID (GUID) in the format `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`, found in your ZarinPal dashboard under the terminal/merchant settings
- Your store's currency set to either **IRR (Iranian Rial)** or **IRT (Iranian Toman)** — see the [Amount Currency section](https://docs.j2commerce.com/v6/payment-methods/zarinpal#amount-currency-rial-vs-toman) below for the critical difference between them

For testing, no live account is required. The ZarinPal sandbox (`sandbox.zarinpal.com`) works with any placeholder merchant ID.

## Purchase and download

This plugin is a separate add-on available from the [ZarinPal](https://www.j2commerce.com/extensions/payment-plugins/zarinpal). It is not included with the core J2Commerce 6 component.

1. Go to the [J2Commerce website](https://www.j2commerce.com/extensions) and locate **ZarinPal Payment** .
2. Add it to your cart and complete checkout.
3. Go to **My Downloads** under your account profile and find the plugin.
4. Click **Available Versions** -> **View Files** -> **Download Now** to download the ZIP file.

## Install the plugin

In the Joomla Administrator, go to **System** -> **Install** -> **Extensions**.

Upload the `plg_j2commerce_payment_zarinpal.zip` file.

![Joomla System Dashboard with System in the sidebar and the Install Extensions link highlighted to open the extension installer](https://docs.j2commerce.com/images/docs/shared/install.webp)

## Enable the Plugin

Once you have installed the App, you will need to enable it. There are **two** ways you can access the App.

**Option A:** Go to the **J2Commerce** icon at the top right corner **-> Setup -> Payment Methods**

**Option B:** Go to **Components** on the left sidebar **-> J2Commerce -> Dashboard** **-> Setup** **-> Payment Methods**

![J2Commerce Payment Methods list reached via Components > J2Commerce and the J2Commerce menu's Setup > Payment Methods, both highlighted, with 2Checkout listed](https://docs.j2commerce.com/images/docs/shared/culqi.webp)

To help you narrow down the list, you can do a search for **ZarinPal Payment** , click the **X,** and it will turn into a green checkmark. It is now enabled and ready for setup.

![Payment Methods list searched for ZarinPal, search box highlighted, with the ZarinPal Payment plugin's enabled status check mark highlighted](https://docs.j2commerce.com/images/docs/shared/zarinpal-enable.webp)

## Configure the Plugin

> **Tip:** Click the **Toggle Inline Help** button at the top of any plugin configuration page to show a short description beneath each field.

![Plugins: ZarinPal Payment toolbar with Toggle Inline Help highlighted and Display Name help text shown; Display Name ZarinPal, Status Enabled, Access Public](https://docs.j2commerce.com/images/docs/shared/zarinpal-toggle.webp)

### Display Settings

![Plugins: ZarinPal Payment, highlighted: Display Name ZarinPal, empty Display Image with a Select button, and the plugin description](https://docs.j2commerce.com/images/docs/shared/zarinpal-display.webp)

**Display Name:** Text shown to the customer at checkout (default: "ZarinPal")

**Display Image:** Logo or icon shown next to the payment option

### Credentials

![ZarinPal plugin credentials, highlighted: Sandbox Mode No, with empty Live Merchant ID, Access Token and Terminal ID fields](https://docs.j2commerce.com/images/docs/shared/zarinpal-api.webp)

Find the **Merchant ID** field and paste your UUID from the ZarinPal merchant dashboard.

The field only appears when **Sandbox Mode** is set to **No**. When Sandbox Mode is **Yes**, the **Sandbox Merchant ID** field appears in its place — you can leave that field empty or enter any placeholder value for testing.

**Merchant ID:** Your live ZarinPal UUID (shown when Sandbox = No)

**Sandbox Merchant ID:** Your test UUID (shown when Sandbox = Yes)

Set **Sandbox Mode** to **Yes** while testing, and to **No** for a live store.

When Sandbox Mode is on, the plugin points to `sandbox.zarinpal.com` instead of the live gateway. No real charges are made. The sandbox redirects to a test payment page where you can simulate a successful or failed transaction.

### Currency: Rial vs Toman

![ZarinPal plugin currency setting, highlighted: Amount Currency dropdown set to IRR - Iranian Rial](https://docs.j2commerce.com/images/docs/shared/zarinpal-currency.webp)

This is the most important setting to get right. ZarinPal's API accepts amounts in either **IRR** (Iranian Rial) or **IRT** (Iranian Toman), and your store currency must match this selection.

The key fact: **1 Toman = 10 Rials**. Iran informally uses Toman for most prices, but the Rial is the official currency. If you send 50,000 to ZarinPal but the shopper sees 5,000 on the payment page (or vice versa), this setting is the cause.

| Setting | Currency Unit | What happens to the amount |
| --- | --- | --- |
| **IRR — Iranian Rial** (default) | Rial | Sent as-is to ZarinPal |
| **IRT — Iranian Toman** | Toman | Divided by 10 before sending to ZarinPal |

Set this to match the unit your store uses for product prices. If your products are priced in Toman (e.g., a product costs 50,000 Toman), choose **IRT**. If prices are in Rial, choose **IRR**.

### Access Token (for Refunds)

![ZarinPal plugin Access Token field and Terminal ID field, highlighted, both empty](https://docs.j2commerce.com/images/docs/shared/zarinpal-token.webp)

The **Access Token** field is optional and only needed if you plan to process refunds through the ZarinPal GraphQL API. Leave it empty if you do not need refunds — they can always be issued manually through the ZarinPal merchant portal instead.

**Terminal ID:** Required for refunds. Your ZarinPal terminal identifier from the ZarinPal panel. Used with the Access Token to look up the payment session before a refund is issued. Leave empty if refunds are not needed.

### Template Style

![ZarinPal plugin Template Style dropdown, highlighted, set to Default](https://docs.j2commerce.com/images/docs/shared/zarinpal-style.webp)

**Template Style:** Choose the frontend template layout for checkout forms and saved card displays. Options depend on your site's template framework.

Available subtemplates: **Bootstrap 5** and **UIkit**. Leave blank to use the default layout. If your Joomla template is UIkit-based (e.g., YOOtheme Pro), select the UIkit subtemplate for consistent styling.

### Order Status

![ZarinPal plugin order status settings, highlighted: Order Status Confirmed and Failed Order Status Failed](https://docs.j2commerce.com/images/docs/shared/zarinpal-status.webp)

**Successful Payment Status:** Order status applied when payment verification returns code 100 or 101

**Failed Order Status:** Order status applied when the customer cancels or verification fails

You can change these to any status in your J2Commerce order status list.

> **Tip:** If the status you want is not listed in a dropdown, create a new one first by going to **J2Commerce** -> **Setup** -> **Order Statuses**.

![J2Commerce Order Statuses list with the J2Commerce menu open at the right, highlighting Setup and its Order Statuses item](https://docs.j2commerce.com/images/docs/shared/shipstation-order-status2-1.webp)

### Surcharge (Optional)

![ZarinPal plugin surcharge settings, highlighted: empty Surcharge Name, Percent and Fixed fields, Surcharge Tax Class Not Taxable](https://docs.j2commerce.com/images/docs/shared/zarinpal-surcharge.webp)

If ZarinPal processing costs need to be passed to the customer, fill in the surcharge fields:

**Surcharge Name:** Label shown in the cart, e.g. "Payment fee"

**Surcharge (%):** Percentage of the order total

**Surcharge (fixed):** Fixed amount added to the order

**Surcharge Tax Class:** Tax profile to apply to the surcharge (leave empty for no tax)

### Restrictions

![ZarinPal plugin restriction settings, highlighted: Geo Zone Restriction All, Minimum Subtotal 0 and Maximum Subtotal -1](https://docs.j2commerce.com/images/docs/shared/zarinpal-restrictions.webp)

**Geozone Restriction:** Limit this payment method to specific countries/regions

**Minimum Subtotal:** Hide this method if cart is below a minimum value

**Maximum Subtotal:** Hide this method if cart exceeds a maximum value

### Custom Checkout Messages

![ZarinPal plugin message settings, highlighted: Thank You Article selector and empty On Selection, After Payment, On Error and Order Cancelled text boxes](https://docs.j2commerce.com/images/docs/shared/zarinpal-messages.webp)

**Thank-You Article:** A Joomla article to display after successful payment

**On Selection:** Text shown when the customer selects this payment method

**On After Payment:** Text shown on the success screen after payment

**On Error Payment:** Text shown when a gateway error occurs

**On Cancel Payment:** Text shown when the customer cancels payment

### Other Settings

**Show Dashboard Icon:** When enabled, this plugin adds an icon tile to the J2Commerce dashboard and the J2Commerce quick icons module.

- **Icon Label:** Override the default label shown on the icon tile. Leave empty to use the plugin default.

**Debug Mode:** Log all API requests and responses — disable in production

Click **Save** when done.

## How the Checkout Flow Works

From a shopper's perspective, paying with ZarinPal looks like this:

1. The shopper reaches the **Order Confirmation** step and selects **ZarinPal** as their payment method.
2. They click the **Pay via ZarinPal** button.
3. The store sends a payment request to ZarinPal in the background. On success, the shopper is automatically redirected to `zarinpal.com/pg/StartPay/[authority]` — the ZarinPal secure payment page.
4. The shopper enters their Iranian bank card details and confirms the payment on the ZarinPal page.
5. ZarinPal redirects the shopper back to your store.
6. The plugin verifies the payment with ZarinPal. If the verification response code is `100` (verified) or `101` (already verified), the order is marked as confirmed.
7. The shopper sees the order success screen with their ZarinPal **Reference ID**.

If the shopper clicks **Cancel** on the ZarinPal page, or if verification fails, the order is marked with the failed status you configured and the shopper sees an error message.

## Testing with the Sandbox

ZarinPal provides a working sandbox environment at `sandbox.zarinpal.com`.

1. Set **Sandbox Mode** to **Yes** in the plugin settings.
2. Place a test order in your store and proceed to payment.
3. You will be redirected to the ZarinPal sandbox payment page.
4. Complete or cancel the test transaction.
5. Return to your store and verify the order status updated correctly.

No real money is processed during sandbox testing. Switch **Sandbox Mode** back to **No** when you go live.

## What's New vs the Old J2Store Plugin

If you previously used the ZarinPal plugin for J2Store, here is what changed in this J2Commerce 6 version:

| Area | Old J2Store Plugin | J2Commerce 6 Plugin |
| --- | --- | --- |
| Architecture | FOF 2 framework, non-namespaced | Native Joomla 6 MVC, fully namespaced |
| Gateway host | `api.zarinpal.com` (deprecated — dead) | `payment.zarinpal.com` (ZarinPal v4 live host) |
| Sandbox support | No sandbox toggle | Built-in Sandbox Mode toggle |
| Amount currency | Hard-coded divide-by-10 (assumed Toman) | Configurable: IRR Rial or IRT Toman |
| SDK | Raw cURL | Official ZarinPal SDK bundled in `lib/` |
| Refunds | Not supported | Refund/inquiry/reverse via GraphQL API (requires Access Token) |
| Language files | Persian hard-coded, no `.ini` files | Full English + Persian (`fa-IR`) language files |
| Error handling | Persian gate messages only | Localized error codes with English translations |

The most common breakage when migrating from the J2Store version is the gateway host. The old `api.zarinpal.com` endpoint no longer exists. The J2Commerce 6 plugin uses `payment.zarinpal.com`, which is the correct ZarinPal v4 address.

## Troubleshooting

### Shoppers are not redirected to ZarinPal: a gateway error appears immediately

**Cause:** The Merchant ID is incorrect, or the plugin cannot reach `payment.zarinpal.com`.

**Check these:**

1. Verify the **Merchant ID** is the correct UUID from your ZarinPal merchant dashboard. A Merchant ID with the wrong format returns error code `-2` ("The merchant ID or acceptance terminal is not correct").
2. If you just installed the plugin and are testing, make sure **Sandbox Mode** is set to **Yes** and try again — the sandbox uses a different hostname.
3. Enable **Debug Mode** temporarily to capture the gateway response in the Joomla error log, then check **System** -> **Logs**.

### The payment amount on ZarinPal's page is 10x too large or too small

**Cause:** The **Amount Currency** setting does not match the unit your store uses for prices.

**Solution:** If your products are priced in Toman, set Amount Currency to **IRT**. If priced in Rial, set it to **IRR**. This is the only calculation ZarinPal requires — the plugin handles the conversion automatically once the correct unit is selected.

### Error code -10: "Invalid merchant_id"

This error code means the Merchant ID UUID you entered is not recognized by ZarinPal. Double-check the value in your ZarinPal dashboard. Note that sandbox and live accounts have different Merchant IDs — use the **Sandbox Merchant ID** field for the sandbox account and the **Merchant ID** field for the live account.

### The order status does not update after the shopper returns

**Cause:** The callback URL was not reached, or session state was lost during redirect.

**Check these:**

1. Confirm your Joomla site is publicly accessible (not on a private IP or `localhost`) so ZarinPal can redirect back.
2. Check that no caching plugin is caching the checkout page — the callback URL must process dynamically.
3. Enable **Debug Mode** and re-test to see the full verification response in the Joomla log.

### Refunds are not available in the plugin admin

ZarinPal refunds require an **Access Token** (from your ZarinPal developer panel) and are processed via the GraphQL API. Enter your access token in the **Access Token** field to enable refund support. If you prefer, you can issue refunds manually through the ZarinPal merchant portal without configuring the access token.

### Payment completes but the order stays in Pending status

**Cause:** The Successful Payment Status may be set to the wrong order status, or the verification call did not complete.

**Solution:** Go to the plugin settings and confirm the **Successful Payment Status** is set to a confirmed/paid status (such as "Confirmed"). Then check the Joomla log for any verification errors.
