KonaKart Logo Customization FAQ
Search

Where is the source code ?
How do I build the customizable java code ?
How do I create a new payment module ?

Where is the source code ?


Not all of KonaKart source code is available, only the parts designed to be customised.  These include:
Custom directories You will find all the java sources and associated properties files under the "custom" directory in every download kit from KonaKart version 2.2.1.0 and above. (These source files were available in previous releases but structured slightly differently).
  

The "custom" directory is located directly under the  installation directory that was selected for KonaKart.

The "custom" directory has two main source directories underneath:  "appn" and "modules".  

The "appn" directory tree holds the java source for the actions, the forms, the module super-classes and other customisable classes such as  AdminOrderIntegrationMgr.java.

The "modules" directory tree holds all of the java classes required to implement each of the modules.


An ant build file (build.xml) can be found at the root of the custom directory.  


The "bin" directory under custom contains a cut-down ant that is sufficient to build all of the custom code - all you need is to set JAVA_HOME to your JDK.

The "custom/lib" directory contains jars for ant.


Once you have executed an ant build you will see a few more directories under "custom" which are the products of the build process.  For example, you will see classes directories, a new jar directory etc.   To remove the files and directories produced by the build you can execute the "clean" target of the ant build, eg:

$ bin/ant clean



How do I build the customizable java code?


An ant file is provided that should make it easy to build the customizable java classes.   Use "ant -p" to see the ant command targets:


$ ~/konakart/custom$ ./bin/ant -p
Buildfile: build.xml

Main targets:

 build                       Compiles all the custom code and creates all the jars
 clean                       Clears away everything that's created during a build
 clean_wars                  Clears away all the wars
 compile                     Compile the customisable application code
 compile_modules             Compile the customisable module code
 copy_jars                   Copy the konakart custom jars to the lib directories
 make_jars                   Create the konakart custom jars
 make_ordertotal_module_jar  Create the ordertotal module jar
 make_payment_module_jar     Create the payment module jar
 make_portlet_war            Create the konakart portlet war
 make_shipping_module_jar    Create the shipping module jar

 make_wars                   Create the konakart wars
Default target: build


Notice that the default build target compiles all the source files and creates the jars.   It doesn't move the jars or create any wars.

If after building the jars you wish to move these to your webapp lib directories you should use the "copy_jars" target.

The "make_wars" target is just a convenient means of creating wars out of the KonaKart webapps.  It is not required to be run to build and deploy the custom code so it's not closely-related to the topics discussed on this page.

The "make_portlet_war" target is for creating a JSR-168 compliant WAR out of your current KonaKart application.   See the JSR 168 Portlet page for more details.

Here is an example of running the default ant target:


$ ~/konakart/custom$ ./bin/ant

Buildfile: build.xml

clean_wars:
     [echo] Cleanup WARs...

clean:
     [echo] Cleanup...

compile:
     [echo] Compile the customisable application code
    [mkdir] Created dir: /home/pete/konakart/custom/appn/classes
    [javac] Compiling 104 source files to /home/pete/konakart/custom/appn/classes

compile_modules:
     [echo] Compile the customisable module code
    [mkdir] Created dir: /home/pete/konakart/custom/modules/classes
    [javac] Compiling 50 source files to /home/pete/konakart/custom/modules/classes

make_payment_module_jar:
     [echo] Create the module jar
    [mkdir] Created dir: /home/pete/konakart/custom/jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_authorizenet.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_chronopay.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_cod.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_epaybg.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_payjunction.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_paypal.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_usaepay.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_worldpay.jar

make_payment_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_payment_yourpay.jar

make_ordertotal_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_ordertotal_productdiscount.jar

make_ordertotal_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_ordertotal_shipping.jar

make_ordertotal_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_ordertotal_subtotal.jar

make_ordertotal_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_ordertotal_tax.jar

make_ordertotal_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_ordertotal_total.jar

make_ordertotal_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_ordertotal_totaldiscount.jar

make_shipping_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_shipping_digitaldownload.jar

make_shipping_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_shipping_flat.jar

make_shipping_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_shipping_free.jar

