Custom Payment Modules

While Satchmo currently has support for several different payment modules, you may have unique needs or the desire to create your own payment processor module. This document will discuss how to create your own payment modules. If you do decide to create your own module, please let us know so we can include it back into the satchmo core and make the framework that much more robust.

Overview

Satchmo’s payment processor modules are meant to be as modular as possible. For many types of payment processors, you should be able to use one of the existing modules as a basis for creating your own.

All of the modules are stored in the /payment/modules directory. If you take a quick look at any one of the subdirectories, you will see a number of files:

  • __init__.py
  • config.py
  • processor.py
  • urls.py
  • views.py

The __init__.py is required so that satchmo can import the files. There is no need to put any code in this file. Just be sure it exists!

The rest of the files are described below.

Building your processor

The processor.py file is where the majority of the heavy lifting is done. The processor does 4 things:

  • Sets up its configuration for the service (__init__)
  • Takes order data and formats it in the appropriate manner (prepareData)
  • Sends the data to the processing server/url (authorize_payment, capture_payment, capture_authorized_payment) and returns the results.

Of them, only capture_payment is required. If the processor can both authorize and process, then you need to add a function can_authorize, which returns True, and implement the other two methods. See the dummy module for an example.

Optionally, the processor can include include test code so that it is easy to verify from the command line.

Here is a stub you can use to create your own processor:

from payment.modules.base import BasePaymentProcessor, ProcessorResult

class PaymentProcessor(BasePaymentProcessor):
    def __init__(self, settings):
        # Set up your configuration for items like
        # Test server, url, various flags and settings
        super(PaymentProcessor, self).__init__('example', settings)

    def capture_payment(self):
        # Send the data via the appropriate manner and return a ProcessorResult
        # object.

Refer to the dummy, authorize.net, cybersource or trustcommerce modules for various examples to help you through the process.

Configuration

Each processor will have unique variables that need to be set. The config.py file is where you can leverage the Satchmo settings capability to add your unique variables. Please refer to the Basic Configuration in order to understand how the system works. For more examples, the existing working modules are great examples of what to setup. The basic format is:

Create the new configuration group:

PAYMENT_GROUP = ConfigurationGroup('PAYMENT_MYNEWPROCESSOR',
    _('My New Processor Payment Settings'),
    ordering=102)

Note

The key of the ConfigurationGroup must be the module name, upper-cased.

For example, if your custom payment module was located in mypaymentmodules.mynewprocessor, the ConfigurationGroup should be given the key PAYMENT_MYNEWPROCESSOR. The reason for this is that the active_gateways() function in payment/__init__.py attempts to automatically determine these keys by appending the upper-cased module name to PAYMENT_.

Now register the settings you need:

config_register_list(
    BooleanValue(PAYMENT_GROUP,
        'LIVE',
        description=_("Accept real payments"),
        help_text=_("False if you want to be in test mode"),
        default=False),

    StringValue(PAYMENT_GROUP,
        'LABEL',
        description=_('English name for this group on the checkout screens'),
        default = 'Credit Cards',
        help_text = _('This will be passed to the translation utility')),

    StringValue(PAYMENT_GROUP,
        'URL_BASE',
        description=_('The url base used for constructing urlpatterns which will use this module'),
        default = r'^credit/'),

    MultipleStringValue(PAYMENT_GROUP,
        'CREDITCHOICES',
        description=_('Available credit cards'),
        choices = (
            (('Amex', 'American Express')),
            (('Visa','Visa')),
            (('Mastercard','Mastercard')),
            (('Discover','Discover'))),
        default = ('Visa', 'Mastercard', 'Discover')),

    StringValue(PAYMENT_GROUP,
        'PASSWORD',
        description=_('Your Processor password'),
        default=""),

    BooleanValue(PAYMENT_GROUP,
        'EXTRA_LOGGING',
        description=_("Verbose logs"),
        help_text=_("Add extensive logs during post."),
        default=False)
)

All of these settings can be accessed in your __init__ method (shown above). For example, the LIVE value above can be accessed by using settings.LIVE.value

Views

Most payment processing have similar steps:

  • Collect demographic information
  • Collect payment information
  • Confirm info is correct
  • Return a status

The views.py file contains the information that maps your processor views to the existing views or your own custom view.

For most people, the views contained in payment.views will be sufficient. The example below maps these views to views already available in Satchmo:

from livesettings import config_get_group
from payment.views import confirm, payship

def pay_ship_info(request):
    return payship.credit_pay_ship_info(request, config_get_group('PAYMENT_MYNEWPROCESSOR'))

def confirm_info(request):
    return confirm.credit_confirm_info(request, config_get_group('PAYMENT_MYNEWPROCESSOR'))

However, there is nothing stopping you from creating your own view:

def confirm_info(request):
    # Do a lot of custom stuff here
    return render_to_response(template, context)

All of the current satchmo payment views are in /payment/views. Please review these before trying to build one of your own!

Url configuration

Now that you have built your processor, configured your settings and built your views, you need to tell Satchmo how to access these views. This is where the urls.py file is useful.

For most processors, a simple file would look like this:

from django.conf.urls.defaults import *
from livesettings import config_value, config_get_group


config = config_get_group('PAYMENT_MYNEWPROCESSOR')

urlpatterns = patterns('satchmo',
     (r'^$', 'mypaymentmodules.myprocessor.views.pay_ship_info',
                    {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-step2'),
     (r'^confirm/$', 'payment.modules.trustcommerce.views.confirm_info',
                    {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-step3'),
     (r'^success/$', 'payment.views.checkout.success',
                    {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-success'),
)

The nice thing about this file is that it allows you to easily plug in the views you need and rename the urls to whatever form you need. Just make sure to maintain the naming convention for the urls as shown above.

Enabling the new module

In order to enable your new payment processor, you must add it to your INSTALLED_APPS setting in your settings.py. For example:

INSTALLED_APPS = (
        ...
        'payment',
        'mypaymentmodules.myprocessor',
        ...

Conclusion

Hopefully this document will help you get started in creating your own payment modules. Before trying to tackle one on your own, take some time to look at the existing models and get a feel for how things have been done. Once you are comfortable, we suggest copying one of the modules and using it as a starting point for your subsequent efforts. If you get stuck, please feel free to ask the mailing list for help.