Skip to main content

django-iyzico

Django integration for Iyzico payment gateway - Turkey's leading payment solution

Python Version Django Version License Tests Coverage Version

Note: This is an unofficial, community-maintained package and is not endorsed by or affiliated with Iyzico. For the official Iyzico Python SDK, please visit iyzipay-python.

django-iyzico provides a complete Django-native integration for the Iyzico payment gateway, designed specifically for the Turkish market. Reduce integration time from days to hours with a secure, well-tested, production-ready solution.

🌟 Features

Core Features

  • ✅ Payment Processing - Direct payments and 3D Secure support
  • ✅ Subscription Payments - Recurring billing with automated lifecycle management
  • ✅ Installment Payments - Full installment support with BIN-based options
  • ✅ Multi-Currency - Support for TRY, USD, EUR, GBP with conversion
  • ✅ PCI DSS Compliant - Secure card data handling (never stores full card numbers)
  • ✅ Refund Processing - Full and partial refunds
  • ✅ Django Admin - Professional interface with color-coded statuses
  • ✅ Webhook Handling - Real-time payment status updates
  • ✅ Signal System - Event-driven architecture (20 signals)
  • ✅ Celery Integration - Automated subscription billing and task processing
  • ✅ Management Commands - Sync and cleanup utilities
  • ✅ Type Hints - Full type coverage for IDE support
  • ✅ Well Tested - 662+ tests, 95%+ coverage across all modules
  • ✅ Monitoring - Structured logging, metrics, and alerting

Optional Features

  • 🔌 Django REST Framework - Optional API support
  • 🔧 Advanced Utilities - Currency conversion, installment calculation, basket ID generator

📦 Installation

pip install django-iyzico

Requirements

  • Python 3.12+
  • Django 4.2+ (supports 4.2 LTS, 5.2, 6.0)
  • iyzipay >= 1.0.45

🚀 Quick Start

1. Add to INSTALLED_APPS

# settings.py
INSTALLED_APPS = [
    ...
    'django_iyzico',
]

2. Configure Settings

# settings.py

# Required settings
IYZICO_API_KEY = 'your-api-key'
IYZICO_SECRET_KEY = 'your-secret-key'
IYZICO_BASE_URL = 'https://sandbox-api.iyzipay.com'  # Sandbox
# IYZICO_BASE_URL = 'https://api.iyzipay.com'  # Production

# Optional settings (with defaults)
IYZICO_LOCALE = 'tr'  # Default locale
IYZICO_CURRENCY = 'TRY'  # Default currency

# Optional webhook security
IYZICO_WEBHOOK_SECRET = 'your-webhook-secret'  # For signature validation
IYZICO_WEBHOOK_ALLOWED_IPS = ['1.2.3.4', '5.6.7.0/24']  # IP whitelist with CIDR

3. Create Your Payment Model

# models.py
from django.db import models
from django_iyzico.models import AbstractIyzicoPayment

class Order(AbstractIyzicoPayment):
    """Your order model extending Iyzico payment."""

    user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    product = models.CharField(max_length=200)

    class Meta:
        db_table = 'orders'
        ordering = ['-created_at']

4. Run Migrations

python manage.py makemigrations
python manage.py migrate

5. Include URLs

# urls.py
from django.urls import path, include

urlpatterns = [
    path('payments/', include('django_iyzico.urls')),
    ...
]

6. Process a Payment

# views.py
from decimal import Decimal
from django_iyzico.client import IyzicoClient
from .models import Order

