Skip to content

Payment Gateways

The internet_payment_gateways adapter provides integration with Iranian Shaparak payment gateways. Supports both Parsian (SOAP/WSDL) and Saman (REST/JSON) protocols.

Parsian Shaparak

Parsian Shaparak adapter using the SOAP protocol with WSDL service definitions.

Ports

Abstract port interface defining the Parsian Shaparak adapter contract.

Classes:

Name Description
PaymentRequestDTO

DTO for initiating a payment request.

PaymentResponseDTO

DTO for payment response.

ConfirmRequestDTO

DTO for confirming a payment.

ConfirmResponseDTO

DTO for confirm payment response.

ConfirmWithAmountRequestDTO

DTO for confirming a payment with amount and order verification.

ConfirmWithAmountResponseDTO

DTO for confirm payment with amount response.

ReverseRequestDTO

DTO for reversing a payment.

ReverseResponseDTO

DTO for reverse payment response.

ParsianShaparakPaymentPort

Port interface for Parsian Shaparak payment gateway.

AsyncParsianShaparakPaymentPort

Async port interface for Parsian Shaparak payment gateway.

PaymentRequestDTO

DTO for initiating a payment request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class PaymentRequestDTO(BaseDTO):
    """DTO for initiating a payment request."""

    amount: int = Field(..., gt=0, description="Transaction amount in IRR")
    order_id: int = Field(..., gt=0, description="Unique order identifier")
    callback_url: HttpUrl = Field(..., description="URL to redirect after payment")
    additional_data: str | None = Field(None, description="Additional transaction data")
    originator: str | None = Field(None, description="Transaction originator")

PaymentResponseDTO

DTO for payment response.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class PaymentResponseDTO(BaseDTO):
    """DTO for payment response."""

    token: int | None = Field(None, description="Transaction token")
    status: int | None = Field(None, description="Transaction status code")
    message: str | None = Field(None, description="Status message or error description")

ConfirmRequestDTO

DTO for confirming a payment.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ConfirmRequestDTO(BaseDTO):
    """DTO for confirming a payment."""

    token: int = Field(..., gt=0, description="Transaction token")

ConfirmResponseDTO

DTO for confirm payment response.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ConfirmResponseDTO(BaseDTO):
    """DTO for confirm payment response."""

    status: int | None = Field(None, description="Transaction status code")
    rrn: int | None = Field(None, description="Retrieval Reference Number")
    card_number_masked: str | None = Field(None, description="Masked card number")
    token: int | None = Field(None, description="Transaction token")

ConfirmWithAmountRequestDTO

DTO for confirming a payment with amount and order verification.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ConfirmWithAmountRequestDTO(BaseDTO):
    """DTO for confirming a payment with amount and order verification."""

    token: int = Field(..., gt=0, description="Transaction token")
    order_id: int = Field(..., gt=0, description="Unique order identifier")
    amount: int = Field(..., gt=0, description="Transaction amount in IRR")

ConfirmWithAmountResponseDTO

DTO for confirm payment with amount response.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ConfirmWithAmountResponseDTO(BaseDTO):
    """DTO for confirm payment with amount response."""

    status: int | None = Field(None, description="Transaction status code")
    rrn: int | None = Field(None, description="Retrieval Reference Number")
    card_number_masked: str | None = Field(None, description="Masked card number")
    token: int | None = Field(None, description="Transaction token")

ReverseRequestDTO

DTO for reversing a payment.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ReverseRequestDTO(BaseDTO):
    """DTO for reversing a payment."""

    token: int = Field(..., gt=0, description="Transaction token")

ReverseResponseDTO

DTO for reverse payment response.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ReverseResponseDTO(BaseDTO):
    """DTO for reverse payment response."""

    status: int | None = Field(None, description="Transaction status code")
    message: str | None = Field(None, description="Status message or error description")
    token: int | None = Field(None, description="Transaction token")

ParsianShaparakPaymentPort

Port interface for Parsian Shaparak payment gateway.

Defines the contract for Parsian IPG adapters implementing payment operations (token request, confirmation, and reversal).

Methods:

Name Description
initiate_payment

Step 1: Request payment token.

confirm_payment

Step 3: Confirm transaction.

confirm_payment_with_amount

Confirm transaction with amount and order verification.

reverse_payment

Reverse a transaction.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class ParsianShaparakPaymentPort:
    """Port interface for Parsian Shaparak payment gateway.

    Defines the contract for Parsian IPG adapters implementing payment
    operations (token request, confirmation, and reversal).
    """

    @abstractmethod
    def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token.

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, and message.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

    @abstractmethod
    def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
        """Step 3: Confirm transaction.

        Args:
            request: Confirm request data.

        Returns:
            ConfirmResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

    @abstractmethod
    def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
        """Confirm transaction with amount and order verification.

        Args:
            request: Confirm with amount request data.

        Returns:
            ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

    @abstractmethod
    def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction.

        Args:
            request: Reverse request data.

        Returns:
            ReverseResponseDTO: Response containing status, message, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

initiate_payment abstractmethod

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token.

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, and message.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token.

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, and message.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

confirm_payment abstractmethod

confirm_payment(
    request: ConfirmRequestDTO,
) -> ConfirmResponseDTO

Step 3: Confirm transaction.

Parameters:

Name Type Description Default
request ConfirmRequestDTO

Confirm request data.

required

Returns:

Name Type Description
ConfirmResponseDTO ConfirmResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
    """Step 3: Confirm transaction.

    Args:
        request: Confirm request data.

    Returns:
        ConfirmResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

confirm_payment_with_amount abstractmethod

confirm_payment_with_amount(
    request: ConfirmWithAmountRequestDTO,
) -> ConfirmWithAmountResponseDTO

Confirm transaction with amount and order verification.

Parameters:

Name Type Description Default
request ConfirmWithAmountRequestDTO

Confirm with amount request data.

required

Returns:

Name Type Description
ConfirmWithAmountResponseDTO ConfirmWithAmountResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
    """Confirm transaction with amount and order verification.

    Args:
        request: Confirm with amount request data.

    Returns:
        ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

reverse_payment abstractmethod

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction.

Parameters:

Name Type Description Default
request ReverseRequestDTO

Reverse request data.

required

Returns:

Name Type Description
ReverseResponseDTO ReverseResponseDTO

Response containing status, message, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction.

    Args:
        request: Reverse request data.

    Returns:
        ReverseResponseDTO: Response containing status, message, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

AsyncParsianShaparakPaymentPort

Async port interface for Parsian Shaparak payment gateway.

Defines the contract for async Parsian IPG adapters implementing payment operations (token request, confirmation, and reversal).

Methods:

Name Description
initiate_payment

Step 1: Request payment token (async).

confirm_payment

Step 3: Confirm transaction (async).

confirm_payment_with_amount

Confirm transaction with amount and order verification (async).

reverse_payment

