« The Seven Fallacies of jPOS Applications (a response) | Main | Result Codes, Part II »

Saturday, July 14, 2007

When Your Remote Auth Needs Don't Conform to ISO8583

As may you know from previous my posts here, when Alejandro originally envisioned  jPOS, he did so in part to solve the frustrating, error-prone, time-consuming (and often mind-numbing) process of building ISO8583-based payment system interfaces.   From the kernel of that original idea, he's evolved jPOS to become Your Complete Payment System Solution Framework.

Nowadays, things have come full circle - people (including me) often pop up with the need to build specific payment interfaces that aren't ISO8583-based.  For example, we have a customer with a terminal interface (servicing 4,000+ multi-lane locations shooting us close to one million authorization attempts per day) that uses Visa Gen 2 ('VG2').  And, we've just implemented a remote authorization link to Verizon (formally MCI) that is waaaay non-ISO.

What these interfaces - and others like it - have in common is that they're Field Separator Delimited ('FSD')-style implementations.  In other words, instead of being bit-mapped, they're defined by some type of fixed format.  'Fixed' here is a loose term.  The VG2 interface, for example, has some message-to-message variance, but its essence is that by knowing a few key variables, you can know/define the appropriate message structure.  I've blogged in the past about jPOS' FSD facility, which is what I call the unsung hero of the jPOS framework - Here I talk about how to implement a Thales HSM interface in FSD...and here's where you'd use the same facility to implement an extract/settlement subsystem.

Now for a remote authorization interface that can be implemented as FSD, Alejandro has fashioned a 'jPOS extension' called FSDISOMsg - it leverages the full power of the jPOS architecture in a nice way.  For example, a client contacted Alejandro and me the other day and told us about their new interface requirement - it was to implement a remote auth solution to a Trintech-based system.  Trintech's IPSX specification is something that can be implemented using the FSDISOMsg approach.  To explain it to our client, I showed them how we did it recently to certify and implement the Verizon interface.

My note read like this...

You mentioned you’ll have a new (outgoing) interface – it’ll be the first external interface on the new system and will be FSD-based.  We recently faced the same situation.  The Verizon Interface (a Phone Card) is also an FSD interface.  Alejandro created “FSDISOMsg” as a jpos_extension.

Here's the linchpin of the approach:  The QMUX key fields have to be named with their ISO equivalents.  You can see below that we have two fields that equate directly to 41 and 11 (QMUX's default key - the TID and STAN respectively), so we named them as such in the XML structure.  Anything you put in the mux key you need to tie in here.

The field that designates ‘tran-type’ we named as ‘0’ (not mandatory) so that we could note that it’s the MTI-like equivalent

We named the Response Code-like field “39” so as not to break some OLS.Switch (our jPOS-based implementation) internals on response logging and origin-side formatting of replies.

So, we have a Verizon mux deploy file (20_verizon_mux.xml) that looks like this...

<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="verizon-mux">
  <in>verizon-receive</in>
  <out>verizon-send</out>
  <ready>verizon.ready verizon1.ready</ready>
  <key>11, 41</key>
</mux>

...and our outgoing request definition (implemented as verizon-base.xml) is an FSD XML definition that looks like this...

<schema>
  <field id="header"             type="K" length="4" >PREQ</field>
  <field id="msg-version"        type="K" length="2" >40</field>
  <field id="0"                  type="N" length="2" /><!-- tran-type -->
  <field id="length-of-rest"     type="K" length="3" >159</field>
  <field id="POSC-routing-info"  type="K" length="16">*  EYECATCHER  *</field>
  <field id="request-source"     type="N" length="1" />
  <field id="acq-cust-id"        type="K" length="5" >12345</field>
  <field id="division-id"        type="K" length="2" >00</field>
  <field id="store-number"       type="A" length="6" />
  <field id="41"                 type="A" length="16"/><!-- term-id -->
  <field id="11"                 type="N" length="6" /><!-- seqno -->

  <field id="request-date"       type="N" length="8" />
  <field id="request-time"       type="N" length="6" />
  <field id="purchase-price"     type="N" length="6" />
  <field id="request-units"      type="N" length="4" />
  <field id="request-units-frac" type="K" length="2" >00</field>
  <field id="track-data"         type="A" length="80"/>
  <field id="user-context-ind"   type="K" length="1" >N</field>
</schema>

...and the response from Verizon (implemented as verizon-resp-base.xml) looks like this:

<schema>
  <field id="header"             type="A" length="4" />
  <field id="msg-version"        type="N" length="2" />
  <field id="0"                  type="N" length="2" />
  <field id="length-of-rest"     type="N" length="3" />
  <field id="POSC-routing-info"  type="A" length="16"/>
  <field id="store-number"       type="A" length="6" />
  <field id="41"                 type="A" length="16"/><!-- term-id -->
  <field id="11"                 type="N" length="6" /><!-- seqno -->
  <field id="request-date"       type="N" length="8" />
  <field id="request-time"       type="N" length="6" />
  <field id="request-source"     type="N" length="1" />
  <field id="filler-1"           type="A" length="2" />
  <field id="refund-amount"      type="N" length="6" />
  <field id="reply-units"        type="N" length="6" />
  <field id="completion-status"  type="N" length="2" />
  <field id="39"                 type="A" length="3" /><!-- reason-code -->
  <field id="pin-status"         type="A" length="2" />
  <field id="exp-date"           type="N" length="8" />
  <field id="access-num"         type="N" length="10"/>
  <field id="balance"            type="N" length="6" />
  <field id="user-context-ind"   type="A" length="1" />
</schema>

...and our program that ties everything together looks like this...

public class CreateVerizonRequest extends CreateISORequest {
    protected ISOMsg createISOMsg(Context ctx) throws Exception {
        Date now = (Date) ctx.get (TIMESTAMP);
        FSDMsg fsd = new FSDMsg ("file:cfg/verizon-");
        FSDMsg msg = (FSDMsg) ctx.tget (REQUEST);
        assertNotNull (msg, APPLERR_BADDATA,  "CreateVerizonRequest: invalid VG2 request");

        fsd.set ("0", mti);
        fsd.set ("request-source", "0");

        String storeNumber = msg.get ("store-number");
        fsd.set ("store-number", storeNumber);
        StringBuffer sb = new StringBuffer();
        sb.append (storeNumber);
        sb.append (msg.get ("terminal-number"));
        sb.append (msg.get ("register-number"));
        sb.append ("00000");
        fsd.set ("41", sb.toString());

        long l = SpaceUtil.nextLong (sp, "VZNSTAN") % 1000000L;
        if (l == 0) // deal with wrap-around
            l = SpaceUtil.nextLong (sp, "VZNSTAN") % 1000000L;
        fsd.set ("11", ISOUtil.zeropad (Long.toString(l), 6));

        fsd.set ("request-date", ISODate.formatDate (now, "yyyyMMdd"));
        fsd.set ("request-time", ISODate.formatDate (now, "HHmmss"));
        fsd.set ("purchase-price", msg.get ("amount"));

        String track2 = (String) ctx.tget (VZN_TRACK_DATA);
        String units  = (String) ctx.tget (VZN_UNITS);
        String type   = (String) ctx.tget (VZN_TYPE);
        assertNotNull (msg, APPLERR_BADDATA,  "Verizon TRACK DATA not present");
        assertNotNull (msg, APPLERR_BADDATA,  "Verizon UNITS not present");
        assertNotNull (msg, APPLERR_INVCARD, 
            "cannot compute request-units from magnetic-strip-info ("+track2+")");

        fsd.set ("request-units", units);
        fsd.set ("track-data", track2);
        return new FSDISOMsg (fsd);
    }
}

Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

My Photo

Tools

  • Google

    The entire web
    www.andyorrock.com
AddThis Social Bookmark Button

Resources

  • About Me
  • Dave Bergert's blog
    Insightful payment systems thoughts by my OLS colleague, Dave Bergert, CISSP, CISA, CompTIA Security+, and former Visa-certified QSA.
  • Glenbrook Partners' Blog List
    Glenbrook Partners has compiled "a current summary of the latest content from some of our favorite payments and banking blogs based upon their RSS feeds." Alejandro, Dave and I are on the list, as are many other good info sources.
  • jPOS
    Faced with payment systems challenges? Start here to learn more about Alejandro Revilla's jPOS project.
  • Randy San Nicolas' blog
    My OLS colleague Randy San Nicolas writes about his wealth of experience in various Issuer- and Acquirer-side endeavors in his Prepaid Enterprise blog.
  • soliSYSTEMS
    My friend Roque Solis is our go-to guy for RFID, smart cards, chip cards, integrated circuit(s) cards (ICC), HSMs, cryptographic accelerators, DES and public-key cryptography.
  • Specs Online - AMEX
    American Express (Amex) puts all its acquirer specs online for public retrieval.
  • Specs Online - First Data
    First Data Merchant Services (FDMS, aka 'FDR') puts all its acquirer specs online for public retrieval. [NOTE: FDMS' spec repository is accessible only via Internet Explorer; this link will not work with Firefox or other browsers.]
Blog Widget by LinkWithin

Enter your email address:

Delivered by FeedBurner

Blog powered by TypePad

If you're looking here...

  • Your attention to detail is a great asset. Use it wisely.