def checkout(request):
    # Create order
    order = Order.objects.create(
        user=request.user,
        product="Premium Subscription",
        amount=Decimal("99.00"),
        conversation_id="ORDER-12345"
    )

    # Process payment
    client = IyzicoClient()

    payment_data = {
        'price': '99.00',
        'paidPrice': '99.00',
        'currency': 'TRY',
        'basketId': 'BASKET-12345',
        'paymentCard': {
            'cardHolderName': request.POST['card_holder'],
            'cardNumber': request.POST['card_number'],
            'expireMonth': request.POST['expire_month'],
            'expireYear': request.POST['expire_year'],
            'cvc': request.POST['cvc'],
        },
        'buyer': {
            'id': str(request.user.id),
            'name': request.user.first_name,
            'surname': request.user.last_name,
            'email': request.user.email,
            'identityNumber': '11111111111',
            'registrationAddress': 'Address here',
            'city': 'Istanbul',
            'country': 'Turkey',
            'zipCode': '34000',
        },
    }

    try:
        response = client.create_payment(payment_data)

        if response.is_successful():
            # Update order
            order.update_from_response(response)
            return redirect('order_success', order_id=order.id)
        else:
            messages.error(request, response.error_message)
            return redirect('checkout')

    except PaymentError as e:
        messages.error(request, "Payment failed. Please try again.")
        return redirect('checkout')

7. Process Subscription Payments (v0.2.0+)

from django_iyzico.subscription_models import SubscriptionPlan, Subscription
from django_iyzico.subscription_manager import SubscriptionManager

# Create a subscription plan
plan = SubscriptionPlan.objects.create(
    name="Premium Monthly",
    price=Decimal("99.00"),
    currency="TRY",
    billing_interval="MONTHLY",
    billing_period=1,
    trial_days=7
)

# Subscribe a user
manager = SubscriptionManager()
subscription = manager.create_subscription(
    plan=plan,
    user=request.user,
    payment_method={
        'cardHolderName': 'John Doe',
        'cardNumber': '5528790000000008',
        'expireMonth': '12',
        'expireYear': '2030',
        'cvc': '123',
    }
)

# Subscription automatically bills every month
# See docs/SUBSCRIPTION_GUIDE.md for complete guide

8. Use Installment Payments (v0.2.0+)

from django_iyzico.installment_client import InstallmentClient

# Get installment options for a card
client = InstallmentClient()
options = client.get_installment_info(
    bin_number='552879',  # First 6 digits of card
    price=Decimal('1000.00')
)

# Display installment options to user
for option in options:
    print(f"{option.installment_count} installments: {option.installment_price}/month")
    print(f"Total: {option.total_price} (Rate: {option.installment_rate}%)")

# Process payment with installments
payment_data['installment'] = 3  # 3 installments
response = client.create_payment(payment_data)

# See docs/INSTALLMENT_GUIDE.md for complete guide

9. Multi-Currency Support (v0.2.0+)

from django_iyzico.currency import format_amount, CurrencyConverter

# Create payment in any supported currency
order = Order.objects.create(
    amount=Decimal("100.00"),
    currency='USD'  # TRY, USD, EUR, or GBP
)

# Format amount with currency symbol
formatted = order.get_formatted_amount()  # "$100.00"

# Convert between currencies
converter = CurrencyConverter()
try_amount = order.convert_to_currency('TRY')
print(f"${order.amount} USD = ₺{try_amount} TRY")

# See docs/CURRENCY_GUIDE.md for complete guide

🎨 Django Admin Integration

# admin.py
from django.contrib import admin
from django_iyzico.admin import IyzicoPaymentAdminMixin
from .models import Order

@admin.register(Order)
class OrderAdmin(IyzicoPaymentAdminMixin, admin.ModelAdmin):
    list_display = IyzicoPaymentAdminMixin.list_display + ['user', 'product']

    # All payment admin features included:
    # - Color-coded status badges
    # - Advanced filtering
    # - Bulk refund action
    # - CSV export
    # - Delete protection

📡 Signal Handling

django-iyzico provides 20 signals for payment, subscription, and monitoring events:

Payment Signals (8 signals)

# signals.py
from django.dispatch import receiver
from django_iyzico.signals import (
    payment_completed, payment_failed, payment_refunded,
    threeds_completed, webhook_received
)