Reverse a transaction (async).

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
class AsyncParsianShaparakPaymentPort:
    """Async port interface for Parsian Shaparak payment gateway.

    Defines the contract for async Parsian IPG adapters implementing payment
    operations (token request, confirmation, and reversal).
    """

    @abstractmethod
    async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token (async).

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, and message.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

    @abstractmethod
    async def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
        """Step 3: Confirm transaction (async).

        Args:
            request: Confirm request data.

        Returns:
            ConfirmResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

    @abstractmethod
    async def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
        """Confirm transaction with amount and order verification (async).

        Args:
            request: Confirm with amount request data.

        Returns:
            ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

    @abstractmethod
    async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction (async).

        Args:
            request: Reverse request data.

        Returns:
            ReverseResponseDTO: Response containing status, message, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        raise NotImplementedError

initiate_payment abstractmethod async

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token (async).

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, and message.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token (async).

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, and message.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

confirm_payment abstractmethod async

confirm_payment(
    request: ConfirmRequestDTO,
) -> ConfirmResponseDTO

Step 3: Confirm transaction (async).

Parameters:

Name Type Description Default
request ConfirmRequestDTO

Confirm request data.

required

Returns:

Name Type Description
ConfirmResponseDTO ConfirmResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
async def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
    """Step 3: Confirm transaction (async).

    Args:
        request: Confirm request data.

    Returns:
        ConfirmResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

confirm_payment_with_amount abstractmethod async

confirm_payment_with_amount(
    request: ConfirmWithAmountRequestDTO,
) -> ConfirmWithAmountResponseDTO

Confirm transaction with amount and order verification (async).

Parameters:

Name Type Description Default
request ConfirmWithAmountRequestDTO

Confirm with amount request data.

required

Returns:

Name Type Description
ConfirmWithAmountResponseDTO ConfirmWithAmountResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
async def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
    """Confirm transaction with amount and order verification (async).

    Args:
        request: Confirm with amount request data.

    Returns:
        ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

reverse_payment abstractmethod async

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction (async).

Parameters:

Name Type Description Default
request ReverseRequestDTO

Reverse request data.

required

Returns:

Name Type Description
ReverseResponseDTO ReverseResponseDTO

Response containing status, message, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/ports.py
@abstractmethod
async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction (async).

    Args:
        request: Reverse request data.

    Returns:
        ReverseResponseDTO: Response containing status, message, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    raise NotImplementedError

options: show_root_toc_entry: false heading_level: 3

Adapters

Classes:

Name Description
ParsianShaparakPaymentAdapter

Adapter for interacting with Parsian Shaparak payment gateway services.

AsyncParsianShaparakPaymentAdapter

Async adapter for interacting with Parsian Shaparak payment gateway services.

ParsianShaparakPaymentAdapter

Adapter for interacting with Parsian Shaparak payment gateway services.

Provides methods for initiating payments, confirming transactions, and reversing payments through the Parsian Shaparak payment gateway SOAP services. Supports proxy configuration for environments where direct connections are not possible.

Methods:

Name Description
initiate_payment

Step 1: Request payment token.

confirm_payment

Step 3: Confirm transaction.

confirm_payment_with_amount

Confirm transaction with amount and order verification.

reverse_payment

