django-pg


Namedjango-pg JSON
Version 0.4.1 PyPI version JSON
download
home_pageNone
SummaryPluggable Django package for integrating multiple payment gateways like Paystack, Flutterwave, etc.
upload_time2025-08-19 02:15:41
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseMIT
keywords django payment paystack flutterwave gateway
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Django Payment Gateways Package

A pluggable Django package for integrating multiple payment gateways (starting with Paystack and Flutterwave), with an extensible architecture that supports more gateways like Stripe, etc.

---

## ✨ Features

- πŸ”Œ Plug-and-play integration
- πŸ” Paystack support (more gateways coming)
- πŸ“¦ Dispatcher pattern for gateway switching
- 🧱 Abstract `BaseOrder` model for customization
- βœ… Built-in Payment Verification View
- 🧠 Smart unique order reference generation
- πŸ§ͺ Built-in signal handling for order reference
- πŸ’‘ Fully customizable frontend and views

---

## Example Project

A sample Django project demonstrating how to use this package is available here:

πŸ‘‰ [django_pg_test_project](https://github.com/niyimarc/payment_gateway_test)

---

## πŸ“¦ Installation

```bash
pip install django-pg
```

## βš™οΈ Project Setup
1. **Add the app to INSTALLED_APPS**

```bash
# settings.py
INSTALLED_APPS = [
    ...
    'django_pg',  # Your payment package
]
```

2. **Define required settings in your settings.py**

```bash
# settings.py

# Models used for order
PAYMENT_ORDER_MODEL = 'yourapp.Order'

# It's recomended that you put the secret key 
# in a .env file and load it in your settings

# Paystack keys
PAYSTACK_PUBLIC_KEY = 'your-paystack-public-key'
PAYSTACK_SECRET_KEY = 'your-paystack-secret-key'

# Flutterwave keys
FLUTTERWAVE_PUBLIC_KEY = "your-flutterwave-public-key"
FLUTTERWAVE_SECRET_KEY = "your-flutterwave-secret-key"

# Interswitch keys
INTERSWITCH_MERCHANT_CODE = "your-interswitch-merchant-code"
INTERSWITCH_PAY_ITEM_ID = "your-interswitch-pay-item-id"

```

3. **Built-in Payment Verification View**
django-pg provides a built-in payment_verification view that handles verifying transactions for all the payment gateways out of the box.
#### πŸ”Œ URL Configuration
You can use the built-in view directly in your urls.py:
```bash
from django.urls import path
from django_pg.views import payment_verification  # Import from the package

urlpatterns = [
    path("verify/<int:order_id>/<str:payment_method>/", payment_verification, name="payment_verification"),
]
```

#### 🌐 Redirect Behavior
After verifying a transaction, the view will redirect the user based on settings defined in your settings.py.

Option 1: Use named URL patterns
```bash
# settings.py
DJANGO_PG_SUCCESS_REDIRECT = 'yourapp:track_order'
DJANGO_PG_FAILURE_REDIRECT = 'yourapp:create_order'
```
Option 2: Use custom Python functions (advanced)
You can also pass a function that takes the verification result dictionary and returns a HttpResponseRedirect.
```bash
# settings.py
DJANGO_PG_SUCCESS_REDIRECT = 'yourapp.utils.payment_success_redirect'
DJANGO_PG_FAILURE_REDIRECT = 'yourapp.utils.payment_failure_redirect'
```

If you go with option 2, you will need to add the functions in yourapp/utils.py:
```bash
from django.shortcuts import redirect

def payment_success_redirect(result):
    return redirect('yourapp:track_order', order_reference=result["order_reference"])

def payment_failure_redirect(result):
    return redirect('yourapp:create_order')
```
4. **Extend the BaseOrder abstract model**
In your own app, create your order model by extending gateways.models.BaseOrder:
```bash
# yourapp/models.py
from django.db import models
from django_pg.models import BaseOrder
from django.contrib.auth.models import User

class Order(BaseOrder):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    total_price = models.DecimalField(max_digits=10, decimal_places=2)
    # Add your fields here
```

**Note: Users attempting to make a payment via Paystack and Flutterwave must have a valid email address. The Paystack and Flutterwave gateway requires this for transaction initiation. Make sure you enforce email submission when a user register**

### 5. Add JS to Your HTML Template

If you're using multiple payment methods (e.g. Paystack, Flutterwave and Interswitch), make sure your template checks for the selected `payment_method`. If you're only using one payment method, you can pass the preferred payment method in a hidden field when the order is created.

#### βœ… Paystack Integration (HTML Template)
[Check Paystack Documentation](https://paystack.com/docs/payments/accept-payments/)
```bash
{% if payment_method == 'paystack' %}
<script src="https://js.paystack.co/v2/inline.js"></script>
<script type="text/javascript">
    function payWithPaystack() {
        var handler = PaystackPop.setup({
            key: '{{ PAYSTACK_PUBLIC_KEY }}',
            email: '{{ request.user.email }}',
            amount: {{ order.total_price|multiply:100 }},
            currency: "NGN",
            ref: '' + Math.floor((Math.random() * 1000000000) + 1),
            callback: function(response) {
                window.location.href = "{% url 'yourapp:payment_verification' order.id payment_method %}?reference=" + response.reference;
            },
            onClose: function() {
                alert('Payment was not completed.');
            }
        });
        handler.openIframe();
    }

    window.onload = function() {
        payWithPaystack();
    };
</script>
{% endif %}
```

#### βœ… Flutterwave Integration (HTML Template)
[Check Flutterwave Documentation](https://developer.flutterwave.com/docs/inline)
```bash
{% if payment_method == 'flutterwave' %}
<script src="https://checkout.flutterwave.com/v3.js"></script>
<script>
  document.addEventListener("DOMContentLoaded", function () {
    FlutterwaveCheckout({
      public_key: "{{ FLUTTERWAVE_PUBLIC_KEY }}",
      tx_ref: "{{ order.order_reference }}",
      amount: {{order.total_price}},
      currency: "NGN",
      payment_options: "card, ussd, banktransfer",
      redirect_url: "{% url 'yourapp:payment_verification' order.id payment_method %}",
      customer: {
        email: "{{ request.user.email }}",
        name: "{{ request.user.get_full_name|default:request.user.username }}"
      },
      customizations: {
        title: "My Store",
        description: "Payment for order {{ order.order_reference }}"
      }
    });
  });
</script>
{% endif %}
```
#### βœ… Interswitch Integration (HTML Template)
[Check Interswitch Documentation](https://docs.interswitchgroup.com/docs/web-checkout)
```bash
{% if payment_method == 'interswitch' %}
<script src="https://newwebpay.qa.interswitchng.com/inline-checkout.js"></script>
<script>
(function() {
    const redirectUrl = "{% url 'yourapp:payment_verification' order.id payment_method %}?reference={{ order.order_reference }}";
    const paymentAmount = {{ order.total_price|floatformat:0 }} * 100;

    function paymentCallback(response) {
        console.log("Interswitch Payment Response:", response);

        if (response?.resp === '00') {
            // Successful payment
            window.location.href = redirectUrl;
        } else {
            alert("Payment was not successful. Please try again.");
        }
    }

    const paymentRequest = {
        merchant_code: "{{ INTERSWITCH_MERCHANT_CODE }}",
        pay_item_id: "{{ INTERSWITCH_PAY_ITEM_ID }}",
        txn_ref: "{{ order.order_reference }}",
        site_redirect_url: redirectUrl,
        amount: paymentAmount,
        currency: 566,
        cust_email: "{{ request.user.email }}",
        cust_name: "{{ request.user.get_full_name|default:request.user.username }}",
        onComplete: paymentCallback,
        mode: "TEST"
    };

    window.webpayCheckout(paymentRequest);
})();
</script>
{% endif %}
```
## πŸ” Signals (Auto Order Reference)

You don’t need to register anything. The gateways app automatically registers a pre_save signal that generates a unique order_reference.
```bash
# gateways/signals.py
@receiver(pre_save, sender=Order)
def set_order_reference(sender, instance, **kwargs):
    if not instance.order_reference:
        instance.order_reference = generate_unique_order_reference()
```

## 🧠 Gateway Dispatcher (Behind the scenes)

The following function routes the verification based on the selected payment method:
```bash
# gateways/payment.py
def verify_payment(order_id, reference, user, payment_method):
    if payment_method == 'paystack':
        return verify_paystack_payment(order_id, reference, user)
    # elif payment_method == 'flutterwave': ...

```
You don't need to modify this β€” it's extendable internally.

## πŸ›‘ License

This project is licensed under the MIT License – see the [LICENSE](./LICENSE) file for details.

---

## 🀝 Contributing

Pull requests are welcome! If you find a bug or have a feature request, feel free to [open an issue](https://github.com/niyimarc/payment_gateways/issues).

See full [Changelog](https://github.com/niyimarc/payment_gateway/blob/master/CHANGELOG.md).

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-pg",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "django, payment, paystack, flutterwave, gateway",
    "author": null,
    "author_email": "Adeniyi oluwadamilare <oluwadamilareadeniye@yahoo.com>",
    "download_url": "https://files.pythonhosted.org/packages/0e/55/3b262c27686a5fcc95837d07fb02317709ea815e2da71047e0fc2505744b/django_pg-0.4.1.tar.gz",
    "platform": null,
    "description": "# Django Payment Gateways Package\r\n\r\nA pluggable Django package for integrating multiple payment gateways (starting with Paystack and Flutterwave), with an extensible architecture that supports more gateways like Stripe, etc.\r\n\r\n---\r\n\r\n## \u2728 Features\r\n\r\n- \ud83d\udd0c Plug-and-play integration\r\n- \ud83d\udd10 Paystack support (more gateways coming)\r\n- \ud83d\udce6 Dispatcher pattern for gateway switching\r\n- \ud83e\uddf1 Abstract `BaseOrder` model for customization\r\n- \u2705 Built-in Payment Verification View\r\n- \ud83e\udde0 Smart unique order reference generation\r\n- \ud83e\uddea Built-in signal handling for order reference\r\n- \ud83d\udca1 Fully customizable frontend and views\r\n\r\n---\r\n\r\n## Example Project\r\n\r\nA sample Django project demonstrating how to use this package is available here:\r\n\r\n\ud83d\udc49 [django_pg_test_project](https://github.com/niyimarc/payment_gateway_test)\r\n\r\n---\r\n\r\n## \ud83d\udce6 Installation\r\n\r\n```bash\r\npip install django-pg\r\n```\r\n\r\n## \u2699\ufe0f Project Setup\r\n1. **Add the app to INSTALLED_APPS**\r\n\r\n```bash\r\n# settings.py\r\nINSTALLED_APPS = [\r\n    ...\r\n    'django_pg',  # Your payment package\r\n]\r\n```\r\n\r\n2. **Define required settings in your settings.py**\r\n\r\n```bash\r\n# settings.py\r\n\r\n# Models used for order\r\nPAYMENT_ORDER_MODEL = 'yourapp.Order'\r\n\r\n# It's recomended that you put the secret key \r\n# in a .env file and load it in your settings\r\n\r\n# Paystack keys\r\nPAYSTACK_PUBLIC_KEY = 'your-paystack-public-key'\r\nPAYSTACK_SECRET_KEY = 'your-paystack-secret-key'\r\n\r\n# Flutterwave keys\r\nFLUTTERWAVE_PUBLIC_KEY = \"your-flutterwave-public-key\"\r\nFLUTTERWAVE_SECRET_KEY = \"your-flutterwave-secret-key\"\r\n\r\n# Interswitch keys\r\nINTERSWITCH_MERCHANT_CODE = \"your-interswitch-merchant-code\"\r\nINTERSWITCH_PAY_ITEM_ID = \"your-interswitch-pay-item-id\"\r\n\r\n```\r\n\r\n3. **Built-in Payment Verification View**\r\ndjango-pg provides a built-in payment_verification view that handles verifying transactions for all the payment gateways out of the box.\r\n#### \ud83d\udd0c URL Configuration\r\nYou can use the built-in view directly in your urls.py:\r\n```bash\r\nfrom django.urls import path\r\nfrom django_pg.views import payment_verification  # Import from the package\r\n\r\nurlpatterns = [\r\n    path(\"verify/<int:order_id>/<str:payment_method>/\", payment_verification, name=\"payment_verification\"),\r\n]\r\n```\r\n\r\n#### \ud83c\udf10 Redirect Behavior\r\nAfter verifying a transaction, the view will redirect the user based on settings defined in your settings.py.\r\n\r\nOption 1: Use named URL patterns\r\n```bash\r\n# settings.py\r\nDJANGO_PG_SUCCESS_REDIRECT = 'yourapp:track_order'\r\nDJANGO_PG_FAILURE_REDIRECT = 'yourapp:create_order'\r\n```\r\nOption 2: Use custom Python functions (advanced)\r\nYou can also pass a function that takes the verification result dictionary and returns a HttpResponseRedirect.\r\n```bash\r\n# settings.py\r\nDJANGO_PG_SUCCESS_REDIRECT = 'yourapp.utils.payment_success_redirect'\r\nDJANGO_PG_FAILURE_REDIRECT = 'yourapp.utils.payment_failure_redirect'\r\n```\r\n\r\nIf you go with option 2, you will need to add the functions in yourapp/utils.py:\r\n```bash\r\nfrom django.shortcuts import redirect\r\n\r\ndef payment_success_redirect(result):\r\n    return redirect('yourapp:track_order', order_reference=result[\"order_reference\"])\r\n\r\ndef payment_failure_redirect(result):\r\n    return redirect('yourapp:create_order')\r\n```\r\n4. **Extend the BaseOrder abstract model**\r\nIn your own app, create your order model by extending gateways.models.BaseOrder:\r\n```bash\r\n# yourapp/models.py\r\nfrom django.db import models\r\nfrom django_pg.models import BaseOrder\r\nfrom django.contrib.auth.models import User\r\n\r\nclass Order(BaseOrder):\r\n    user = models.ForeignKey(User, on_delete=models.CASCADE)\r\n    total_price = models.DecimalField(max_digits=10, decimal_places=2)\r\n    # Add your fields here\r\n```\r\n\r\n**Note: Users attempting to make a payment via Paystack and Flutterwave must have a valid email address. The Paystack and Flutterwave gateway requires this for transaction initiation. Make sure you enforce email submission when a user register**\r\n\r\n### 5. Add JS to Your HTML Template\r\n\r\nIf you're using multiple payment methods (e.g. Paystack, Flutterwave and Interswitch), make sure your template checks for the selected `payment_method`. If you're only using one payment method, you can pass the preferred payment method in a hidden field when the order is created.\r\n\r\n#### \u2705 Paystack Integration (HTML Template)\r\n[Check Paystack Documentation](https://paystack.com/docs/payments/accept-payments/)\r\n```bash\r\n{% if payment_method == 'paystack' %}\r\n<script src=\"https://js.paystack.co/v2/inline.js\"></script>\r\n<script type=\"text/javascript\">\r\n    function payWithPaystack() {\r\n        var handler = PaystackPop.setup({\r\n            key: '{{ PAYSTACK_PUBLIC_KEY }}',\r\n            email: '{{ request.user.email }}',\r\n            amount: {{ order.total_price|multiply:100 }},\r\n            currency: \"NGN\",\r\n            ref: '' + Math.floor((Math.random() * 1000000000) + 1),\r\n            callback: function(response) {\r\n                window.location.href = \"{% url 'yourapp:payment_verification' order.id payment_method %}?reference=\" + response.reference;\r\n            },\r\n            onClose: function() {\r\n                alert('Payment was not completed.');\r\n            }\r\n        });\r\n        handler.openIframe();\r\n    }\r\n\r\n    window.onload = function() {\r\n        payWithPaystack();\r\n    };\r\n</script>\r\n{% endif %}\r\n```\r\n\r\n#### \u2705 Flutterwave Integration (HTML Template)\r\n[Check Flutterwave Documentation](https://developer.flutterwave.com/docs/inline)\r\n```bash\r\n{% if payment_method == 'flutterwave' %}\r\n<script src=\"https://checkout.flutterwave.com/v3.js\"></script>\r\n<script>\r\n  document.addEventListener(\"DOMContentLoaded\", function () {\r\n    FlutterwaveCheckout({\r\n      public_key: \"{{ FLUTTERWAVE_PUBLIC_KEY }}\",\r\n      tx_ref: \"{{ order.order_reference }}\",\r\n      amount: {{order.total_price}},\r\n      currency: \"NGN\",\r\n      payment_options: \"card, ussd, banktransfer\",\r\n      redirect_url: \"{% url 'yourapp:payment_verification' order.id payment_method %}\",\r\n      customer: {\r\n        email: \"{{ request.user.email }}\",\r\n        name: \"{{ request.user.get_full_name|default:request.user.username }}\"\r\n      },\r\n      customizations: {\r\n        title: \"My Store\",\r\n        description: \"Payment for order {{ order.order_reference }}\"\r\n      }\r\n    });\r\n  });\r\n</script>\r\n{% endif %}\r\n```\r\n#### \u2705 Interswitch Integration (HTML Template)\r\n[Check Interswitch Documentation](https://docs.interswitchgroup.com/docs/web-checkout)\r\n```bash\r\n{% if payment_method == 'interswitch' %}\r\n<script src=\"https://newwebpay.qa.interswitchng.com/inline-checkout.js\"></script>\r\n<script>\r\n(function() {\r\n    const redirectUrl = \"{% url 'yourapp:payment_verification' order.id payment_method %}?reference={{ order.order_reference }}\";\r\n    const paymentAmount = {{ order.total_price|floatformat:0 }} * 100;\r\n\r\n    function paymentCallback(response) {\r\n        console.log(\"Interswitch Payment Response:\", response);\r\n\r\n        if (response?.resp === '00') {\r\n            // Successful payment\r\n            window.location.href = redirectUrl;\r\n        } else {\r\n            alert(\"Payment was not successful. Please try again.\");\r\n        }\r\n    }\r\n\r\n    const paymentRequest = {\r\n        merchant_code: \"{{ INTERSWITCH_MERCHANT_CODE }}\",\r\n        pay_item_id: \"{{ INTERSWITCH_PAY_ITEM_ID }}\",\r\n        txn_ref: \"{{ order.order_reference }}\",\r\n        site_redirect_url: redirectUrl,\r\n        amount: paymentAmount,\r\n        currency: 566,\r\n        cust_email: \"{{ request.user.email }}\",\r\n        cust_name: \"{{ request.user.get_full_name|default:request.user.username }}\",\r\n        onComplete: paymentCallback,\r\n        mode: \"TEST\"\r\n    };\r\n\r\n    window.webpayCheckout(paymentRequest);\r\n})();\r\n</script>\r\n{% endif %}\r\n```\r\n## \ud83d\udd01 Signals (Auto Order Reference)\r\n\r\nYou don\u2019t need to register anything. The gateways app automatically registers a pre_save signal that generates a unique order_reference.\r\n```bash\r\n# gateways/signals.py\r\n@receiver(pre_save, sender=Order)\r\ndef set_order_reference(sender, instance, **kwargs):\r\n    if not instance.order_reference:\r\n        instance.order_reference = generate_unique_order_reference()\r\n```\r\n\r\n## \ud83e\udde0 Gateway Dispatcher (Behind the scenes)\r\n\r\nThe following function routes the verification based on the selected payment method:\r\n```bash\r\n# gateways/payment.py\r\ndef verify_payment(order_id, reference, user, payment_method):\r\n    if payment_method == 'paystack':\r\n        return verify_paystack_payment(order_id, reference, user)\r\n    # elif payment_method == 'flutterwave': ...\r\n\r\n```\r\nYou don't need to modify this \u2014 it's extendable internally.\r\n\r\n## \ud83d\udee1 License\r\n\r\nThis project is licensed under the MIT License \u2013 see the [LICENSE](./LICENSE) file for details.\r\n\r\n---\r\n\r\n## \ud83e\udd1d Contributing\r\n\r\nPull requests are welcome! If you find a bug or have a feature request, feel free to [open an issue](https://github.com/niyimarc/payment_gateways/issues).\r\n\r\nSee full [Changelog](https://github.com/niyimarc/payment_gateway/blob/master/CHANGELOG.md).\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Pluggable Django package for integrating multiple payment gateways like Paystack, Flutterwave, etc.",
    "version": "0.4.1",
    "project_urls": {
        "Homepage": "https://github.com/niyimarc/payment_gateway",
        "Issues": "https://github.com/niyimarc/payment_gateway/issues",
        "Repository": "https://github.com/niyimarc/payment_gateway"
    },
    "split_keywords": [
        "django",
        " payment",
        " paystack",
        " flutterwave",
        " gateway"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3ae46982696144651098a2ab37efea9b4c9dd59dbba41a304457508af991b2f8",
                "md5": "e22dfe8fed8ec7075eb850ad9f6d2677",
                "sha256": "a90716bf6a27c1db0610b91bdbbae555cc1d98a0efcb570bc9336b8fb6bfa1e1"
            },
            "downloads": -1,
            "filename": "django_pg-0.4.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e22dfe8fed8ec7075eb850ad9f6d2677",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 13127,
            "upload_time": "2025-08-19T02:15:38",
            "upload_time_iso_8601": "2025-08-19T02:15:38.337287Z",
            "url": "https://files.pythonhosted.org/packages/3a/e4/6982696144651098a2ab37efea9b4c9dd59dbba41a304457508af991b2f8/django_pg-0.4.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0e553b262c27686a5fcc95837d07fb02317709ea815e2da71047e0fc2505744b",
                "md5": "ddc0e5cddd00f249e3ce57a828a7d103",
                "sha256": "1f2b4a39bb9c8c3594170f95f84342d511480e8690f5b943f1ca795c17cc2406"
            },
            "downloads": -1,
            "filename": "django_pg-0.4.1.tar.gz",
            "has_sig": false,
            "md5_digest": "ddc0e5cddd00f249e3ce57a828a7d103",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 11957,
            "upload_time": "2025-08-19T02:15:41",
            "upload_time_iso_8601": "2025-08-19T02:15:41.711910Z",
            "url": "https://files.pythonhosted.org/packages/0e/55/3b262c27686a5fcc95837d07fb02317709ea815e2da71047e0fc2505744b/django_pg-0.4.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-19 02:15:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "niyimarc",
    "github_project": "payment_gateway",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "django-pg"
}
        
Elapsed time: 0.43917s