View source | Discuss this page | Page history | Printable version   

Retail:Developers Guide/External Payment Providers

Contents

Introduction

Any POS system needs to process credit/debit card payments or any other electronic payment method. These payments are usually processed by third party companies that offer payment processing services. When implementing Openbravo Web POS it is needed the freedom to select the company that offers the best payment services based on customer requirements, prices, country etc. Openbravo Web POS implements electronic payments in a modular way allowing customers to easily select the payment service or services that fits better with its own requirements an also change to other payment services at any moment just installing other module that implements the new connector to the payment provider selected.

This documents describes how to create a new module that implements a new connector to an external payment provider intended to be used with Openbravo Web POS. You need to know the basic concepts of developing and customizing Openbravo ERP and also Openbravo Web POS. You can find a very complete guide on how to develop with Openbravo in these documents: Openbravo ERP Developers Guide and Openbravo Web POS Developers Guide. You need also to install the Openbravo for retail pack that contains the modules the payment connectors depends on.

Module definition for the payment services connector

First create a new module following the Modularity Concepts. This document explains in detail how to create a new Openbravo module. For a payment services connector you need to create an empty module with a dependency to the Web POS module.

Sampleconnectormodule.png

Module Source code

Component provider implementation

Payment services connector are written in javascript. To add this javascript code to the Web POS application you need to create a component provider in java that indicates to Openbravo that the Web POS application needs the javascript code you are writing for the connector. The key line in the component provider is the method that adds the javascript files needed to the Web POS application:

 
@ApplicationScoped
@ComponentProvider.Qualifier(OBPOSPCSComponentProvider.QUALIFIER)
public class OBPOSPCSComponentProvider extends BaseComponentProvider {
 
  public static final String QUALIFIER = "OBPOSPCS_Main";
  public static final String MODULE_JAVA_PACKAGE = "org.openbravo.paymentgateway.paymentconnectorsample";
 
  @Override
  public Component getComponent(String componentId, Map<String, Object> parameters) {
    throw new IllegalArgumentException("Component id " + componentId + " not supported.");
  }
 
  @Override
  public List<ComponentResource> getGlobalComponentResources() {
 
    final List<ComponentResource> globalResources = new ArrayList<ComponentResource>();
    final String prefix = "web/" + MODULE_JAVA_PACKAGE + "/js/";
 
    globalResources.add(createComponentResource(ComponentResourceType.Static, prefix
        + "sampleconnector.js", POSUtils.APP_NAME));
 
    return globalResources;
  }
}

Enyo component implementation

A enyo popup will be shown when the payment which is defined is used. This is a sample of a basic Enyo popup component that implements a payment connector.

initcomponents method will be executed just in the moment when the dialog is opened and all the data of the payment will be part of 'this' (below you can see the object information).

The fields added to the popup are needed to process the payment are:

Take special attention to the property name of the component. This name must match with the value of the payment provider. More details below

 
/*global enyo, $ */
 
