<p align = 'center'>
    <img src = 'https://cinetpay.com/brand/logo-cinetpay.webp' height = 60 align='center' ></img>
</p>
<p align = 'center'>


# New CinetPay Python Library 😎

Python SDK for [CinetPay](https://github.com/AllDotPy/CinetPay) Payment API.

## Currently Supported Services
- Payment API


## Next
We will add progressively support for following CinetPay Services:
- Transfert API
- SMS API
- Airtime API


## Prerequisites

You need to have at least 3.9 version of python to be able to continue. To do this:


Next you can go ahead with `CinetPay`.

## Install

```sh
pip install CinetPay
```

## API

This Python library's API is designed around the [CinetPay REST API](https://cinetpay.com/)

### Settings
There are two ways to setup CinetPay Client:

1. Using a Config object
```python
from cinetpay import (
    Client, Config, Credential
    Channels, Currencies, Languages,
)

# Setting up a client configuration
config = Config(
    currencies = Currencies.XOF,
    languages = Languages.FR,
    channels = Channels.ALL,
    lock_phone_number = True,
    raise_on_error = True,
    credentials = Credential(
        apikey = 'XXXXXXXXXXXXXXXXXX',
        site_id = 'XXXXXX'
    )
)

# Initializing the client
client = Client(
    configs = config
)
```

2. Using a dictionary object

```python

from cinetpay import (
    Client, Config,
    Channels, Currencies, Languages,
)

# Setting up a client configuration
config = {
    'currencies': Currencies.XOF,
    'languages': Languages.FR,
    'channels': Channels.ALL,
    'lock_phone_number': True,
    'raise_on_error': False,            # If True, client will raise on request errors
    'credentials':{
        'apikey':'XXXXXXXXXXXXXXXXXX',
        'site_id':'XXXXXX',
    }
}

# Initializing the client
client = Client(
    configs = config
)
```


## Transactions 

### Create Order
```python
from cinetpay import (
    Order, Customer, Currencies,
)


# CREATING A TRANSACTION
order = Order(
    id = 'ORDER1234',
    amount = 1000,
    currency = Currencies.XOF,
    description = 'Description of the transaction',
    notify_url = 'https://www.exemple.com/notify',
    return_url = 'https://www.exemple.com/return',
    customer = Customer(
        customer_id = 'mycustomer123',
        customer_email = 'mycustomer@mydomain.com',
        customer_phone_number = '+22890000000',
        customer_name = 'John',
        customer_surname = 'Doe',
    )
)

# GET ORDER JSON REPRESENTATION
print(order.to_representation())

```

```json
{
    "transaction_id":"ORDER1234",
    "amount":1000,
    "notify_url":"https://www.exemple.com/notify",
    "return_url":"https://www.exemple.com/return",
    "description":"Description of the transaction",
    "customer_id":"mycustomer123",
    "customer_name":"John",
    "customer_surname":"Doe",
    "customer_phone_number":"+22890000000",
    "apikey":"XXXXXXXXXXXXXXXXXXXXX",
    "site_id":"XXXXXX",
    "channels":"ALL",
    "lang":"fr",
    "currency":"XOF",
    "lock_phone_number":false
}
```

### Create Transaction

```python
from cinetpay import (
    Client, Config, Order, Customer,
    Channels, Currencies, Languages,
    Credential
)

# Setting up a client configuration
config = Config(
    currencies = Currencies.XOF,
    languages = Languages.FR,
    channels = Channels.ALL,
    lock_phone_number = True,
    raise_on_error = True,
    credentials = Credential(
        apikey = 'XXXXXXXXXXXXXXXXXX',
        site_id = 'XXXXXX'
    )
)

# Initializing the client
client = Client(
    configs = config
)

# CREATING A TRANSACTION
order = Order(
    id = 'ORDER1234',
    amount = 1000,
    currency = Currencies.XOF,
    description = 'Description of the transaction',
    notify_url = 'https://www.exemple.com/notify',
    return_url = 'https://www.exemple.com/return',
    customer = Customer(
        customer_id = 'mycustomer123',
        customer_email = 'mycustomer@mydomain.com',
        customer_phone_number = '+22890000000',
        customer_name = 'John',
        customer_surname = 'Doe',
    )
)

# INITIALIZE PAYMENT
res = client.initialize_transaction(order)
print(res)
```


### Retrieve Transaction
To get a specific transaction you can use the `get_transaction` function with the transaction_id or token.
```python
response = client.get_transaction(transaction_id)
```

### Get a Specific Transaction payment url
You can also get a payment URL for a specific Transaction using `get_bill_url` function.
```python
response = client.get_bill_url(transaction_id)
```

## Responses
- ### Response class
The default Request response class, is returned when `detail` is set to `True` in the request.
```python
response = client.create_transaction(my_transaction)

print(response)         # <Class Response status: 201, error: False>

# Use json attribute to access response data.
print(response.json)   # {"id":transaction_id,...}
```
- ### PagginatedResponse Class
PagginatedResponse is used to manage Pagginated response data. It provides properties such as :
- `has_next` : bool , `True` if the PagginatedResponse has a next page else `False`.
- `has_prev` : bool, `True` if the PagginatedResponse has a next page else `False`
- `next_page` : PagginatedResponse, the next page if `has_next` is `True`
- `previous_page` : PagginatedResponse, the next page if `has_prev` is `True`
- `result` : sequence[ Mapping[ str,any ] ], the page data.

## Errors

Errors are raised if requests return an error status.

- ### ErrorResponse class

This Error is returned if raise_on_error is set to True in Client configs.

```python
from cinetpay import (
    Client, Config, Credential,
    Channels, Currencies, Languages,
)

# Setting up a client configuration
config = Config(
    currencies = Currencies.XOF,
    languages = Languages.FR,
    channels = Channels.ALL,
    lock_phone_number = True,
    raise_on_error = True,
    credentials = Credential(
        apikey = 'WRONG-API-KEY',
        site_id = 'SIDE-ID'
    )
)

# Initializing the client
client = Client(
    configs = config
)

response = client.get_transaction('TRANSACTION-ID')

# With raise_on_error set to False
print(type(response))           # <class 'cinetpay._types.ErrorResponse'>

print(response.get_message())   # Client - Client error '400 Bad Request' for url 'https://api-checkout.cinetpay.com/v2/payment'.

# Access ErorResponse infos
print(response.json)
# {'code': '624', 'message': 'UNKNOWN_ERROR', 'description': 'An error occurred while processing the request', 'api_response_id': '1716800180.4474'}

print(response.description)
# An error occurred while processing the request.

print(response.cause)
# 1- l'apikey saisi est incorrect 
# 2- La valeur de lock_phone_number est à true mais la valeur du customer_phone_number est incorrect.

print(response.hint)
# 1- Récupérer l'apikey correcte dans votre back-office(menu integration) 
# 2- La variable doit être false.
# For more information check: https://docs.cinetpay.com/api/1.0-fr/checkout/initialisation#problemes-frequents
```

- ### ResponseError class
This Error is raised if raise_on_error is set to True in Client configs.

```python
from cinetpay import (
    Client, Config, Credential,
    Channels, Currencies, Languages,
)

# Setting up a client configuration
config = Config(
    currencies = Currencies.XOF,
    languages = Languages.FR,
    channels = Channels.ALL,
    lock_phone_number = True,
    raise_on_error = True,
    credentials = Credential(
        apikey = 'WRONG-API-KEY',
        site_id = 'SIDE-ID'
    )
)

# Initializing the client
client = Client(
    configs = config
)

response = client.get_transaction('TRANSACTION-ID')
# Will raise a ResponseError with response message.
```
<br>
<p align = 'center'>Made with ❤️ By <a href='https://github.com/Einswilli'>#Einswilli</a></p>
<!-- <p height='60' align = 'center'>© 2024 DotPy, Inc. All rights reserved.</p> -->
