Add PayFlow Pro wrapper to standard library?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mark McEahern

    Add PayFlow Pro wrapper to standard library?

    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:



    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(d etails)

    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(d etails)
    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('pfpr o',
    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(P yObject *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_ParseTupl e(args, "siis", &server, &port, &timeout,
    &request);

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

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

    requestLength = strlen(request) ;
    pfproSubmitTran saction(context , request, requestLength, &response);
    returnValue = Py_BuildValue(" s", response);
    pfproCompleteTr ansaction(respo nse);
    pfproDestroyCon text(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_do cumentation[] =
    "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_do cumentation,
    (PyObject*)NULL ,
    PYTHON_API_VERS ION);

    /* Add some symbolic constants to the module */
    d = PyModule_GetDic t(m);
    ErrorObject = PyString_FromSt ring("pfpro.err or");
    PyDict_SetItemS tring(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 = '51051051051051 00'
    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.verisig n.com'
    port = 443
    timeout = 10

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



  • Duncan Booth

    #2
    Re: Add PayFlow Pro wrapper to standard library?

    Mark McEahern <mark@mceahern. com> wrote in
    news:mailman.11 27.1075730146.1 2720.python-list@python.org :
    [color=blue]
    > 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(d etails)
    >
    > 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(d etails)
    > 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.[/color]

    First off, forget about adding it to the standard library until a long way
    down the line, if at all. This sounds like a useful but specialised module,
    so it doesn't need to be shipped as standard.

    Next, I suggest you have a look at Greg Ewing's Pyrex, which is a language
    specifically for writing Python Extension modules. This should make your
    life much easier than handling the C api directly. (There are plenty of
    other options, but I prefer Pyrex).

    Pyrex should make it easy for you to define an appropriate context type
    directly in your extension module. This is probably a better solution than
    trying to put a Python wrapper around a set of procedures as it means you
    can control access to the C functions much more tightly.

    Comment

    Working...