Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 10 additions & 25 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,20 @@ on:

jobs:
build-n-publish:
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
name: Build and publish Python distributions to PyPI
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install pypa/build
run: >-
python -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: >-
python -m
build
--sdist
--wheel
--outdir dist/
.
- name: Publish a Python distribution to PyPI
python-version: "3.12"
- name: Install build
run: pip install build --user
- name: Build wheel and source tarball
run: python -m build --sdist --wheel --outdir dist/ .
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
26 changes: 7 additions & 19 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,15 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7]
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Requirements
run: >-
python -m
pip install
-r
requirements.txt
- name: Install Pytest
run: >-
python -m
pip install
pytest
- name: Run Test
run: >-
pytest
-vv

- name: Install dependencies
run: pip install -e ".[dev]"
- name: Run tests
run: pytest tests/ -vv
17 changes: 9 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
venv
**__pycache__**
.vscode
build
dist
*.egg*
.pytest*
test_module
venv/
**/__pycache__/
*.pyc
.vscode/
build/
dist/
*.egg-info/
.pytest_cache/
test_module/
199 changes: 115 additions & 84 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,129 +1,160 @@
# SSLCOMMERZ Payment Gateway Python API
[![Downloads](https://static.pepy.tech/personalized-badge/sslcommerz-python-api?period=total&units=international_system&left_color=blue&right_color=grey&left_text=Downloads)](https://pepy.tech/project/sslcommerz-python-api)

Provides a python module to implement payment gateway in python based web apps.
Python wrapper for the SSLCommerz payment gateway. Requires Python 3.10+.

## Installation

Via PIP

```sh
pip install sslcommerz-python-api
```

or via git
or from git

```sh
pip install git+https://github.com/dreygur/SSLCommerz-Python.git
```

## Projected use
## Usage

```python3
#!usr/bin/env python
### Initiate Payment

```python
from decimal import Decimal
from sslcommerz_python_api import SSLCSession

mypayment = SSLCSession(
sslc_is_sandbox=True,
sslc_store_id='your_sslc_store_id',
sslc_store_pass='your_sslc_store_passcode'
)
from uuid import uuid4

mypayment.set_urls(
success_url='example.com/success',
fail_url='example.com/failed',
cancel_url='example.com/cancel',
ipn_url='example.com/payment_notification'
)
from sslcommerz_python_api import SSLCommerzService
from sslcommerz_python_api.models import CustomerInfo, PaymentRequest, ShippingInfo

mypayment.set_product_integration(
total_amount=Decimal('20.20'),
currency='BDT',
product_category='clothing',
product_name='demo-product',
num_of_item=2,
shipping_method='YES',
product_profile='None'
service = SSLCommerzService.create(
store_id='your_store_id',
store_pass='your_store_pass',
is_sandbox=True,
)

mypayment.set_customer_info(
name='John Doe',
email='johndoe@email.com',
address1='demo address',
address2='demo address 2',
city='Dhaka', postcode='1207',
country='Bangladesh',
phone='01711111111'
request = PaymentRequest(
store_id='your_store_id',
store_pass='your_store_pass',
tran_id=str(uuid4()),
total_amount=Decimal('20.20'),
currency='BDT',
success_url='https://example.com/success',
fail_url='https://example.com/failed',
cancel_url='https://example.com/cancel',
ipn_url='https://example.com/ipn',
product_name='demo-product',
product_category='clothing',
num_of_item=2,
shipping_method='YES',
customer=CustomerInfo(
name='John Doe',
email='johndoe@email.com',
address1='demo address',
address2='demo address 2',
city='Dhaka',
postcode='1207',
country='Bangladesh',
phone='01711111111',
),
shipping=ShippingInfo(
ship_name='demo customer',
address='demo address',
city='Dhaka',
postcode='1209',
country='Bangladesh',
),
value_a='extra-a',
value_b='extra-b',
)

mypayment.set_shipping_info(
shipping_to='demo customer',
address='demo address',
city='Dhaka',
postcode='1209',
country='Bangladesh'
)
response = service.initiate_payment(request)
print(response.gateway_url) # redirect user here
print(response.session_key)
print(response.is_success) # True / False
```

# If you want to post some additional values
mypayment.set_additional_values(
value_a='cusotmer@email.com',
value_b='portalcustomerid',
value_c='1234',
value_d='uuid'
)
### Response

response_data = mypayment.init_payment()
On success, `initiate_payment` returns a `PaymentResponse` dataclass:

# You can Print the response data
print(response_data)
```
| Field | Type | Description |
|---|---|---|
| `status` | `str` | `"SUCCESS"` or `"FAILED"` |
| `session_key` | `str` | SSLCommerz session key |
| `gateway_url` | `str` | URL to redirect the user to |
| `is_success` | `bool` | convenience property |

## Response parameters
On failure, raises `SSLCommerzAPIError`.

### When Successfull with Auth and Payloads provided
### Validate Transaction

- status
- sessionkey
- GatewayPageURL
```python
from sslcommerz_python_api.exceptions import SSLCommerzValidationError

try:
result = service.validate_transaction(val_id='VAL_ID_FROM_IPN')
print(result.status) # "VALIDATED"
print(result.data) # full raw response dict
except SSLCommerzValidationError as e:
print(f"Validation failed: {e}")
```

#### Example
### Verify IPN Signature

```sh
{'status': 'SUCCESS', 'sessionkey': 'F650E87F23DD2A8FFCB4E4E333C13B28', 'GatewayPageURL': 'https://sandbox.sslcommerz.com/EasyCheckOut/testcdef650e87f23dd2a8ffcb4234fasf3b28'}
```python
# ipn_data = POST body received from SSLCommerz webhook
try:
service.verify_ipn(ipn_data)
# signature valid — process the order
except SSLCommerzValidationError:
# signature mismatch — reject
pass
```

or
### Error Handling

```python
>>> response_data['status']
SUCCESS
>>> response_data['sessionkey']
F650E87F23DD2A8FFCB4E4E333C13B28
>>> response_data['GatewayPageURL']
https://sandbox.sslcommerz.com/EasyCheckOut/testcdef650e87f23dd2a8ffcb4234fasf3b28
from sslcommerz_python_api.exceptions import (
SSLCommerzAPIError,
SSLCommerzValidationError,
SSLCommerzError,
)

try:
response = service.initiate_payment(request)
except SSLCommerzAPIError as e:
print(e.reason) # SSLCommerz failure reason
print(e.status_code) # HTTP status code if available
except SSLCommerzError:
# catch-all for any library error
pass
```

### When Failed
### Logging

- status
- failedreason
The library logs via Python's standard `logging` module under the `sslcommerz_python_api` namespace.

#### Example
```python
import logging

```sh
{'status': 'FAILED', 'failedreason': 'Store Credential Error Or Store is De-active'}
# enable for all loggers
logging.basicConfig(level=logging.DEBUG)

# or target just this library
logging.getLogger("sslcommerz_python_api").setLevel(logging.DEBUG)
```

or
| Level | Events |
|---|---|
| `DEBUG` | HTTP request URL + transaction/val ID before each call |
| `DEBUG` | Response status after each call |
| `WARNING` | Payment initiation failed (FAILED status from API) |
| `WARNING` | Transaction not validated |

```python
>>> response_data['status']
FAILED
>>> response_data['failedreason']
'Store Credential Error Or Store is De-active'
```
## Migration from v1

`SSLCSession` still works but emits a `DeprecationWarning`. Switch to `SSLCommerzService` at your convenience — the old builder API is not planned for removal in the near term.

## Acknowledgements

## Acknowledgemetns
It's a fork of [Shahed Mehbub's](https://github.com/shahedex) [sslcommerz-python](https://github.com/shahedex/sslcommerz-payment-gateway-python)
Fork of [Shahed Mehbub's](https://github.com/shahedex) [sslcommerz-python](https://github.com/shahedex/sslcommerz-payment-gateway-python).
23 changes: 0 additions & 23 deletions Tests/test_general.py

This file was deleted.

Loading
Loading