=================================== 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``: .. code-block:: python from lfs.plugins import PaymentMethodProcessor class MyPaymentMethodProcessor(PaymentMethodProcessor): pass Add the ``process`` method -------------------------- .. code-block:: python 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 ---------------------------------------- .. code-block:: python 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. Add the ``get_pay_link`` method -------------------------------- In order to provide a link to the customer to re-visit the payment provider and pay his order (if something did go wrong) LFS calls get ``get_pay_link method`` or your class (this is optional). .. code-block:: python def get_pay_link(self): return "http://www.acme.com/payment?id=4711&total=%s" % total The complete plugin =================== Following all pieces are sticked together to the complete plugin: .. code-block:: python 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: #. Add your application to the PYTHONPATH. #. Add the class to the :ref:`LFS_PAYMENT_METHOD_PROCESSORS ` setting. #. If your are using models (which is completely up to you), add the application to settings.INSTALLED_APPS and sync your database. #. :doc:`Add a new payment method ` and select your payment method within the ``module`` field. #. 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. #. 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") See also ========= * :ref:`PaymentMethodProcessor API `