make_shipping_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_shipping_item.jar

make_shipping_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_shipping_table.jar

make_shipping_module_jar:
     [echo] Create the module jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_shipping_zones.jar

make_jars:
     [echo] Create the konakart_custom.jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakart_custom.jar
     [echo] Create the konakartadmin_custom.jar
      [jar] Building jar: /home/pete/konakart/custom/jar/konakartadmin_custom.jar

build:

BUILD SUCCESSFUL
Total time: 8 seconds




How do I create a new payment module ?


KonaKart supports additional payment/shipping/order total/discount modules using a simple plug-in model.  

Payment modules are typically designed to interface between KonaKart and a 3rd Party payment gateway supplier - like PayPal, Authorize.Net or WorldPay etc.

You can install as many payment gateways as you like with KonaKart but typically you would just have one configured as there is usually a cost associated with the merchant account that you have to set-up with each payment organisation in order to receive your payments.


Suppose you want to create a brand new payment gateway module to interface between KonaKart and your chosen payment gateway supplier.   For the purposes of this guide, let's call the payment gateway supplier "KonaPay" (a completely fictitious gateway).

Find out about "KonaPay"'s APIs


First of all you should find out as much as you can about which interfaces "KonaPay" supports.   They might supply an XML interface, a HTTP post interface, a SOAP interface or any kind of weird custom API that allows you to communicate with them.   Some payment gateways do not provide any APIs for providing credit card information at all and require that your user is directed to their site to enter such sensitive details.

Decide which type of interface you want for your users


So, you have to consider which type of gateway you want to implement for your users?   This may well affect which gateway supplier you choose.    Do you want to collect the credit card details yourself within KonaKart or do you want to send the users off to a payment gateway site to collect this information?   Some prefer the former, some the latter.

You will see in the code that you need to set the paymentType on the PaymentDetails object, which defines which of these two modes you want:


// For Authorize.Net,YourPay etc.
setPaymentType(PaymentDetails.SERVER_PAYMENT_GATEWAY);  

or

// For PayPal, WorldPay etc.
setPaymentType(PaymentDetails.BROWSER_PAYMENT_GATEWAY);



For the sake of our discussion, KonaPay provides a well-documented HTTP API that allows us to collect credit card information on the KonaKart site and send these off synchronously for payment authorizaton - which we think provides the best user experience at payment time.   It's attractive to us because we can retain the same look and feel of our KonaKart store across the full shopping experience - rather than having to jump off to a payment gateway page provided by the gateway supplier which doesn't look anything like the rest of our site.

OK, we've chosen "KonaPay" because it fits our preferred implementation model and it has a well-documented API, what next?  

Sign up for a test account with "KonaPay"


Typically, the payment gateway supplier will provide a free dummy test account so the next step is to apply for one of these at "KonaPay".   Fortunately, "KonaPay" do provide a test account so we sign up and study the API documentation in a little more detail.

Determine which of the existing payment modules is the closest match


The next important step is to study the existing payment modules to see which one looks to be the closest fit to "KonaPay".   This step is very important and will save you a great deal of time if you pick a close match.

The good news is that many of the gateways work in very similar ways within the two distinct payment module groups:

Copy the files of the closest match as the starting point


We decide that PayJunction is the closest match to "KonaPay" so we make copies of all the PayJunction files and directories - ensuring that we are completely consistent with the naming conventions used by PayJuntion (ie, the same lower/mixed case conventions as PayJunction).  Make copies of the various properties files as well and rename these as appropriate to "KonaPay", "Konapay" or "konapay" in a consistent manner.

There will be payment directories to copy under com.konakart.bl.modules.payment and com.konakartadmin.modules.payment.

We also need to copy modules/src/com/konakart/actions/gateways/PayjunctionAction.java to modules/src/com/konakart/actions/gateways/KonapayAction.java

Which configuration parameters do we need?


Next, we need to decide which configuration options we will allow an administrator to change once the "KonaPay" module is installed.