enyo.kind({
  name: 'SPCO_.UI.SampleConnector',
  components: [{
    components: [{
      classes: 'row-fluid',
      components: [{
        classes: 'span6',
        content: 'Payment type'
      }, {
        name: 'paymenttype',
        classes: 'span6',
        style: 'font-weight: bold;'
      }]
    }, {
      classes: 'row-fluid',
      components: [{
        classes: 'span6',
        content: 'Configuration value'
      }, {
        name: 'configvalue',
        classes: 'span6',
        style: 'font-weight: bold;'
      }]
    }, {      
      classes: 'row-fluid',
      components: [{
        classes: 'span6',
        content: OB.I18N.getLabel('OBPOS_LblModalAmount')
      }, {
        name: 'paymentamount',
        classes: 'span6',
        style: 'font-weight: bold;'
      }]
    }]
  }, {
    kind: 'OB.UI.Button',
    classes: 'btnlink',
    style: 'float: right;',
    content: 'OK',
    ontap: 'confirmPayment'
  }],
  voidTransaction: function (callback, receipt, removedPayment) {
    // This function will be executed when the payment is removed using the payments UI
    // In this point we should communicate with servers to remove the payment
    // The callback function has the following signature:
    // callback(true, 'Error message'); // Cannot remove the payment, The error message in the parameter will be displayed to the user
    // callback(false); // The payment has been voided successfully and the payment will be removed.
  },
  confirmPayment: function () {
      //In this point we should retrieve the needed info to pay (credit card
      //and then connect with the payment provider.
      var me = this;
      $.ajax({
        url: urlOfProxy, //In general hwmanager should be the proxy
        data: {
           url: url,
           contenttype: 'text/xml;charset=utf-8',
           content: OBPOSPCS.transformToXML(dataToSend)
        },
        dataType: 'json',
        type: 'POST',
        success: function (data){
        //Add the payment when the confirmation is received.
        //The information to save will depend on the payment provider
          var paymentresult = {
            TransactionID: data.Transaction.TransactionID,
            ApprovedAmount: data.Transaction.ApprovedAmount,
            CardNumberMasked: data.carddata.Card.MskPAN,
            CardLogo: data.Card.CardLogo,
            // Void Confirmation indicates whether or not to show a confirmation dialog when the user taps on the
            // button that removes this payment before executing the voidTransaction function.
            // By default is true
            voidConfirmation: false,          
            // Void transaction will be executed when the payment line is removed.
            // VERY IMPORTANT TO REMOVE PAYMENTS
            voidTransaction: me.voidTransaction
          };
          
        var newPayment = new OB.Model.PaymentLine({
          'kind': this.key,
          'name': this.name,
          'amount': parseFloat(paymentresult.ApprovedAmount),
          'paymentData': paymentresult
        });
 
        this.receipt.addPayment(newPayment);
        //close the popup
        this.doHideThisPopup();
      },
      error: function (error){
        //Inform about error
      }
    });
  },
  initComponents: function() {
    this.inherited(arguments);
    this.$.paymenttype.setContent(this.paymentType);
    this.$.paymentamount.setContent(this.paymentAmount);
    this.$.configvalue.setContent(this.paymentMethod.spcoConfigfield);
  }
});

The name field is the name of the component that will be used to reference this Enyo component when configuring payment providers. It must start with the DB prefix followed by _ you define when creating the module. The components field is the definition of the user interface of this component. Here the most important part is the function which manage paymentConfirmed action. This function adds a new payment to the receipt after send it to the payment provider and get the confirmation.

 
        var newPayment = new OB.Model.PaymentLine({
          'kind': this.key,
          'name': this.name,
          'amount': parseFloat(paymentresult.ApprovedAmount),
          'paymentData': paymentresult
        });

and finally closes the payment popup:

 
  this.doHideThisPopup();

Here you have a sample of a payment method object:

$ref: "OBPOS_App_Payment_Type/8C9A0C69D21548B89095C4F5A337BCCB"
_entityName: "OBPOS_App_Payment_Type"
_identifier: "Vouchers"
active: true
allowdeposits: true
allowdontmove: false
allowdrops: true
allowmoveeverything: false
allowvariableamount: false
amount: null
automatemovementtoother: false
cashDifferences: "DE339E8EE03D431B8456AEF76C23D09A"
cashDifferences$_identifier: "Company Capital"
client: "23C59575B9CF467C9620760EB255B389"
client$_identifier: "F&B International Group"
createdBy: "100"
createdBy$_identifier: "Openbravo"
creationDate: "2012-07-17T10:13:09+02:00"
currency: "102"
currency$_identifier: "EUR"
documentType: "F9F6EF7BEF4E485184AEB80C923FDE45"
documentType$_identifier: "MM Shipment"
gLItemForDeposits: "B8C26796E2894C428D4EE13CBF8324B9"
gLItemForDeposits$_identifier: "Funds transfer"
gLItemForDrops: "B8C26796E2894C428D4EE13CBF8324B9"
gLItemForDrops$_identifier: "Funds transfer"
glitemDropdep: null
glitemWriteoff: "F37E42A338854490A764A714024300B6"
glitemWriteoff$_identifier: "Salaries"
id: "8C9A0C69D21548B89095C4F5A337BCCB"
keepfixedamount: false
name: "Vouchers"
obposTerminaltype: "6988853FA4B342EDAC318BA46B1A03C2"
obposTerminaltype$_identifier: "Standard Terminal"
organization: "2E60544D37534C0B89E765FE29BC0B43"
organization$_identifier: "F&B US, Inc."
paymentMethod: "40A8D390260845A59646391073713DDE"
paymentMethod$_identifier: "Check"
paymentProvider: "SPCO_.UI.SampleConnector"
recordTime: 1346412701408
searchKey: "Vouchers"
updated: "2012-08-28T14:45:26+02:00"
updatedBy: "100"
updatedBy$_identifier: "Openbravo"