@receiver(payment_completed)
def on_payment_success(sender, instance, **kwargs):
    """Handle successful payment."""
    # Update user subscription
    instance.user.activate_premium()

    # Send confirmation email
    send_email(instance.buyer_email, "Payment Confirmed")

    # Log for analytics
    track_event('payment_success', amount=instance.amount)

@receiver(payment_failed)
def on_payment_failed(sender, instance, **kwargs):
    """Handle failed payment."""
    # Log failure
    logger.error(f"Payment failed: {instance.error_message}")

    # Notify user
    send_email(instance.buyer_email, "Payment Failed")

Subscription Signals (9 signals - v0.2.0+)

from django_iyzico.subscription_signals import (
    subscription_created, subscription_activated,
    subscription_cancelled, subscription_payment_succeeded,
    subscription_payment_failed
)

@receiver(subscription_activated)
def on_subscription_activated(sender, subscription, **kwargs):
    """Handle subscription activation."""
    # Grant access to premium features
    subscription.user.grant_premium_access()

    # Send welcome email
    send_email(subscription.user.email, "Welcome to Premium!")

@receiver(subscription_payment_failed)
def on_subscription_payment_failed(sender, subscription, payment, **kwargs):
    """Handle failed subscription payment."""
    # Notify user
    send_email(subscription.user.email, "Payment Failed - Please Update Card")

    # Log for retry
    logger.warning(f"Subscription {subscription.id} payment failed")

Monitoring Signals (3 signals - v0.2.0+)

from django_iyzico.signals import (
    payment_alert, double_billing_prevented, high_failure_rate_detected
)

@receiver(payment_alert)
def on_payment_alert(sender, alert_type, message, severity, **kwargs):
    """Handle payment system alerts."""
    if severity == 'critical':
        notify_ops_team(alert_type, message)

@receiver(double_billing_prevented)
def on_double_billing_prevented(sender, subscription_id, **kwargs):
    """Log prevented double billing attempts."""
    logger.info(f"Double billing prevented for subscription {subscription_id}")

@receiver(high_failure_rate_detected)
def on_high_failure_rate(sender, failure_rate, threshold, **kwargs):
    """Alert on high payment failure rates."""
    alert_ops(f"Payment failure rate {failure_rate:.1%} exceeds threshold {threshold:.1%}")

🔄 Webhook Handling

Webhooks are automatically handled at /payments/webhook/. Configure your Iyzico merchant panel to send webhooks to:

https://yourdomain.com/payments/webhook/

For enhanced security, configure webhook validation:

# settings.py
IYZICO_WEBHOOK_SECRET = 'your-webhook-secret'  # HMAC signature validation
IYZICO_WEBHOOK_ALLOWED_IPS = ['1.2.3.4']  # IP whitelist

💰 Refund Processing

# Process a refund
from .models import Order

order = Order.objects.get(id=order_id)

# Full refund
response = order.process_refund()

# Partial refund
response = order.process_refund(
    amount=Decimal("50.00"),
    reason="Customer request"
)

if response.is_successful():
    # Refund processed
    # Status automatically updated
    # Signal automatically triggered
    pass

🛠️ Management Commands

Sync Payment Statuses

# Sync payments from last 7 days
python manage.py sync_iyzico_payments --model myapp.models.Order --days 7

# Dry run (see what would be updated)
python manage.py sync_iyzico_payments --model myapp.models.Order --dry-run

# Filter by status
python manage.py sync_iyzico_payments --model myapp.models.Order --status pending

Clean Up Old Payments

# Delete payments older than 365 days
python manage.py cleanup_old_payments --model myapp.models.Order --days 365

# Keep successful payments longer
python manage.py cleanup_old_payments \
    --model myapp.models.Order \
    --days 365 \
    --keep-successful 730

# Export before deleting
python manage.py cleanup_old_payments \
    --model myapp.models.Order \
    --export /backup/payments.csv \
    --days 365