PayJunction allows these to be configured:   (the following is the code that initialises these in modules/src/com/konakartadmin/modules/payment/payjunction/Payjunction.java:)


    configs[i++] = new KKConfiguration(
    /* title */"Enable PayJunction Module",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_STATUS",
    /* value */"true",
    /* description */"Do you want to accept PayJunction payments? ('true' or 'false')",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"tep_cfg_select_option(array('true', 'false'), ",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"Sort order of display.",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_SORT_ORDER",
    /* value */"0",
    /* description */"Sort order of display. Lowest is displayed first.",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"Payment Zone",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_ZONE",
    /* value */"0",
    /* description */"If a zone is selected, only enable this payment method for
                      that zone.",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"tep_get_zone_class_title",
    /* setFun */"tep_cfg_pull_down_zone_classes(",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"PayJunction Username",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_USERNAME",
    /* value */"pj-ql-01",
    /* description */"The username used to access the PayJunction service",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"PayJunction Password",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_PASSWORD",
    /* value */"pj-ql-01p",
    /* description */"The password used to access the PayJunction service",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"Payment Server URL",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_URL",
    /* value */"https://payjunction.com/quick_link",
    /* description */"URL used by KonaKart to send the transaction details",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"Security Options",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_SECURITY",
    /* value */"AWZ|M|false|true|false",
    /* description */"Security Options for Pay Junction - refer to PayJunction
                      documentation for details",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"",
    /* dateAdd */now);

    configs[i++] = new KKConfiguration(
    /* title */"Debug Mode",
    /* key */"MODULE_PAYMENT_
PAYJUNCTION_DEBUG_MODE",
    /* value */"true",
    /* description */"If set to true, the PayJunction module will be set to debug code",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"tep_cfg_select_option(array('true', 'false'), ",
    /* dateAdd */now);



The above are quite a typical combination of fields.   Let's look at each one in turn:

For "KonaPay" we will change the configuration parameter names to include "KONAPAY" rather than "PAYJUNCTION", so we would have "MODULE_PAYMENT_KONAPAY_STATUS" etc...    We need to replace _PAYJUNCTION_ with _KONAPAY_ throughout all the source and properties files.    For "KonaPay" we will assume, for simplicity that we will define the same set as is defined for PayJunction except the MODULE_PAYMENT_PAYJUNCTION_SECURITY variable which we'll exclude.

Understanding the configuration options


Looking more closely at the KKConfiguration structure that is initialised for each configuration object:

    configs[i++] = new KKConfiguration(
    /* title */"Enable PayJunction Module",
    /* key */"MODULE_PAYMENT_PAYJUNCTION_STATUS",
    /* value */"true",
    /* description */"Do you want to accept PayJunction payments? ('true' or 'false')",
    /* groupId */groupId,
    /* sort Order */i,
    /* useFun */"",
    /* setFun */"tep_cfg_select_option(array('true', 'false'), ",
    /* dateAdd */now);


The comments should help a lot in understanding what these attributes are for.  In more detail:
The only slightly complicated ones are the use and set functions.   The example above shows the setFun to use to display a true/false toggle in the Admin App.  The setFun and useFun can be null for most simple text fields.  These setFun and useFun formats are used throughout the Admin App and perhaps the easiest way to see how they work is to look at these columns in the database for each configuration key that uses them.. eg:  Issue "SELECT configuration_title, configuration_key, use_function, set_function FROM configuration;" against your database to see lots of examples.
** Ask questions in the forum if you're uncertain about these.

Add the KonaPay gateway to the Admin App

In order to see the "KonaPay" payment gateway module in the Admin App we have to add it to the list of payment modules in webapps/konakartadmin/WEB-INF/classes/konakartadmin.properties.   Remember to match the classname - so be careful with your lower case/upper case characters!   Once set, the Admin App will inclde the "KonaPay" module in the set of modules that can be installed or removed from the system:   (Konapay has been added in bold below):


# -----------------------------------------------------------------------------------
# Set the class names of the various modules you would like to make available.
# The administrator can still choose to enable or disable these.
#
# Note that if you remove a module from the definitions below that has already been
# set up in the database the users may still have access to the modules in the
# konakart application.   Hence, it is advisable to remove the modules before they
# are removed from these definitions.