Reverse a transaction.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
class ParsianShaparakPaymentAdapter(ParsianShaparakPaymentPort):
    """Adapter for interacting with Parsian Shaparak payment gateway services.

    Provides methods for initiating payments, confirming transactions, and reversing
    payments through the Parsian Shaparak payment gateway SOAP services. Supports
    proxy configuration for environments where direct connections are not possible.
    """

    def __init__(self, config: ParsianShaparakConfig | None = None) -> None:
        """Initialize the adapter with Parsian Shaparak configuration.

        Args:
            config (ParsianShaparakConfig | None): Configuration for Parsian Shaparak services.
                If None, uses global config. Includes optional proxy configuration via
                the PROXIES field.

        Raises:
            ValueError: If LOGIN_ACCOUNT is not a valid string.
        """
        configs = BaseConfig.global_config().PARSIAN_SHAPARAK if config is None else config
        if not configs.LOGIN_ACCOUNT or not isinstance(configs.LOGIN_ACCOUNT, str):
            raise ValueError("LOGIN_ACCOUNT must be a non-empty string")

        self.login_account = configs.LOGIN_ACCOUNT
        sync_transport = None
        if configs.PROXIES:
            session = requests.Session()
            session.proxies = configs.PROXIES
            sync_transport = Transport(session=session)

        self.sale_client = zeep.Client(wsdl=configs.PAYMENT_WSDL_URL, transport=sync_transport)
        self.confirm_client = zeep.Client(wsdl=configs.CONFIRM_WSDL_URL, transport=sync_transport)
        self.reversal_client = zeep.Client(wsdl=configs.REVERSAL_WSDL_URL, transport=sync_transport)

    def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token.

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, and message.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {
                "LoginAccount": self.login_account,
                "Amount": request.amount,
                "OrderId": request.order_id,
                "CallBackUrl": str(request.callback_url),
                "AdditionalData": request.additional_data,
                "Originator": request.originator,
            }

            logger.debug(f"Initiating payment: {request_data}")
            response = self.sale_client.service.SalePaymentRequest(requestData=request_data)
            result = PaymentResponseDTO(
                token=response.Token,
                status=response.Status,
                message=response.Message,
            )
            logger.debug(f"Payment response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Sale Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

    def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
        """Step 3: Confirm transaction.

        Args:
            request: Confirm request data.

        Returns:
            ConfirmResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {"LoginAccount": self.login_account, "Token": request.token}

            logger.debug(f"Confirming payment: {request_data}")
            response = self.confirm_client.service.ConfirmPayment(requestData=request_data)
            result = ConfirmResponseDTO(
                status=response.Status,
                rrn=response.RRN,
                card_number_masked=response.CardNumberMasked,
                token=response.Token,
            )
            logger.debug(f"Confirm response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

    def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
        """Confirm transaction with amount and order verification.

        Args:
            request: Confirm with amount request data.

        Returns:
            ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {
                "LoginAccount": self.login_account,
                "Token": request.token,
                "OrderId": request.order_id,
                "Amount": request.amount,
            }

            logger.debug(f"Confirming payment with amount: {request_data}")
            response = self.confirm_client.service.ConfirmPaymentWithAmount(requestData=request_data)
            result = ConfirmWithAmountResponseDTO(
                status=response.Status,
                rrn=response.RRN,
                card_number_masked=response.CardNumberMasked,
                token=response.Token,
            )
            logger.debug(f"Confirm with amount response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

    def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction.

        Args:
            request: Reverse request data.

        Returns:
            ReverseResponseDTO: Response containing status, message, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {"LoginAccount": self.login_account, "Token": request.token}

            logger.debug(f"Reversing payment: {request_data}")
            response = self.reversal_client.service.ReversalRequest(requestData=request_data)
            result = ReverseResponseDTO(
                status=response.Status,
                message=response.Message,
                token=response.Token,
            )
            logger.debug(f"Reversal response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Reversal Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

initiate_payment

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token.

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, and message.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token.

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, and message.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {
            "LoginAccount": self.login_account,
            "Amount": request.amount,
            "OrderId": request.order_id,
            "CallBackUrl": str(request.callback_url),
            "AdditionalData": request.additional_data,
            "Originator": request.originator,
        }

        logger.debug(f"Initiating payment: {request_data}")
        response = self.sale_client.service.SalePaymentRequest(requestData=request_data)
        result = PaymentResponseDTO(
            token=response.Token,
            status=response.Status,
            message=response.Message,
        )
        logger.debug(f"Payment response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Sale Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

confirm_payment

confirm_payment(
    request: ConfirmRequestDTO,
) -> ConfirmResponseDTO

Step 3: Confirm transaction.

Parameters:

Name Type Description Default
request ConfirmRequestDTO

Confirm request data.

required

Returns:

Name Type Description
ConfirmResponseDTO ConfirmResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
    """Step 3: Confirm transaction.

    Args:
        request: Confirm request data.

    Returns:
        ConfirmResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {"LoginAccount": self.login_account, "Token": request.token}

        logger.debug(f"Confirming payment: {request_data}")
        response = self.confirm_client.service.ConfirmPayment(requestData=request_data)
        result = ConfirmResponseDTO(
            status=response.Status,
            rrn=response.RRN,
            card_number_masked=response.CardNumberMasked,
            token=response.Token,
        )
        logger.debug(f"Confirm response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

confirm_payment_with_amount

confirm_payment_with_amount(
    request: ConfirmWithAmountRequestDTO,
) -> ConfirmWithAmountResponseDTO

Confirm transaction with amount and order verification.

Parameters:

Name Type Description Default
request ConfirmWithAmountRequestDTO

Confirm with amount request data.

required

Returns:

Name Type Description
ConfirmWithAmountResponseDTO ConfirmWithAmountResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
    """Confirm transaction with amount and order verification.

    Args:
        request: Confirm with amount request data.

    Returns:
        ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {
            "LoginAccount": self.login_account,
            "Token": request.token,
            "OrderId": request.order_id,
            "Amount": request.amount,
        }

        logger.debug(f"Confirming payment with amount: {request_data}")
        response = self.confirm_client.service.ConfirmPaymentWithAmount(requestData=request_data)
        result = ConfirmWithAmountResponseDTO(
            status=response.Status,
            rrn=response.RRN,
            card_number_masked=response.CardNumberMasked,
            token=response.Token,
        )
        logger.debug(f"Confirm with amount response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

reverse_payment

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction.

Parameters:

Name Type Description Default
request ReverseRequestDTO

Reverse request data.

required

Returns:

Name Type Description
ReverseResponseDTO ReverseResponseDTO

Response containing status, message, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction.

    Args:
        request: Reverse request data.

    Returns:
        ReverseResponseDTO: Response containing status, message, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {"LoginAccount": self.login_account, "Token": request.token}

        logger.debug(f"Reversing payment: {request_data}")
        response = self.reversal_client.service.ReversalRequest(requestData=request_data)
        result = ReverseResponseDTO(
            status=response.Status,
            message=response.Message,
            token=response.Token,
        )
        logger.debug(f"Reversal response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Reversal Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

AsyncParsianShaparakPaymentAdapter

Async adapter for interacting with Parsian Shaparak payment gateway services.

Provides async methods for initiating payments, confirming transactions, and reversing payments through the Parsian Shaparak payment gateway SOAP services. Supports proxy configuration for environments where direct connections are not possible.

Methods:

Name Description
initiate_payment

Step 1: Request payment token (async).

confirm_payment

Step 3: Confirm transaction (async).

confirm_payment_with_amount

Confirm transaction with amount and order verification (async).

reverse_payment

Reverse a transaction (async).

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
class AsyncParsianShaparakPaymentAdapter(AsyncParsianShaparakPaymentPort):
    """Async adapter for interacting with Parsian Shaparak payment gateway services.

    Provides async methods for initiating payments, confirming transactions, and
    reversing payments through the Parsian Shaparak payment gateway SOAP services.
    Supports proxy configuration for environments where direct connections are
    not possible.
    """

    def __init__(self, config: ParsianShaparakConfig | None = None) -> None:
        """Initialize the async adapter with Parsian Shaparak configuration.

        Args:
            config (ParsianShaparakConfig | None): Configuration for Parsian Shaparak services.
                If None, uses global config. Includes optional proxy configuration via
                the PROXIES field.

        Raises:
            ValueError: If LOGIN_ACCOUNT is not a valid string.
        """
        configs = BaseConfig.global_config().PARSIAN_SHAPARAK if config is None else config
        if not configs.LOGIN_ACCOUNT or not isinstance(configs.LOGIN_ACCOUNT, str):
            raise ValueError("LOGIN_ACCOUNT must be a non-empty string")

        self.login_account = configs.LOGIN_ACCOUNT
        proxy = self._get_proxy(configs.PROXIES)
        async_transport = None
        if proxy:
            httpx_client = httpx.AsyncClient(proxy=proxy)
            async_transport = AsyncTransport(client=httpx_client)

        self.sale_client = AsyncClient(wsdl=configs.PAYMENT_WSDL_URL, transport=async_transport)
        self.confirm_client = AsyncClient(wsdl=configs.CONFIRM_WSDL_URL, transport=async_transport)
        self.reversal_client = AsyncClient(wsdl=configs.REVERSAL_WSDL_URL, transport=async_transport)

    @staticmethod
    def _get_proxy(proxies: dict[str, str] | None) -> str | None:
        if proxies is None:
            return None
        return proxies.get("https") or proxies.get("http") or proxies.get("socks5") or proxies.get("socks5h")

    async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token (async).

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, and message.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {
                "LoginAccount": self.login_account,
                "Amount": request.amount,
                "OrderId": request.order_id,
                "CallBackUrl": str(request.callback_url),
                "AdditionalData": request.additional_data,
                "Originator": request.originator,
            }

            logger.debug(f"Initiating payment: {request_data}")
            response = await self.sale_client.service.SalePaymentRequest(requestData=request_data)
            result = PaymentResponseDTO(
                token=response.Token,
                status=response.Status,
                message=response.Message,
            )
            logger.debug(f"Payment response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Sale Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

    async def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
        """Step 3: Confirm transaction (async).

        Args:
            request: Confirm request data.

        Returns:
            ConfirmResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {"LoginAccount": self.login_account, "Token": request.token}

            logger.debug(f"Confirming payment: {request_data}")
            response = await self.confirm_client.service.ConfirmPayment(requestData=request_data)
            result = ConfirmResponseDTO(
                status=response.Status,
                rrn=response.RRN,
                card_number_masked=response.CardNumberMasked,
                token=response.Token,
            )
            logger.debug(f"Confirm response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

    async def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
        """Confirm transaction with amount and order verification (async).

        Args:
            request: Confirm with amount request data.

        Returns:
            ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {
                "LoginAccount": self.login_account,
                "Token": request.token,
                "OrderId": request.order_id,
                "Amount": request.amount,
            }

            logger.debug(f"Confirming payment with amount: {request_data}")
            response = await self.confirm_client.service.ConfirmPaymentWithAmount(requestData=request_data)
            result = ConfirmWithAmountResponseDTO(
                status=response.Status,
                rrn=response.RRN,
                card_number_masked=response.CardNumberMasked,
                token=response.Token,
            )
            logger.debug(f"Confirm with amount response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

    async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction (async).

        Args:
            request: Reverse request data.

        Returns:
            ReverseResponseDTO: Response containing status, message, and token.

        Raises:
            UnavailableError: If a SOAP fault occurs during the request.
            InternalError: If an unexpected error occurs during the request.
        """
        try:
            request_data = {"LoginAccount": self.login_account, "Token": request.token}

            logger.debug(f"Reversing payment: {request_data}")
            response = await self.reversal_client.service.ReversalRequest(requestData=request_data)
            result = ReverseResponseDTO(
                status=response.Status,
                message=response.Message,
                token=response.Token,
            )
            logger.debug(f"Reversal response: {result}")
        except Fault as exception:
            raise UnavailableError(resource_type="Parsian Shaparak Reversal Service") from exception
        except Exception as exception:
            raise InternalError() from exception
        else:
            return result

initiate_payment async

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token (async).

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, and message.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token (async).

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, and message.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {
            "LoginAccount": self.login_account,
            "Amount": request.amount,
            "OrderId": request.order_id,
            "CallBackUrl": str(request.callback_url),
            "AdditionalData": request.additional_data,
            "Originator": request.originator,
        }

        logger.debug(f"Initiating payment: {request_data}")
        response = await self.sale_client.service.SalePaymentRequest(requestData=request_data)
        result = PaymentResponseDTO(
            token=response.Token,
            status=response.Status,
            message=response.Message,
        )
        logger.debug(f"Payment response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Sale Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

confirm_payment async

confirm_payment(
    request: ConfirmRequestDTO,
) -> ConfirmResponseDTO

Step 3: Confirm transaction (async).

Parameters:

Name Type Description Default
request ConfirmRequestDTO

Confirm request data.

required

Returns:

Name Type Description
ConfirmResponseDTO ConfirmResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
async def confirm_payment(self, request: ConfirmRequestDTO) -> ConfirmResponseDTO:
    """Step 3: Confirm transaction (async).

    Args:
        request: Confirm request data.

    Returns:
        ConfirmResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {"LoginAccount": self.login_account, "Token": request.token}

        logger.debug(f"Confirming payment: {request_data}")
        response = await self.confirm_client.service.ConfirmPayment(requestData=request_data)
        result = ConfirmResponseDTO(
            status=response.Status,
            rrn=response.RRN,
            card_number_masked=response.CardNumberMasked,
            token=response.Token,
        )
        logger.debug(f"Confirm response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

confirm_payment_with_amount async

confirm_payment_with_amount(
    request: ConfirmWithAmountRequestDTO,
) -> ConfirmWithAmountResponseDTO

Confirm transaction with amount and order verification (async).

Parameters:

Name Type Description Default
request ConfirmWithAmountRequestDTO

Confirm with amount request data.

required

Returns:

Name Type Description
ConfirmWithAmountResponseDTO ConfirmWithAmountResponseDTO

Response containing status, RRN, card number, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
async def confirm_payment_with_amount(self, request: ConfirmWithAmountRequestDTO) -> ConfirmWithAmountResponseDTO:
    """Confirm transaction with amount and order verification (async).

    Args:
        request: Confirm with amount request data.

    Returns:
        ConfirmWithAmountResponseDTO: Response containing status, RRN, card number, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {
            "LoginAccount": self.login_account,
            "Token": request.token,
            "OrderId": request.order_id,
            "Amount": request.amount,
        }

        logger.debug(f"Confirming payment with amount: {request_data}")
        response = await self.confirm_client.service.ConfirmPaymentWithAmount(requestData=request_data)
        result = ConfirmWithAmountResponseDTO(
            status=response.Status,
            rrn=response.RRN,
            card_number_masked=response.CardNumberMasked,
            token=response.Token,
        )
        logger.debug(f"Confirm with amount response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Confirm Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

reverse_payment async

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction (async).

Parameters:

Name Type Description Default
request ReverseRequestDTO

Reverse request data.

required

Returns:

Name Type Description
ReverseResponseDTO ReverseResponseDTO

Response containing status, message, and token.

Raises:

Type Description
UnavailableError

If a SOAP fault occurs during the request.

InternalError

If an unexpected error occurs during the request.

Source code in archipy/adapters/internet_payment_gateways/ir/parsian/adapters.py
async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction (async).

    Args:
        request: Reverse request data.

    Returns:
        ReverseResponseDTO: Response containing status, message, and token.

    Raises:
        UnavailableError: If a SOAP fault occurs during the request.
        InternalError: If an unexpected error occurs during the request.
    """
    try:
        request_data = {"LoginAccount": self.login_account, "Token": request.token}

        logger.debug(f"Reversing payment: {request_data}")
        response = await self.reversal_client.service.ReversalRequest(requestData=request_data)
        result = ReverseResponseDTO(
            status=response.Status,
            message=response.Message,
            token=response.Token,
        )
        logger.debug(f"Reversal response: {result}")
    except Fault as exception:
        raise UnavailableError(resource_type="Parsian Shaparak Reversal Service") from exception
    except Exception as exception:
        raise InternalError() from exception
    else:
        return result

options: show_root_toc_entry: false heading_level: 3

Saman Shaparak

Saman Shaparak adapters using the REST/JSON protocol. Includes four variants:

  • SamanShaparakPaymentAdapter — Classic SEP adapter, redirects to fixed payment URL
  • SamanNeoPgShaparakPaymentAdapter — Neo-PG adapter, receives dynamic payment URL from X-IPG-Url response header
  • AsyncSamanShaparakPaymentAdapter — Async version of classic SEP adapter
  • AsyncSamanNeoPgShaparakPaymentAdapter — Async version of Neo-PG adapter

Ports

Abstract port interfaces defining the Saman Shaparak adapter contract.

Classes:

Name Description
PaymentRequestDTO

Request for getting payment token.

PaymentResponseDTO

Response from token request.

VerifyRequestDTO

Request for verifying a payment.

VerifyResponseDTO

Response from payment verification.

ReverseRequestDTO

Request for reversing a payment.

ReverseResponseDTO

Response from payment reversal.

SamanShaparakPaymentPort

Port interface for Saman Shaparak payment gateway.

AsyncSamanShaparakPaymentPort

Async port interface for Saman Shaparak payment gateway.

PaymentRequestDTO

Request for getting payment token.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class PaymentRequestDTO(BaseDTO):
    """Request for getting payment token."""

    amount: int = Field(..., gt=0, description="مبلغ به ریال")
    res_num: str = Field(..., description="شماره سفارش یکتا (ResNum)")
    redirect_url: HttpUrl = Field(..., description="آدرس صفحه بازگشت")
    cell_number: str | None = Field(None, description="شماره موبایل خریدار")
    wage: int | None = Field(None, description="مبلغ کارمزد")
    token_expiry_in_min: int = Field(20, ge=20, le=3600, description="مدت اعتبار توکن به دقیقه")
    hashed_card_number: str | None = Field(None, description="شماره کارت هش شده")

PaymentResponseDTO

Response from token request.

Methods:

Name Description
validate_status

Validate TLS-related settings to ensure compatibility.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class PaymentResponseDTO(BaseDTO):
    """Response from token request."""

    status: int
    token: str | None = None
    error_code: str | None = None
    error_desc: str | None = None
    ipg_url: str | None = Field(None, description="Dynamic payment page URL from X-IPG-Url header (Neo-PG only)")

    @model_validator(mode="after")
    def validate_status(self) -> Self:
        """Validate TLS-related settings to ensure compatibility."""
        if (self.status == 1 and self.token is None) or (self.status == -1 and self.error_code is None):
            raise FailedPreconditionError()
        return self

validate_status

validate_status() -> Self

Validate TLS-related settings to ensure compatibility.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@model_validator(mode="after")
def validate_status(self) -> Self:
    """Validate TLS-related settings to ensure compatibility."""
    if (self.status == 1 and self.token is None) or (self.status == -1 and self.error_code is None):
        raise FailedPreconditionError()
    return self

VerifyRequestDTO

Request for verifying a payment.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class VerifyRequestDTO(BaseDTO):
    """Request for verifying a payment."""

    reference_number: str = Field(..., description="رسید دیجیتالی (RefNum)")

VerifyResponseDTO

Response from payment verification.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class VerifyResponseDTO(BaseDTO):
    """Response from payment verification."""

    success: bool
    result_code: int
    result_description: str
    rrn: str | None = None
    reference_number: str | None = None
    masked_pan: str | None = None
    hashed_pan: str | None = None
    original_amount: int | None = None
    affective_amount: int | None = None
    trace_no: str | None = None

ReverseRequestDTO

Request for reversing a payment.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class ReverseRequestDTO(BaseDTO):
    """Request for reversing a payment."""

    reference_number: str = Field(...)

ReverseResponseDTO

Response from payment reversal.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class ReverseResponseDTO(BaseDTO):
    """Response from payment reversal."""

    success: bool
    result_code: int
    result_description: str

SamanShaparakPaymentPort

Port interface for Saman Shaparak payment gateway.

Defines the contract for Saman IPG adapters implementing payment operations (token request, verification, and reversal).

Methods:

Name Description
initiate_payment

Step 1: Request payment token.

verify_payment

Step 3: Verify transaction.

reverse_payment

Reverse a transaction.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class SamanShaparakPaymentPort:
    """Port interface for Saman Shaparak payment gateway.

    Defines the contract for Saman IPG adapters implementing payment
    operations (token request, verification, and reversal).
    """

    @abstractmethod
    def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token."""
        raise NotImplementedError

    @abstractmethod
    def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
        """Step 3: Verify transaction."""
        raise NotImplementedError

    @abstractmethod
    def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction."""
        raise NotImplementedError

initiate_payment abstractmethod

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@abstractmethod
def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token."""
    raise NotImplementedError

verify_payment abstractmethod

verify_payment(
    request: VerifyRequestDTO,
) -> VerifyResponseDTO

Step 3: Verify transaction.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@abstractmethod
def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
    """Step 3: Verify transaction."""
    raise NotImplementedError

reverse_payment abstractmethod

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@abstractmethod
def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction."""
    raise NotImplementedError

AsyncSamanShaparakPaymentPort

Async port interface for Saman Shaparak payment gateway.

Defines the contract for async Saman IPG adapters implementing payment operations (token request, verification, and reversal).

Methods:

Name Description
initiate_payment

Step 1: Request payment token (async).

verify_payment

Step 3: Verify transaction (async).

reverse_payment

Reverse a transaction (async).

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
class AsyncSamanShaparakPaymentPort:
    """Async port interface for Saman Shaparak payment gateway.

    Defines the contract for async Saman IPG adapters implementing payment
    operations (token request, verification, and reversal).
    """

    @abstractmethod
    async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token (async)."""
        raise NotImplementedError

    @abstractmethod
    async def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
        """Step 3: Verify transaction (async)."""
        raise NotImplementedError

    @abstractmethod
    async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction (async)."""
        raise NotImplementedError

initiate_payment abstractmethod async

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token (async).

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@abstractmethod
async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token (async)."""
    raise NotImplementedError

verify_payment abstractmethod async

verify_payment(
    request: VerifyRequestDTO,
) -> VerifyResponseDTO

Step 3: Verify transaction (async).

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@abstractmethod
async def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
    """Step 3: Verify transaction (async)."""
    raise NotImplementedError

reverse_payment abstractmethod async

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction (async).

Source code in archipy/adapters/internet_payment_gateways/ir/saman/ports.py
@abstractmethod
async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction (async)."""
    raise NotImplementedError

options: show_root_toc_entry: false heading_level: 3

Adapters

Classes:

Name Description
SamanShaparakPaymentAdapter

Saman Shaparak (SEP) Classic Adapter - Full v3/.5 Protocol.

SamanNeoPgShaparakPaymentAdapter

Saman Neo-PG (New Generation) Adapter - Uses dynamic X-IPG-Url.

AsyncSamanShaparakPaymentAdapter

Async Saman Shaparak (SEP) Classic Adapter - Full v3/.5 Protocol.

AsyncSamanNeoPgShaparakPaymentAdapter

Async Saman Neo-PG (New Generation) Adapter - Uses dynamic X-IPG-Url.

SamanShaparakPaymentAdapter

Saman Shaparak (SEP) Classic Adapter - Full v3/.5 Protocol.

Implements the SamanShaparakPaymentPort interface using httpx for HTTP operations. Provides methods for initiating payments, verifying transactions, and reversing payments.

Methods:

Name Description
initiate_payment

Step 1: Request payment token.

verify_payment

Step 3: Verify transaction (strongly recommended).

reverse_payment

Reverse a transaction.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
class SamanShaparakPaymentAdapter(SamanShaparakPaymentPort):
    """Saman Shaparak (SEP) Classic Adapter - Full v3/.5 Protocol.

    Implements the SamanShaparakPaymentPort interface using httpx for HTTP operations.
    Provides methods for initiating payments, verifying transactions, and reversing payments.
    """

    def __init__(self, config: SamanShaparakConfig | None = None) -> None:
        configs = BaseConfig.global_config().SAMAN_SHAPARAK if config is None else config

        if not configs.TERMINAL_ID:
            raise ValueError("TERMINAL_ID must be provided in SamanShaparakConfig")

        self.terminal_id = configs.TERMINAL_ID
        self.payment_url = str(configs.PAYMENT_URL)
        self.verify_url = str(configs.VERIFY_URL)
        self.reverse_url = str(configs.REVERSE_URL)

        proxy = self._get_proxy(configs.PROXIES)
        self.client = httpx.Client(proxy=proxy, timeout=30)

        logger.info(f"SamanShaparakPaymentAdapter initialized with terminal {self.terminal_id}")

    @staticmethod
    def _get_proxy(proxies: dict[str, str] | None) -> str | None:
        if proxies is None:
            return None
        return proxies.get("https") or proxies.get("http") or proxies.get("socks5") or proxies.get("socks5h")

    def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token.

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, etc.

        Raises:
            UnavailableError: If the payment service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {
                "action": "token",
                "TerminalId": self.terminal_id,
                "Amount": request.amount,
                "ResNum": request.res_num,
                "RedirectUrl": str(request.redirect_url),
                "CellNumber": request.cell_number,
                "Wage": request.wage,
                "TokenExpiryInMin": request.token_expiry_in_min,
                "HashedCardNumber": request.hashed_card_number,
            }
            payload = {k: v for k, v in payload.items() if v is not None}

            logger.debug(f"Saman initiate payment payload: {payload}")
            resp = self.client.post(self.payment_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            return PaymentResponseDTO(
                status=data.get("status"),
                token=data.get("token"),
                error_code=data.get("errorCode"),
                error_desc=data.get("errorDesc"),
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Token Service") from e
        except Exception as e:
            raise InternalError() from e

    def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
        """Step 3: Verify transaction (strongly recommended).

        Args:
            request: Verify request with reference number.

        Returns:
            VerifyResponseDTO: Response containing transaction details.

        Raises:
            UnavailableError: If the verify service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}

            resp = self.client.post(self.verify_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            transaction_detail = data.get("TransactionDetail") or {}
            return VerifyResponseDTO(
                success=data.get("Success", False),
                result_code=data.get("ResultCode", -1),
                result_description=data.get("ResultDescription", "Unknown"),
                rrn=transaction_detail.get("RRN"),
                reference_number=transaction_detail.get("RefNum"),
                masked_pan=transaction_detail.get("MaskedPan"),
                hashed_pan=transaction_detail.get("HashedPan"),
                original_amount=transaction_detail.get("OrginalAmount"),
                affective_amount=transaction_detail.get("AffectiveAmount"),
                trace_no=transaction_detail.get("StraceNo"),
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Verify Service") from e
        except Exception as e:
            raise InternalError() from e

    def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction.

        Args:
            request: Reverse request with reference number.

        Returns:
            ReverseResponseDTO: Response containing reversal result.

        Raises:
            UnavailableError: If the reverse service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}
            resp = self.client.post(self.reverse_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            return ReverseResponseDTO(
                success=data.get("Success", False),
                result_code=data.get("ResultCode", -1),
                result_description=data.get("ResultDescription", "Unknown"),
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Reverse Service") from e
        except Exception as e:
            raise InternalError() from e

initiate_payment

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token.

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, etc.

Raises:

Type Description
UnavailableError

If the payment service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token.

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, etc.

    Raises:
        UnavailableError: If the payment service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {
            "action": "token",
            "TerminalId": self.terminal_id,
            "Amount": request.amount,
            "ResNum": request.res_num,
            "RedirectUrl": str(request.redirect_url),
            "CellNumber": request.cell_number,
            "Wage": request.wage,
            "TokenExpiryInMin": request.token_expiry_in_min,
            "HashedCardNumber": request.hashed_card_number,
        }
        payload = {k: v for k, v in payload.items() if v is not None}

        logger.debug(f"Saman initiate payment payload: {payload}")
        resp = self.client.post(self.payment_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        return PaymentResponseDTO(
            status=data.get("status"),
            token=data.get("token"),
            error_code=data.get("errorCode"),
            error_desc=data.get("errorDesc"),
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Token Service") from e
    except Exception as e:
        raise InternalError() from e

verify_payment

verify_payment(
    request: VerifyRequestDTO,
) -> VerifyResponseDTO

Step 3: Verify transaction (strongly recommended).

Parameters:

Name Type Description Default
request VerifyRequestDTO

Verify request with reference number.

required

Returns:

Name Type Description
VerifyResponseDTO VerifyResponseDTO

Response containing transaction details.

Raises:

Type Description
UnavailableError

If the verify service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
    """Step 3: Verify transaction (strongly recommended).

    Args:
        request: Verify request with reference number.

    Returns:
        VerifyResponseDTO: Response containing transaction details.

    Raises:
        UnavailableError: If the verify service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}

        resp = self.client.post(self.verify_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        transaction_detail = data.get("TransactionDetail") or {}
        return VerifyResponseDTO(
            success=data.get("Success", False),
            result_code=data.get("ResultCode", -1),
            result_description=data.get("ResultDescription", "Unknown"),
            rrn=transaction_detail.get("RRN"),
            reference_number=transaction_detail.get("RefNum"),
            masked_pan=transaction_detail.get("MaskedPan"),
            hashed_pan=transaction_detail.get("HashedPan"),
            original_amount=transaction_detail.get("OrginalAmount"),
            affective_amount=transaction_detail.get("AffectiveAmount"),
            trace_no=transaction_detail.get("StraceNo"),
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Verify Service") from e
    except Exception as e:
        raise InternalError() from e

reverse_payment

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction.

Parameters:

Name Type Description Default
request ReverseRequestDTO

Reverse request with reference number.

required

Returns:

Name Type Description
ReverseResponseDTO ReverseResponseDTO

Response containing reversal result.

Raises:

Type Description
UnavailableError

If the reverse service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction.

    Args:
        request: Reverse request with reference number.

    Returns:
        ReverseResponseDTO: Response containing reversal result.

    Raises:
        UnavailableError: If the reverse service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}
        resp = self.client.post(self.reverse_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        return ReverseResponseDTO(
            success=data.get("Success", False),
            result_code=data.get("ResultCode", -1),
            result_description=data.get("ResultDescription", "Unknown"),
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Reverse Service") from e
    except Exception as e:
        raise InternalError() from e

SamanNeoPgShaparakPaymentAdapter

Saman Neo-PG (New Generation) Adapter - Uses dynamic X-IPG-Url.

Extends SamanShaparakPaymentAdapter to capture the dynamic payment page URL from the X-IPG-Url header in the token response.

Methods:

Name Description
initiate_payment

Override to capture dynamic neo-pg URL from header.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
class SamanNeoPgShaparakPaymentAdapter(SamanShaparakPaymentAdapter):
    """Saman Neo-PG (New Generation) Adapter - Uses dynamic X-IPG-Url.

    Extends SamanShaparakPaymentAdapter to capture the dynamic payment page URL
    from the X-IPG-Url header in the token response.
    """

    def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Override to capture dynamic neo-pg URL from header.

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, and IPG URL.

        Raises:
            UnavailableError: If the payment service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {
                "action": "token",
                "TerminalId": self.terminal_id,
                "Amount": request.amount,
                "ResNum": request.res_num,
                "RedirectUrl": str(request.redirect_url),
                "CellNumber": request.cell_number,
                "Wage": request.wage,
                "TokenExpiryInMin": request.token_expiry_in_min,
                "HashedCardNumber": request.hashed_card_number,
            }
            payload = {k: v for k, v in payload.items() if v is not None}

            resp = self.client.post(self.payment_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            ipg_url = resp.headers.get("X-IPG-Url")

            return PaymentResponseDTO(
                status=data.get("status"),
                token=data.get("token"),
                error_code=data.get("errorCode"),
                error_desc=data.get("errorDesc"),
                ipg_url=ipg_url,
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Neo-PG Token Service") from e
        except Exception as e:
            raise InternalError() from e

initiate_payment

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Override to capture dynamic neo-pg URL from header.

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, and IPG URL.

Raises:

Type Description
UnavailableError

If the payment service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Override to capture dynamic neo-pg URL from header.

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, and IPG URL.

    Raises:
        UnavailableError: If the payment service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {
            "action": "token",
            "TerminalId": self.terminal_id,
            "Amount": request.amount,
            "ResNum": request.res_num,
            "RedirectUrl": str(request.redirect_url),
            "CellNumber": request.cell_number,
            "Wage": request.wage,
            "TokenExpiryInMin": request.token_expiry_in_min,
            "HashedCardNumber": request.hashed_card_number,
        }
        payload = {k: v for k, v in payload.items() if v is not None}

        resp = self.client.post(self.payment_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        ipg_url = resp.headers.get("X-IPG-Url")

        return PaymentResponseDTO(
            status=data.get("status"),
            token=data.get("token"),
            error_code=data.get("errorCode"),
            error_desc=data.get("errorDesc"),
            ipg_url=ipg_url,
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Neo-PG Token Service") from e
    except Exception as e:
        raise InternalError() from e

AsyncSamanShaparakPaymentAdapter

Async Saman Shaparak (SEP) Classic Adapter - Full v3/.5 Protocol.

Async implementation of SamanShaparakPaymentPort using httpx.AsyncClient. Provides async methods for initiating payments, verifying transactions, and reversing payments.

Methods:

Name Description
initiate_payment

Step 1: Request payment token (async).

verify_payment

Step 3: Verify transaction (async, strongly recommended).

reverse_payment

Reverse a transaction (async).

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
class AsyncSamanShaparakPaymentAdapter(AsyncSamanShaparakPaymentPort):
    """Async Saman Shaparak (SEP) Classic Adapter - Full v3/.5 Protocol.

    Async implementation of SamanShaparakPaymentPort using httpx.AsyncClient.
    Provides async methods for initiating payments, verifying transactions,
    and reversing payments.
    """

    def __init__(self, config: SamanShaparakConfig | None = None) -> None:
        configs = BaseConfig.global_config().SAMAN_SHAPARAK if config is None else config

        if not configs.TERMINAL_ID:
            raise ValueError("TERMINAL_ID must be provided in SamanShaparakConfig")

        self.terminal_id = configs.TERMINAL_ID
        self.payment_url = str(configs.PAYMENT_URL)
        self.verify_url = str(configs.VERIFY_URL)
        self.reverse_url = str(configs.REVERSE_URL)

        proxy = self._get_proxy(configs.PROXIES)
        self.client = httpx.AsyncClient(proxy=proxy, timeout=30)

        logger.info(f"AsyncSamanShaparakPaymentAdapter initialized with terminal {self.terminal_id}")

    @staticmethod
    def _get_proxy(proxies: dict[str, str] | None) -> str | None:
        if proxies is None:
            return None
        return proxies.get("https") or proxies.get("http") or proxies.get("socks5") or proxies.get("socks5h")

    async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Step 1: Request payment token (async).

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, etc.

        Raises:
            UnavailableError: If the payment service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {
                "action": "token",
                "TerminalId": self.terminal_id,
                "Amount": request.amount,
                "ResNum": request.res_num,
                "RedirectUrl": str(request.redirect_url),
                "CellNumber": request.cell_number,
                "Wage": request.wage,
                "TokenExpiryInMin": request.token_expiry_in_min,
                "HashedCardNumber": request.hashed_card_number,
            }
            payload = {k: v for k, v in payload.items() if v is not None}

            logger.debug(f"Saman async initiate payment payload: {payload}")
            resp = await self.client.post(self.payment_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            return PaymentResponseDTO(
                status=data.get("status"),
                token=data.get("token"),
                error_code=data.get("errorCode"),
                error_desc=data.get("errorDesc"),
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Token Service") from e
        except Exception as e:
            raise InternalError() from e

    async def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
        """Step 3: Verify transaction (async, strongly recommended).

        Args:
            request: Verify request with reference number.

        Returns:
            VerifyResponseDTO: Response containing transaction details.

        Raises:
            UnavailableError: If the verify service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}

            resp = await self.client.post(self.verify_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            transaction_detail = data.get("TransactionDetail") or {}
            return VerifyResponseDTO(
                success=data.get("Success", False),
                result_code=data.get("ResultCode", -1),
                result_description=data.get("ResultDescription", "Unknown"),
                rrn=transaction_detail.get("RRN"),
                reference_number=transaction_detail.get("RefNum"),
                masked_pan=transaction_detail.get("MaskedPan"),
                hashed_pan=transaction_detail.get("HashedPan"),
                original_amount=transaction_detail.get("OrginalAmount"),
                affective_amount=transaction_detail.get("AffectiveAmount"),
                trace_no=transaction_detail.get("StraceNo"),
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Verify Service") from e
        except Exception as e:
            raise InternalError() from e

    async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
        """Reverse a transaction (async).

        Args:
            request: Reverse request with reference number.

        Returns:
            ReverseResponseDTO: Response containing reversal result.

        Raises:
            UnavailableError: If the reverse service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}
            resp = await self.client.post(self.reverse_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            return ReverseResponseDTO(
                success=data.get("Success", False),
                result_code=data.get("ResultCode", -1),
                result_description=data.get("ResultDescription", "Unknown"),
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Reverse Service") from e
        except Exception as e:
            raise InternalError() from e

initiate_payment async

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Step 1: Request payment token (async).

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, etc.

Raises:

Type Description
UnavailableError

If the payment service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Step 1: Request payment token (async).

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, etc.

    Raises:
        UnavailableError: If the payment service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {
            "action": "token",
            "TerminalId": self.terminal_id,
            "Amount": request.amount,
            "ResNum": request.res_num,
            "RedirectUrl": str(request.redirect_url),
            "CellNumber": request.cell_number,
            "Wage": request.wage,
            "TokenExpiryInMin": request.token_expiry_in_min,
            "HashedCardNumber": request.hashed_card_number,
        }
        payload = {k: v for k, v in payload.items() if v is not None}

        logger.debug(f"Saman async initiate payment payload: {payload}")
        resp = await self.client.post(self.payment_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        return PaymentResponseDTO(
            status=data.get("status"),
            token=data.get("token"),
            error_code=data.get("errorCode"),
            error_desc=data.get("errorDesc"),
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Token Service") from e
    except Exception as e:
        raise InternalError() from e

verify_payment async

verify_payment(
    request: VerifyRequestDTO,
) -> VerifyResponseDTO

Step 3: Verify transaction (async, strongly recommended).

Parameters:

Name Type Description Default
request VerifyRequestDTO

Verify request with reference number.

required

Returns:

Name Type Description
VerifyResponseDTO VerifyResponseDTO

Response containing transaction details.

Raises:

Type Description
UnavailableError

If the verify service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
async def verify_payment(self, request: VerifyRequestDTO) -> VerifyResponseDTO:
    """Step 3: Verify transaction (async, strongly recommended).

    Args:
        request: Verify request with reference number.

    Returns:
        VerifyResponseDTO: Response containing transaction details.

    Raises:
        UnavailableError: If the verify service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}

        resp = await self.client.post(self.verify_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        transaction_detail = data.get("TransactionDetail") or {}
        return VerifyResponseDTO(
            success=data.get("Success", False),
            result_code=data.get("ResultCode", -1),
            result_description=data.get("ResultDescription", "Unknown"),
            rrn=transaction_detail.get("RRN"),
            reference_number=transaction_detail.get("RefNum"),
            masked_pan=transaction_detail.get("MaskedPan"),
            hashed_pan=transaction_detail.get("HashedPan"),
            original_amount=transaction_detail.get("OrginalAmount"),
            affective_amount=transaction_detail.get("AffectiveAmount"),
            trace_no=transaction_detail.get("StraceNo"),
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Verify Service") from e
    except Exception as e:
        raise InternalError() from e

reverse_payment async

reverse_payment(
    request: ReverseRequestDTO,
) -> ReverseResponseDTO

Reverse a transaction (async).

Parameters:

Name Type Description Default
request ReverseRequestDTO

Reverse request with reference number.

required

Returns:

Name Type Description
ReverseResponseDTO ReverseResponseDTO

Response containing reversal result.

Raises:

Type Description
UnavailableError

If the reverse service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
async def reverse_payment(self, request: ReverseRequestDTO) -> ReverseResponseDTO:
    """Reverse a transaction (async).

    Args:
        request: Reverse request with reference number.

    Returns:
        ReverseResponseDTO: Response containing reversal result.

    Raises:
        UnavailableError: If the reverse service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {"RefNum": request.reference_number, "TerminalNumber": int(self.terminal_id)}
        resp = await self.client.post(self.reverse_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        return ReverseResponseDTO(
            success=data.get("Success", False),
            result_code=data.get("ResultCode", -1),
            result_description=data.get("ResultDescription", "Unknown"),
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Reverse Service") from e
    except Exception as e:
        raise InternalError() from e

AsyncSamanNeoPgShaparakPaymentAdapter

Async Saman Neo-PG (New Generation) Adapter - Uses dynamic X-IPG-Url.

Async implementation extending AsyncSamanShaparakPaymentAdapter to capture the dynamic payment page URL from the X-IPG-Url header in the token response.

Methods:

Name Description
initiate_payment

Override to capture dynamic neo-pg URL from header (async).

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
class AsyncSamanNeoPgShaparakPaymentAdapter(AsyncSamanShaparakPaymentAdapter):
    """Async Saman Neo-PG (New Generation) Adapter - Uses dynamic X-IPG-Url.

    Async implementation extending AsyncSamanShaparakPaymentAdapter to capture
    the dynamic payment page URL from the X-IPG-Url header in the token response.
    """

    async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
        """Override to capture dynamic neo-pg URL from header (async).

        Args:
            request: Payment request data.

        Returns:
            PaymentResponseDTO: Response containing token, status, and IPG URL.

        Raises:
            UnavailableError: If the payment service is unavailable.
            InternalError: If an unexpected error occurs.
        """
        try:
            payload = {
                "action": "token",
                "TerminalId": self.terminal_id,
                "Amount": request.amount,
                "ResNum": request.res_num,
                "RedirectUrl": str(request.redirect_url),
                "CellNumber": request.cell_number,
                "Wage": request.wage,
                "TokenExpiryInMin": request.token_expiry_in_min,
                "HashedCardNumber": request.hashed_card_number,
            }
            payload = {k: v for k, v in payload.items() if v is not None}

            resp = await self.client.post(self.payment_url, json=payload)
            resp.raise_for_status()
            data = resp.json()

            ipg_url = resp.headers.get("X-IPG-Url")

            return PaymentResponseDTO(
                status=data.get("status"),
                token=data.get("token"),
                error_code=data.get("errorCode"),
                error_desc=data.get("errorDesc"),
                ipg_url=ipg_url,
            )
        except httpx.RequestError as e:
            raise UnavailableError(resource_type="Saman Neo-PG Token Service") from e
        except Exception as e:
            raise InternalError() from e

initiate_payment async

initiate_payment(
    request: PaymentRequestDTO,
) -> PaymentResponseDTO

Override to capture dynamic neo-pg URL from header (async).

Parameters:

Name Type Description Default
request PaymentRequestDTO

Payment request data.

required

Returns:

Name Type Description
PaymentResponseDTO PaymentResponseDTO

Response containing token, status, and IPG URL.

Raises:

Type Description
UnavailableError

If the payment service is unavailable.

InternalError

If an unexpected error occurs.

Source code in archipy/adapters/internet_payment_gateways/ir/saman/adapters.py
async def initiate_payment(self, request: PaymentRequestDTO) -> PaymentResponseDTO:
    """Override to capture dynamic neo-pg URL from header (async).

    Args:
        request: Payment request data.

    Returns:
        PaymentResponseDTO: Response containing token, status, and IPG URL.

    Raises:
        UnavailableError: If the payment service is unavailable.
        InternalError: If an unexpected error occurs.
    """
    try:
        payload = {
            "action": "token",
            "TerminalId": self.terminal_id,
            "Amount": request.amount,
            "ResNum": request.res_num,
            "RedirectUrl": str(request.redirect_url),
            "CellNumber": request.cell_number,
            "Wage": request.wage,
            "TokenExpiryInMin": request.token_expiry_in_min,
            "HashedCardNumber": request.hashed_card_number,
        }
        payload = {k: v for k, v in payload.items() if v is not None}

        resp = await self.client.post(self.payment_url, json=payload)
        resp.raise_for_status()
        data = resp.json()

        ipg_url = resp.headers.get("X-IPG-Url")

        return PaymentResponseDTO(
            status=data.get("status"),
            token=data.get("token"),
            error_code=data.get("errorCode"),
            error_desc=data.get("errorDesc"),
            ipg_url=ipg_url,
        )
    except httpx.RequestError as e:
        raise UnavailableError(resource_type="Saman Neo-PG Token Service") from e
    except Exception as e:
        raise InternalError() from e

options: show_root_toc_entry: false heading_level: 3