🔌 Django REST Framework (Optional)

If you have DRF installed, you can use the optional API support:

# urls.py
from rest_framework.routers import DefaultRouter
from django_iyzico.viewsets import IyzicoPaymentViewSet
from .models import Order

router = DefaultRouter()

# Configure viewset with your model
class OrderPaymentViewSet(IyzicoPaymentViewSet):
    queryset = Order.objects.all()

router.register('payments', OrderPaymentViewSet, basename='payment')

urlpatterns = [
    path('api/', include(router.urls)),
]

API Endpoints:

  • GET /api/payments/ - List all payments
  • GET /api/payments/{id}/ - Retrieve payment details
  • GET /api/payments/successful/ - List successful payments
  • GET /api/payments/failed/ - List failed payments
  • GET /api/payments/stats/ - Payment statistics

🔒 Security

PCI DSS Compliance

django-iyzico is designed to be PCI DSS Level 1 compliant:

  • ✅ Never stores full card numbers - Only last 4 digits
  • ✅ Never stores CVC/CVV codes
  • ✅ Automatic log sanitization - No sensitive data in logs
  • ✅ Secure card data masking
  • ✅ Input validation on all endpoints

Webhook Security

  • ✅ HMAC-SHA256 signature validation
  • ✅ IP whitelisting with CIDR support
  • ✅ Constant-time comparison (timing attack prevention)
  • ✅ X-Forwarded-For header support

Best Practices

See SECURITY.md for complete security guidelines.

🧪 Testing

# Run all tests
pytest

# With coverage
pytest --cov=django_iyzico --cov-report=html

# Specific test file
pytest tests/test_client.py -v

Test Statistics:

  • 662+ test methods across 22 test files
  • 95%+ coverage across all modules
  • ~12,000 lines of test code
  • Comprehensive test suites for payments, subscriptions, installments, currency, and monitoring
  • 83+ security-critical tests

🔧 Troubleshooting

Common Issues and Solutions

1. Payment Fails with "INVALID_SIGNATURE" Error

Problem: Payment requests return an error about invalid signature.

Solution:

# Verify your API credentials are correct
# settings.py
IYZICO_API_KEY = 'your-correct-api-key'
IYZICO_SECRET_KEY = 'your-correct-secret-key'
IYZICO_BASE_URL = 'https://sandbox-api.iyzipay.com'  # For testing

# Check that credentials match your Iyzico merchant panel
# Production credentials differ from sandbox credentials

2. Webhook Not Receiving Updates

Problem: Payments succeed but webhooks don't trigger.

Solution:

# 1. Ensure webhook URL is publicly accessible
IYZICO_WEBHOOK_SECRET = 'your-webhook-secret'

# 2. Configure webhook URL in Iyzico merchant panel:
# https://yourdomain.com/payments/webhook/

# 3. Check webhook logs
import logging
logger = logging.getLogger('django_iyzico')
logger.setLevel(logging.DEBUG)

# 4. Verify IP whitelist (if configured)
IYZICO_WEBHOOK_ALLOWED_IPS = []  # Allow all IPs for testing

# 5. Test webhook locally with ngrok:
# ngrok http 8000
# Use ngrok URL in Iyzico panel

3. "Payment ID already exists" Error

Problem: Duplicate payment_id constraint violation.

Solution:

# Use unique conversation_id for each payment attempt
import uuid

order = Order.objects.create(
    conversation_id=f"ORDER-{uuid.uuid4()}",  # Always unique
    amount=Decimal("99.00")
)

# Or use the utility function
from django_iyzico.utils import generate_basket_id
basket_id = generate_basket_id()  # Returns UUID-based ID

4. Card Data Not Saving

Problem: card_last_four_digits is always None.

Solution:

# Store card data before sending to Iyzico
payment_data = {
    'paymentCard': {
        'cardNumber': '5528790000000008',
        # ... other fields
    }
}