# Make these space or semi-colon-separated class names - they have implied prefixes
# of:
#     com.konakartadmin.modules.payment.{lower case module name}.
#     com.konakartadmin.modules.shipping.{lower case module name}.
#     com.konakartadmin.modules.orderTotal.{lower case module name}.

konakart.modules.payment=Paypal Cod Worldpay Authorizenet Yourpay Payjunction Konapay
konakart.modules.shipping=Flat Item Table Zones Free DigitalDownload
konakart.modules.ordertotal=Shipping SubTotal Tax Total ProductDiscount TotalDiscount



Implement the PaymentInterface

Next we need to implement the PaymentInterface in our Konapay class in the com.konakart.bl.modules.payment.konapay package.    If the PayJunction directories were copied correctly earlier the java file should be at custom/modules/src/com/konakart/bl/modules/payment/konapay

This Konapay.java source extends BasePaymentModule (whose source is provided at custom/appn/src/com/konakart/bl/modules/payment/BasePaymentModule.java) and implements PaymentInterface.

It's advisable to follow the pattern you see in the file you copied.   Therefore,  rename all the constants and variables to names appropriate for "KonaPay" and set up the PaymentDetails object in a similar way in getPaymentDetails().

For much of the PaymentDetails, the values set will be very similar between payment modules (eg. the payment module code, the sort order, title and description etc) but there will always be differences in the "NameValue[]" parameters that are added further down in the getPaymentDetails() method.

NameValue[] parameters

Each payment gateway will need different parameter names so to work out which NameValue pairs you need to add you need to study the API specification.    With PayJunction, you can see that the following are required:  dc_logon, dc_password, dc_transaction_type etc.   With "KonaPay" there will be different names and perhaps different encoding rules;  the API documentation will define the requirements.  Check the examples in the gateway documentation, these often make it clear what the names and values should be.   Once the parameters are understood, add these to the PaymentDetails - they will be used later to build the request to the gateway supplier.

Implement the Action code

