Billing gateways¶
Adding a new gateway to fleio¶
The following gateways already exist in Fleio: Paypal, Stripe, Romcard and PayU. Those are located in
/var/webapps/fleio/project/fleio/billing/gateways/
(location is available after running fleio bash command)
and you can find some inspiration from there when adding your desired gateway. To configure an existing gateway read
the gateways configuration documentation
A gateway template exists here https://github.com/fleio/gateway-template, however the following instructions show information about each step required to create a new gateway template. Also, please note that each gateway has its own implementation and the following information might not be all that needs to be done so that the new gateway to work properly. For implementing a new gateway we highly recommend to talk to a python developer.
First, we will have to change directory to /home/fleio/compose and create a new directory where we will place our custom gateway files:
cd /home/fleio/compose
mkdir custombackend
cd custombackend
git clone https://github.com/fleio/gateway-template.git
Create the following Dockerfile related files in /home/fleio/compose/custombackend/ with the code from below:
Important
Depending on edition, you might need to add _web
or _openstack
on the 4th line of each Dockerfile
e.g. FROM ${FLEIO_DOCKER_HUB}/fleio_backend${FLEIO_RELEASE_SUFFIX}
will be FROM ${FLEIO_DOCKER_HUB}/fleio_backend_openstack${FLEIO_RELEASE_SUFFIX}
or
FROM ${FLEIO_DOCKER_HUB}/fleio_backend_web${FLEIO_RELEASE_SUFFIX}
Dockerfile-backend
ARG FLEIO_DOCKER_HUB
ARG FLEIO_RELEASE_SUFFIX
FROM ${FLEIO_DOCKER_HUB}/fleio_backend${FLEIO_RELEASE_SUFFIX}
ENV INSTALL_PATH="/var/webapps/fleio"
COPY --chown=fleio:fleio gateway-template "$INSTALL_PATH/project/fleio/billing/gateways/"
Dockerfile-updated
ARG FLEIO_DOCKER_HUB
ARG FLEIO_RELEASE_SUFFIX
FROM ${FLEIO_DOCKER_HUB}/fleio_updated${FLEIO_RELEASE_SUFFIX}
ENV INSTALL_PATH="/var/webapps/fleio"
COPY --chown=fleio:fleio gateway-template "$INSTALL_PATH/project/fleio/billing/gateways/"
Dockerfile-celery
ARG FLEIO_DOCKER_HUB
ARG FLEIO_RELEASE_SUFFIX
FROM ${FLEIO_DOCKER_HUB}/fleio_celery${FLEIO_RELEASE_SUFFIX}
ENV INSTALL_PATH="/var/webapps/fleio"
COPY --chown=fleio:fleio gateway-template "$INSTALL_PATH/project/fleio/billing/gateways/"
Dockerfile-celerybeat
ARG FLEIO_DOCKER_HUB
ARG FLEIO_RELEASE_SUFFIX
FROM ${FLEIO_DOCKER_HUB}/fleio_celerybeat${FLEIO_RELEASE_SUFFIX}
ENV INSTALL_PATH="/var/webapps/fleio"
COPY --chown=fleio:fleio gateway-template "$INSTALL_PATH/project/fleio/billing/gateways/"
Dockerfile-operations
ARG FLEIO_DOCKER_HUB
ARG FLEIO_RELEASE_SUFFIX
FROM ${FLEIO_DOCKER_HUB}/fleio_operations${FLEIO_RELEASE_SUFFIX}
ENV INSTALL_PATH="/var/webapps/fleio"
COPY --chown=fleio:fleio gateway-template "$INSTALL_PATH/project/fleio/billing/gateways/"
This will add the newgateway folder (with its content) in /var/webapps/fleio/project/fleio/billing/gateways/ to all needed images which will be built in the next step.
Add this to your /home/fleio/compose/docker-compose.override.yml file:
# Add here your Docker Compose customizations
# docker-compose.override.yml is not overwritten by Fleio
# (while docker-compose.yml may be OVERWRITTEN on Fleio upgrades)
services:
backend:
build:
context: ./customgateway/
dockerfile: Dockerfile-backend
args:
- FLEIO_DOCKER_HUB
- FLEIO_RELEASE_SUFFIX
image: fleio_backend_custom
pull_policy: never
updated:
build:
context: ./customgateway/
dockerfile: Dockerfile-updated
args:
- FLEIO_DOCKER_HUB
- FLEIO_RELEASE_SUFFIX
image: fleio_updated_custom
pull_policy: never
celery:
build:
context: ./customgateway/
dockerfile: Dockerfile-celery
args:
- FLEIO_DOCKER_HUB
- FLEIO_RELEASE_SUFFIX
image: fleio_celery_custom
pull_policy: never
celerybeat:
build:
context: ./customgateway/
dockerfile: Dockerfile-celerybeat
args:
- FLEIO_DOCKER_HUB
- FLEIO_RELEASE_SUFFIX
image: fleio_celerybeat_custom
pull_policy: never
operations:
build:
context: ./customgateway/
dockerfile: Dockerfile-operations
args:
- FLEIO_DOCKER_HUB
- FLEIO_RELEASE_SUFFIX
image: fleio_operations_custom
pull_policy: never
At this point, you should have the following directory structure:
compose
├── customgateway
│ ├── Dockerfile-backend
│ ├── Dockerfile-celery
│ ├── Dockerfile-celerybeat
│ ├── Dockerfile-operations
│ ├── Dockerfile-updated
│ └── gateway-template
│ ├── README.md
│ └── newgateway
│ ├── __init__.py
│ ├── apps.py
│ ├── conf.py
│ ├── models.py
│ └── newgateway.py
├── docker-compose.override.yml
├── docker-compose.yml
├── env_template
└── secrets
If everything looks ok, you can build your new image and make sure that the affected containers are being reloaded and they’re using thew new custom build images:
cd /home/fleio/compose
docker compose build && docker compose up -d
Run docker ps -a command to confirm that the rebuild containers reloaded (uptime should be a few seconds) and they’re using the fleio custom images:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c52140d9f894 hub.fleio.com/fleio_web-2023-02:1 "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 80/tcp, 0.0.0.0:80->8080/tcp, :::80->8080/tcp fleio-web-1
fa8228540bbe fleio_backend_custom "/var/webapps/fleio/…" 11 seconds ago Up 6 seconds 8000/tcp fleio-backend-1
a227f0badff4 fleio_updated_custom "/var/webapps/fleio/…" 11 seconds ago Up 6 seconds fleio-updated-1
605eb2e6286b fleio_celerybeat_custom "/var/webapps/fleio/…" 11 seconds ago Up 6 seconds fleio-celerybeat-1
a267943154f1 fleio_celery_custom "/var/webapps/fleio/…" 11 seconds ago Up 6 seconds fleio-celery-1
e2d260de66bf fleio_operations_custom "/var/webapps/fleio/…" 11 seconds ago Up 6 seconds fleio-operations-1
706aeca45b84 hub.fleio.com/fleio_incomingmail-2023-02:1 "/var/webapps/fleio/…" 45 minutes ago Up 24 minutes fleio-incomingmail-1
f18bd6760827 hub.fleio.com/fleio_frontend-2023-02:1 "/docker-entrypoint.…" 45 minutes ago Up 24 minutes 80/tcp fleio-frontend-1
dfea54b07fab hub.fleio.com/fleio_fluentd-2023-02:1 "tini -- /bin/entryp…" 45 minutes ago Up 24 minutes 5140/tcp, 127.0.0.1:24224->24224/tcp, 127.0.0.1:24224->24224/udp fleio-fluentd-1
688fd8203263 redis:7.0.7-alpine "docker-entrypoint.s…" 45 minutes ago Up 24 minutes 6379/tcp fleio-redis-1
c8dc28269128 mariadb:10.9.4-focal "docker-entrypoint.s…" 48 minutes ago Up 24 minutes 3306/tcp fleio-db-1
The next step is to add the newgateway to the django installed apps. Run fleio edit settings.py and add the following line at the end of the file:
INSTALLED_APPS += ('fleio.billing.gateways.newgateway', )
NEWGATEWAY_SETTINGS = {
'secret_key': 'whatever!@#$',
'test_mode': True,
'callback_url': 'https://fleio.com',
}
Save and exit and answer with “y” when asked if you want to restart Fleio. At this point, the gateway should be visible when going to the staff/billing/gateways page in the frontend dashboard panel.
Notes on files present in newgateway directory:¶
apps.py
from django.utils.translation import ugettext_lazy as _
from django.apps import AppConfig
class NewgatewayConfig(AppConfig):
name = "fleio.billing.gateways.newgateway"
verbose_name = _("NewGateway")
fleio_module_type = 'payment_gateway'
module_settings = {
'capabilities': {
'can_process_payments': True,
'returns_fee_information': False
}
}
The returns_fee_information attribute from module_settings specifies if this gateway returns fee information. If so, fees will automatically be added to transactions otherwise they may be added from frontend on the /staff/billing/gateways page.
conf.py
from django.conf import settings
class Conf(object):
def __init__(self):
self.newgateway_settings = getattr(settings, 'NEWGATEWAY_SETTINGS', {})
self.test_mode = self.newgateway_settings.get('test_mode')
self.secret_key = self.newgateway_settings.get('secret_key')
self.callback_url = self.newgateway_settings.get('callback_url')
conf = Conf()
As you can see, the first line in the __init__(self) method gets the gateway settings dictionary from the settings.py file. You defined a dictionary in settings.py earlier, containing all the information and variables required by your gateway.
The lines just retrieve each value from the dictionary and assigns them to variables defined on the Conf class.
The dictionary defined in settings.py may look like this given the above example:
NEWGATEWAY_SETTINGS = {
'secret_key': 'whatever!@#$',
'test_mode': True,
'callback_url': 'https://fleio.com',
}
newgateway.py
from django.conf import settings
from django.http import HttpResponseRedirect
from .conf import conf
from fleio.billing.gateways.decorators import gateway_action, staff_gateway_action
from fleio.billing.gateways import exceptions as gateway_exceptions
from fleio.core.utils import fleio_join_url
def process_test_payment(test_mode):
pass
@gateway_action(methods=['GET'])
def pay_invoice(request):
invoice_id = request.query_params.get('invoice')
try:
process_test_payment(test_mode=conf.test_mode)
except Exception as create_payment_exception:
# handle possible exception
raise gateway_exceptions.InvoicePaymentException(
message=str(create_payment_exception),
invoice_id=invoice_id
)
# redirect to invoice
relative_url = 'billing/invoices/{}'.format(invoice_id)
Note on 4th line (from fleio.billing.gateways.decorators import gateway_action, staff_gateway_action):
These decorators are used for functions that can be done by end-users or staff users. There is also the callback(request) function. This will be used in case you want to implement callbacks from the gateway (see the example from stripe.py file).
An example of pay_invoice function can be this:
from django.conf import settings
from django.http import HttpResponseRedirect
from .conf import conf
from fleio.billing.gateways.decorators import gateway_action, staff_gateway_action
from fleio.billing.gateways import exceptions as gateway_exceptions
from fleio.core.utils import fleio_join_url
def process_test_payment(test_mode):
pass
@gateway_action(methods=['GET'])
def pay_invoice(request):
invoice_id = request.query_params.get('invoice')
try:
process_test_payment(test_mode=conf.test_mode)
except Exception as create_payment_exception:
# handle possible exception
raise gateway_exceptions.InvoicePaymentException(
message=str(create_payment_exception),
invoice_id=invoice_id
)
# redirect to invoice (or maybe render a gateway template)
relative_url = 'billing/invoices/{}'.format(invoice_id)
return HttpResponseRedirect(fleio_join_url(settings.FRONTEND_URL, relative_url))
You will now see that when paying an invoice this code gets executed.
Other decorated methods you can use:
Using the gateway_action decorator: pay_invoice, confirm_payment, cancel_payment,
Using the staff_gateway_action decorator: refund, capture
For rendering custom html pages you may find inspiration in the existing Stripe or Romcard gateways.