Returns

In openbravo Web POS, returns are managed as individual payments, it means that when a return is done we are not reversing a previous ticket, we are just doing a new negative payment. Because of that, you should ensure that the external provider allow this return policy.

Registration

To allow the payment connector created to be selected you need to register it. To register your payment connector log in as System Administrator go to the window Reference, Find the record called Payment Provider and add a new record to the tab List reference. In this new record the value of the field Search Key must the name of the Enyo component created.

Sampleconnectorregister.png

Once created login as Client Administrator and go to the tab Payment Method of the window POS Terminal Type to select the connector created.

Sampleconnectoselect.png

Finally, you should create at least one payment type for a determined POS terminal which will use the defined payment method. More info here

Note: if you create the payment method but there aren't payment types, the payment method info will not be sent to the client side.

Configuration fields for the connector

The connector created may need some fields to configure it. This section explains how to add and use these fields needed.

Database fields

Configuration fields for connectors go to the database table OBPOS_APP_PAYMENT_TYPE. This is an example of adding a new field:

  alter table obpos_app_payment_type add column em_spco_configfield character varying(60);

Once created you need to add this field to the openbravo table OBPOS_App_Payment_Type and to the tab Payment Method of the window POS Terminal Type. Recompile your application and you will see your new field. This field can be access from your enyo component

 
  this.$.configvalue.setContent(this.paymentMethod.spcoConfigfield);

Communicating with an external provider

Openbravo Web POS client side has been developed using Javascript. Because javascript is not allowed to initiate cross domain calls Openbravo hardware manager is used as proxy.

Openbravo hardware manager works as proxy forwading ajax calls to the provided URL. When the response is received from the externa server it is forwarded to the client side. Using this approach Openbravo Web POS is able to communicate with external payment providers.

The contenttype of the data depends on the payment provider. In most cases is usual to use xml to send the data to the payment provider. The work to transform our json data to a valid XML document must be implemented by the connector.

 
      $.ajax({
        url: urlOfProxy, //hwmanager URL
        data: {
           url: url,
           contenttype: 'text/xml;charset=utf-8',
           content: OBPOSPCS.transformToXML(dataToSend)
        },
        dataType: 'json',
        type: 'POST',
        success: function (data){
        //Add the payment when the confirmation is received.
        //The information to save will depend on the payment provider
          var paymentresult = {
            TransactionID: data.Transaction.TransactionID,
            ApprovedAmount: data.Transaction.ApprovedAmount,
            CardNumberMasked: data.carddata.Card.MskPAN,
            CardLogo: data.Card.CardLogo          
            //Void transaction will be excuted when the payment line is removed.
            //VERY IMPORTANT TO REMOVE PAYMENTS
            voidTransaction: function (callback) {
              OB.ELPS.voidTransaction(this.paymentMethod, this, callback);
            }
          };
        error: function () {
          //Show an error to the user
        }
      });

Sample connector module

A working payment connector module containing all the sample code of this document can be downloaded from here: Sampleconnector.zip . This module includes a payment connector implementation that displays the payment information and adds it to the receipt.


Sampleconnectorpayment.png

Back to Concepts

Retrieved from "http://wiki.openbravo.com/wiki/Retail:Developers_Guide/External_Payment_Providers"

This page has been accessed 11,703 times. This page was last modified on 14 December 2016, at 14:51. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.