How to add an own payment processor

In this how-to you will learn how to add a own payment processor.

Create an application

First you need to create a default Django application (or use an existing one), where you can put in your plugin. If you do not know how to do this, please refer to the excellent Django tutorial.

Implement the PaymentMethodProcessor class

The main part of the plugin consists of a class which must provide a certain API.

Create the class

Create a class which inherits from lfs.plugins.PaymentMethodProcessor:

from lfs.plugins import PaymentMethodProcessor

class MyPaymentMethodProcessor(PaymentMethodProcessor):
    pass

Add the process method

def process(self):
    total = self.order.price
    return {
        "accepted": True,
        "next_url": "http://www.acme.com/payment?id=4711&total=%s" % total,
    }

This method is called from LFS when the shop customer submits the checkout page (while selected this payment method). Within that method you can do whatever it is necessary to process your payment, e.g.:

  • Call an API via HTTP(S)
  • Redirect to another URL

Return Value

The process method must return a dictionary with following keys (most of them are optional):

accepted (mandatory)
Indicates whether the payment is accepted or not. if this is False the customer keeps on the checkout page and gets the message below. If this is True the customer will be redirected to next_url or to LFS’ thank-you page
message (optional)
This message is displayed on the checkout page, when the order is not accepted.
message_location (optional)
The location, where the message is displayed.
next_url (optional)
The url to which the user is redirect after the payment has been processed. if this is not given the customer is redirected to the default thank-you page.
order_state (optional)
The state in which the order should be set. It’s just PAID. If it’s not given the state keeps in SUBMITTED.

Add the get_create_order_time method

from lfs.plugins import PM_ORDER_IMMEDIATELY

def get_create_order_time(self):
    return PM_ORDER_ACCEPTED

This method is called from LFS to determine when the order is to be created and must return one of following values:

PM_ORDER_IMMEDIATELY
The order is created immediately before the payment is processed.
PM_ORDER_ACCEPTED
The order is created when the payment has been processed and accepted.

The complete plugin

Following all pieces are sticked together to the complete plugin:

from lfs.plugins import PaymentMethodProcessor
from lfs.plugins import PM_ORDER_IMMEDIATELY

class ACMEPaymentMethodProcessor(PaymentMethodProcessor):
    """
    Implements the ACME payment processor.
    """
    def process(self):
        return {
            "accepted": True,
            "next_url": self.get_pay_link(),
        }

    def get_create_order_time(self):
        return PM_ORDER_IMMEDIATELY

    def get_pay_link(self):
        total = self.order.price
        return "http://www.acme.com/payment?id=4711&total=%s" % total

In this example the order is created immediately and the customer is redirected to the ACME page in order to pay his order. After he has paid he might be redirected to the thank-you page of LFS, but this is completely up to ACME. However, if something goes wrong while he is paying he can always go back to ACME to pay his order because he gets the pay link via the order confirmation mail.

Plug in your payment method

Now as the code is ready, you can easily plugin your payment method:

  1. Add your application to the PYTHONPATH.
  2. Add the class to the LFS_PAYMENT_METHOD_PROCESSORS setting.
  3. If your are using models (which is completely up to you), add the application to settings.INSTALLED_APPS and sync your database.
  4. Add a new payment method and select your payment method within the module field.
  5. Select the type of your payment method. Following types are provided:
    • Plain - no further fields are displayed.
    • Bank - fields to enter a bank account are displayed.
    • Credit Card - fields to enter a credit cart are displayed.
  6. Save the payment method.

Further hints

  • Within the PaymentMethodProcessor request, the current order or the current cart are available as instance variables:

    self.request
    self.cart (only when get_create_order_time returns PM_ORDER_ACCEPTED)
    self.order (only when get_create_order_time returns PM_ORDER_IMMEDIATELY)
    
  • When an external payment processor redirects to LFS the current order is still in the session. This means you can redirect to an own view and set the order state to PAID, for instance:

    from django.core.urlresolvers import reverse
    from django.http import HttpResponseRedirect
    from lfs.plugins import PAID
    
    def acme_callback_success_view(request):
        order = request.session.get("order")
        order.state = PAID
        order.save()
    
        return HTTPRedirectResponse(reverse("lfs_thank_you"))
    
  • All fields of the checkout form are available within the process method via the request variable, e.g.:

    request.POST.get("invoice_firstname")