# Extract and store card info
order.mask_and_store_card_data(payment_data)

# Then process payment
response = client.create_payment(...)

5. 3D Secure Callback Fails

Problem: 3DS callback returns 404 or doesn't update payment.

Solution:

# 1. Verify URLs are included in your project
# urls.py
urlpatterns = [
    path('payments/', include('django_iyzico.urls')),  # Required
]

# 2. Check callback URL configuration
IYZICO_CALLBACK_URL = 'https://yourdomain.com/payments/callback/'

# 3. Ensure callback URL is accessible (not behind auth)
# The view has @csrf_exempt decorator by default

# 4. Check payment token in callback
# Token should be in GET parameters: ?token=xxx

6. Refund Fails with "INSUFFICIENT_FUNDS"

Problem: Refund requests fail even though payment was successful.

Solution:

# 1. Check payment status
if order.can_be_refunded():
    # Payment must be SUCCESS status
    response = order.process_refund()

# 2. For partial refunds, ensure amount is valid
if order.amount >= Decimal("50.00"):
    response = order.process_refund(amount=Decimal("50.00"))

# 3. Check Iyzico merchant account balance
# Refunds require sufficient balance in merchant account

# 4. Wait time: Allow 24 hours after payment before refund

7. Admin Shows Wrong Payment Status

Problem: Admin displays incorrect status or outdated data.

Solution:

# Sync payment statuses with Iyzico API
python manage.py sync_iyzico_payments --model myapp.Order --days 7

# Check for specific payment
python manage.py sync_iyzico_payments --model myapp.Order --payment-id 12345

# Use --dry-run to see what would be updated
python manage.py sync_iyzico_payments --model myapp.Order --dry-run

8. Migration Errors

Problem: Errors when running makemigrations or migrate.

Solution:

# 1. Ensure django_iyzico is in INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    # ...
    'django_iyzico',  # Add this
    'myapp',  # Your app with Order model
]

# 2. Create migrations for your model
python manage.py makemigrations myapp

# 3. Apply migrations
python manage.py migrate

# 4. If you get conflicts, try:
python manage.py makemigrations --merge

9. Test Card Numbers Not Working

Problem: Sandbox test cards are being rejected.

Solution:

# Use Iyzico's official test cards:

# Successful payment test card:
{
    'cardNumber': '5528790000000008',
    'cardHolderName': 'John Doe',
    'expireMonth': '12',
    'expireYear': '2030',
    'cvc': '123'
}

# 3D Secure test card (OTP: 123456):
{
    'cardNumber': '5528790000000008',
    'cardHolderName': 'John Doe',
    'expireMonth': '12',
    'expireYear': '2030',
    'cvc': '123'
}

# Ensure you're using SANDBOX_BASE_URL
IYZICO_BASE_URL = 'https://sandbox-api.iyzipay.com'

10. High Response Times

Problem: Payment processing is slow.

Solution:

# 1. Enable database connection pooling
# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'CONN_MAX_AGE': 600,  # Connection pooling
    }
}

# 2. Use select_related for foreign keys
orders = Order.objects.select_related('user').all()

# 3. Add database indexes (already included in AbstractIyzicoPayment)
# Check with:
# python manage.py sqlmigrate myapp 0001

# 4. Cache Iyzico settings
from django.core.cache import cache
# Settings are auto-cached in IyzicoClient

# 5. Use async views for I/O-bound operations (Django 4.1+)
from django.views.decorators.http import require_http_methods

Debug Mode

Enable detailed logging for troubleshooting:

# settings.py
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django_iyzico': {
            'handlers': ['console'],
            'level': 'DEBUG',  # Shows all API calls
            'propagate': False,
        },
    },
}

Getting Help

If you're still experiencing issues:

  1. Check the GitHub Issues for similar problems
  2. Review the SECURITY.md for security-related questions
  3. Enable DEBUG logging and check the output
  4. Create a new issue with:
    • Django version
    • Python version
    • django-iyzico version
    • Error message and full traceback
    • Minimal code to reproduce the issue

