Add PayFlow Pro wrapper to standard library?

Mark McEahern mark at mceahern.com
Mon Feb 2 08:55:40 EST 2004


I just wrote a very simple wrapper for the PayFlow Pro SDK (see below).

A friend of mine did this before, but I didn't have access to his
source, so I took it as a learning opportunity for me to write a C
wrapper.  I did a little searching to see whether anyone had done
anything like this for Python.  I didn't find anything.

I did find that PHP comes with an extension for PayFlow Pro that you can
compile into the language:

  http://www.phpbuilder.com/manual/ref.pfpro.php

This inspired me to imagine something similar being added to Python's
standard library.  The basic idea:  This would mean someone like me
wouldn't have to reinvent the wheel over and over.  Do other folks use
Python for payment processing?  Do they use something other than
Verisign?  Verisign--with all its warts--is particularly nice because it
supports recurring billing, which means I don't have to store the credit
card number, I just setup a recurring billing profile and they do the
recurring billing.  You can't beat that.

I'd be willing to do most of the work, but I'm probably going to need
help.

What I imagine is there would be a pure Python module that provides a
high level interface to process transactions like this:

  import pfpro
  result = pfpro.process(details)

This will then use a C wrapper to call the PayFlow Pro dynamic library.

The Python wrapper would also support using the context functions:

  import pfpro
  context = pfpro.context(details)
  for tx in transactions:
    tx.result = context.process(tx.details)
  
  # context's __del__ could handle destroying itself, etc.

What's the next step?  I don't know since I've never been involved in
adding anything to the standard library.

Further, I can imagine Zope/CMF/Plone wrappers on top of this too.

Thanks,

// m

p.s.  Here's the code; consider it 0.0.0.1.  ;-)

# setup.py

"""
Before you run this, you need to:

1.  Copy the dynamic library from the PayFlow Pro SDK for your
    platform to /usr/local/lib.

2.  Copy the pfpro.h from the PayFlow Pro SDK for your platform
    to /usr/local/include.

TODO:

- For Windows, there's a COM server--use that or use the dynamic
  library?

- Add a pure Python module "on top" of the C wrapper.
"""

from distutils.core import setup, Extension

pfpro = Extension('pfpro',
                  sources = ['pfpromodule.c'],
                  libraries = ['pfpro'],
                  runtime_library_dirs = ['/usr/local/lib'],
                  include_dirs = ['/usr/local/include'])

setup (name = 'pfpro',
       version = '1.0',
       description = 'PayFlowPro',
       ext_modules = [pfpro])

# pfpromodule.c

#include <Python.h>
#include <string.h>
#include "pfpro.h"

/* This is very, very raw. */

static PyObject *ErrorObject;

static PyObject *
pfpro_process(PyObject *self, PyObject *args)
{
  int      ok;
  char     *server;
  int      port;
  int      timeout;
  char     *proxyAddress	    = NULL;
  int      proxyPort		    = 0;
  char     *proxyLogon		= NULL;
  char     *proxyPassword	= NULL;
  int      context;
  char     *request;
  int      requestLength;
  char     *response;
  PyObject *returnValue;

  ok = PyArg_ParseTuple(args, "siis", &server, &port, &timeout,
&request);

  if (pfproInit()) {
    // "raise"
    return Py_BuildValue("i", 1);
  }

  if (pfproCreateContext(&context, server, port, timeout, proxyAddress, 
                         proxyPort, proxyLogon, proxyPassword)) {
    // "raise"
    return Py_BuildValue("i", 2);
  }

  requestLength = strlen(request);
  pfproSubmitTransaction(context, request, requestLength, &response);
  returnValue = Py_BuildValue("s", response);
  pfproCompleteTransaction(response);
  pfproDestroyContext(context);
  pfproCleanup();

  return returnValue;
}

static PyMethodDef pfpro_methods[] = {
  {"process",  pfpro_process, METH_VARARGS,
   "Process a PayFlowPro transaction and return the result."},
  {NULL, NULL, 0, NULL}        /* Sentinel */
};

static char pfpro_module_documentation[] = 
"pfpro - Python wrapper for the PayFlowPro library."
;

void 
initpfpro()
{
  PyObject *m, *d;

  /* Create the module and add the functions */
  m = Py_InitModule4("pfpro", 
                     pfpro_methods,
                     pfpro_module_documentation,
                     (PyObject*)NULL, 
                     PYTHON_API_VERSION);

  /* Add some symbolic constants to the module */
  d = PyModule_GetDict(m);
  ErrorObject = PyString_FromString("pfpro.error");
  PyDict_SetItemString(d, "error", ErrorObject);

  /* XXXX Add constants here */
	
  /* Check for errors */
  if (PyErr_Occurred())
    Py_FatalError("can't initialize module pfpro");
}

# test.py
#!/usr/bin/env python

import pfpro

username = # your username
password = # your password
cardExpiration = '1209'
cardNumber = '5105105105105100'
amount = '1.00'

values = {'VENDOR': username,
          'TRXTYPE': 'S',
          'ExpDate': cardExpiration,
          'PWD': password,
          'USER': username,
          'ACCT': cardNumber,
          'TENDER': 'C',
          'PARTNER': 'verisign',
          'AMT': amount}

server = 'test-payflow.verisign.com'
port = 443
timeout = 10

request = '&'.join(['%s=%s' % (k, v) for k, v in values.iteritems()])
response = pfpro.process(server, port, timeout, request)
print response






More information about the Python-list mailing list