Next we need to implement the Action code in our KonapayAction class in the com.konakart.actions.gateways package.    The "KonaPay" java file should be called custom/modules/src/com/konakart/actions/gateways/KonapayAction.java.   (Notice that the (usually synchronous) modules which collect the payment information from the user on the KonaKart site have to have "com.konakart.actions.gateways" implementations, whereas the (asynchronous) modules that divert the user off to a page on the gateway's site have to have "com.konakart.actions.ipn" implementations).

This Konapay.java source extends BasePaymentModule (whose source is provided at custom/appn/src/com/konakart/bl/modules/payment/BasePaymentModule.java) and implements PaymentInterface.

It's advisable to follow the pattern in the file you copied from PayJunction.   Therefore,  rename all the constants and variables to names appropriate for "KonaPay" and set up the PaymentDetails object in a similar way in getPaymentDetails().

The Action files are quite well documented so it should be easy to see where to make modifications for a new module.   Basically you will have to create your message to post to the gateway then process the returned information to determine success or failure.   If there's a failure you can return the user to the credit card screen to try again (and show the error message that you received).  Alternatively, for more serious errors, you can show the exception in a standard form for the KonaKart site.

Save IPN details

In order for your KonaKart administrator to diagnose payment gateway problems in the future, it's a good idea to save details of each transaction with a call to "saveIpnHistory"  (see kkAppEng.getEng().saveIpnHistory()).    Set the various attributes on IpnHistoryIf to values that you derive from the response as you see in the example source.   These records are available in the KonaKart Admin App for inspection and can be useful when diagnosing problems with payment gateways.   The records can also be useful in recording unique transaction codes that are provided by the gateway suppliers for proving that payments have been made, should that need ever arise.

Save the gateway response to a file

Another technique that you can use to diagnose problems is to save gateway responses to a file on disk.  An example of such code is in the YourpayAction source as follows:


    if (yourPayDebugMode)
    {
          // Write the response to an HTML file which is handy for
          // diagnosing problems


          try
          {
              String outputFilename = getLogFileDirectory() + "yourpay_resp_"
                      + order.getId()

                      + ".html";
              File myOutFile = new File(outputFilename);
              if (log.isDebugEnabled())
              {
                  log.debug("Write gateway response to "
                      + myOutFile.getAbsolutePath());

              }
              BufferedWriter bw = new BufferedWriter(new FileWriter(myOutFile));
              bw.write(gatewayResp);
              bw.close();
          } catch (Exception e)
          {
              // dump the exception and continue
              e.printStackTrace();
          }
    }



Note that the yourPayDebugMode boolean could be set by one of your module configuration parameters and the log file location that is returned by the getLogFileDirectory() call is defined in the Admin Application under the Configuration >> Logging section.

Send payment confirmation email

You have a choice whether or not to send payment confirmation mails in the Action class.   (You are also free to change the format of these emails if you wish by modifying the velocity templates).   The call for sending emails is  simply kkAppEng.getEng().sendOrderConfirmationEmail().

Struts mapping

More often that not the Struts mapping code in the Action class will be the same for all the synchronous (or "server-side") payment modules.   Each "mapping string" in the mapping.forward("mapping string")  calls must match the struts-config.xml file as follows:   The entry for "KonaPay" has been added below:


   <!-- =========================================== Server Side Gateways -->
   <action path="/USAePay" type="com.konakart.actions.gateways.UsaepayAction">
       <forward name="Approved" path="/CheckoutFinished.do"/>
       <forward name="TryAgain" path="/CheckoutServerPayment.do"/>
       <forward name="NotLoggedIn" path="/CheckoutDelivery.do"/>                       </action>
   <action path="/AuthorizeNet" type="com.konakart.actions.gateways.AuthorizenetAction">
       <forward name="Approved" path="/CheckoutFinished.do"/>
       <forward name="TryAgain" path="/CheckoutServerPayment.do"/>
       <forward name="NotLoggedIn" path="/CheckoutDelivery.do"/>
  
</action>
   <action path="/PayJunction" type="com.konakart.actions.gateways.PayjunctionAction">
       <forward name="Approved" path="/CheckoutFinished.do"/>
       <forward name="TryAgain" path="/CheckoutServerPayment.do"/>
       <forward name="NotLoggedIn" path="/CheckoutDelivery.do"/>
   </action>
   <action path="/KonaPay" type="com.konakart.actions.gateways.KonapayAction">
       <forward name="Approved" path="/CheckoutFinished.do"/>
       <forward name="TryAgain" path="/CheckoutServerPayment.do"/>
       <forward name="NotLoggedIn" path="/CheckoutDelivery.do"/>
   </action>
   <action path="/YourPay" type="com.konakart.actions.gateways.YourpayAction">
       <forward name="Approved" path="/CheckoutFinished.do"/>
       <forward name="TryAgain" path="/CheckoutServerPayment.do"/>
       <forward name="NotLoggedIn" path="/CheckoutDelivery.do"/>
   </action>



One other change is required in struts-config.xml which defines the forwarding for the server-side payments:   It's critical to maintain naming consistency here (use lower or mixed case as in the other examples - or whatever it takes to match your definitions elsewhere).

 
  <action path="/CheckoutServerPaymentSubmit"
          type="com.konakart.actions.CheckoutServerPaymentSubmitAction"
          name="CreditCardForm" scope="request" validate="true"
          input="/CheckoutServerPayment.do">

       <forward name="usaepay" path="/USAePay.do"/>
       <forward name="authorizenet" path="/AuthorizeNet.do"/>
       <forward name="payjunction" path="/PayJunction.do"/>
       <forward name="konapay" path="/KonaPay.do"/>
       <forward name="yourpay" path="/YourPay.do"/>
   </action>



Build, Deploy and Test

Once the java code is built, the properties files and the struts-config.xml have been updated, all that is required to be done is to execute the ant build, copy the new jars into position, restart tomcat and test!

The gateway suppliers typically provide test credit card numbers for you to use for these tests.


If you have questions on customizing KonaKart please post these on our forum.