📚 Documentation

Core Documentation

Feature Guides (v0.2.0+)

🤝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Development Setup

# Clone repository
git clone https://github.com/aladagemre/django-iyzico.git
cd django-iyzico

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black django_iyzico tests
isort django_iyzico tests

# Run linters
flake8 django_iyzico
mypy django_iyzico

📊 Project Status

Phase Status Features
Milestone 1 ✅ Complete Core payment processing, admin, refunds
Milestone 2 ✅ Complete Subscription payments with Celery
Milestone 3 ✅ Complete Installment payments
Milestone 4 ✅ Complete Multi-currency support
Milestone 5 ✅ Complete v0.2.0 Release with monitoring & CI/CD

🗺️ Roadmap

v0.1.0-beta (Released - December 2025)

  • ✅ Core payment processing (direct and 3D Secure)
  • ✅ Admin interface with advanced features
  • ✅ Refund processing (full and partial)
  • ✅ Webhook handling with security
  • ✅ Management commands
  • ✅ 95% test coverage
  • ✅ PCI DSS compliance

v0.2.0 (Released - December 2025)

  • ✅ Subscription payments - Recurring billing with automated lifecycle
  • ✅ Installment support - BIN-based installment options and processing
  • ✅ Multi-currency support - TRY, USD, EUR, GBP with conversion
  • ✅ Celery integration - Automated subscription billing tasks
  • ✅ Monitoring module - Structured logging, metrics, and alerting
  • ✅ 20 lifecycle signals - Payment, subscription, and monitoring events
  • ✅ 662+ comprehensive tests - 95%+ coverage maintained
  • ✅ CI/CD workflows - GitHub Actions for testing and publishing
  • ✅ DevContainer support - VS Code development environment
  • ✅ Complete example project - Full Django app with all features

v0.3.0 (Planned)

  • Payment tokenization
  • Split payments for marketplaces
  • Additional payment methods (bank transfer, etc.)
  • Enhanced reporting and analytics
  • Webhook retry mechanism

📝 License

MIT License - See LICENSE for details.

🙏 Credits

Built on top of the official iyzipay-python SDK.

💬 Support

⭐ Show Your Support

If django-iyzico helps your project, please give it a star on GitHub!


Author: Emre Aladag (@aladagemre) Version: 0.2.0 Status: ✅ Production-Ready Last Updated: December 18, 2025

Metadata

Release files for django-iyzico 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-iyzico 0.2.2
File Size Uploaded Provenance Actions
django_iyzico-0.2.2.tar.gz 120.3 kB Without provenance Details for django_iyzico-0.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for django-iyzico 0.2.2
File Interpreter ABI Platform Actions
django_iyzico-0.2.2-py3-none-any.whl Python 3 none any Details for django_iyzico-0.2.2-py3-none-any.whl

Total release size: 235.2 kB

Release files / django_iyzico-0.2.2.tar.gz

Download URL django_iyzico-0.2.2.tar.gz
Size 120.3 kB
Tags Source
SHA-256 checksum
How to use checksums
78539ec6d4043b8daef825afcc5c009779622f288e2cf60ca9b07d70952006c4
BLAKE2b-256 checksum
How to use checksums
7503b5082bf547eb088a55455a9ea74292a5daef1da4bcf51bb786a43cc00df9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / django_iyzico-0.2.2-py3-none-any.whl

Download URL django_iyzico-0.2.2-py3-none-any.whl
Size 115.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6b59e93a3c3a6b2e067ba4b031defb794f44c57c188841537a90900360281f1f
BLAKE2b-256 checksum
How to use checksums
dc5ebe6927e96b52ee6f5920d0e18028a057d363a8fe4710abe3b0a05702fd51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Security for django-iyzico 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page