Sie sind auf Seite 1von 22

[code]

/**

*/

package in2.pos;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Arrays;

import java.util.Enumeration;

import java.util.Properties;

import java.util.ResourceBundle;

import java.util.StringTokenizer;

import javax.swing.JOptionPane;

import oracle.forms.handler.IHandler;

import oracle.forms.properties.ID;

import oracle.forms.ui.CustomEvent;

import oracle.forms.ui.VBean;

import gnu.io.*;

/**

* PosTerminalPjc, PJC component for Hypercom POS terminal data exchange

* @author Peter Valencic, peterv@in2.si

*/

public class PosTerminalPjc extends VBean {


private static final long serialVersionUID = -8814623494538014849L;

Properties res = new Properties();

SerialPort serialPort;

OutputStream os;

InputStream is;

CommPortIdentifier portId;

Enumeration portList;

IHandler mHandler;

char STX = (char) 0x02;

char ETX = (char) 0x03;

char EOT = 4;

char ACK = 6;

char NAK = 15;

char FS = 28;

private static final ID COMPORT = ID.registerProperty("COMPORT"); // serial

// port

// (COM1,COM2,COM3,...)

private static final ID AMOUNT = ID.registerProperty("AMOUNT"); // amount of

// the

// transaction

// (12)

private static final ID TRANSACTIONTYPE = ID


.registerProperty("TRANSACTIONTYPE"); // 01-sale, 05-refund, 13

// ticket duplicate

private static final ID AMOUNTCURRENCY = ID

.registerProperty("AMOUNTCURRENCY"); // ISO currency code

private static final ID TRANSACTIONNUMBER = ID

.registerProperty("TRANSACTIONNUMBER"); // transaction number

private static final ID EVT_OK = ID.registerProperty("EVT_OK"); //custom event if


all ok

private static final ID EVT_ERR = ID.registerProperty("EVT_ERR"); //custom


event if error occured

// state machine variables

long l_timeout;

long l_wait_for = 5000; // pos terminal wait for command (5 seconds)

long l_wait_for_transaction = 62000 * 2; // pos terminal timeout

long l_second = 1000; // one second

byte b_retry = 0;

String dataValue = "";

byte[] readBuffer = new byte[2000]; //2000 bytes buffer to read rs232 stream

String comPort = ""; // local variable to store com port name

// (COM1,COM2,...)

String transactionType = "SALE"; // type of transaction to be executed (SALE

// or REFUND) default SALE

String amount = "0"; // default amount value is set to 0

String transactionNumber =""; //store a transaction number from POS trminal

String transactionProcessed;

String transactionFlag;

String transactionDate;
String transactionTime;

String transactionBatchNumber;

String terminalTid;

String terminalCard;

String errDesc;

public PosTerminalPjc() {

super();

System.out.println("============================");

System.out.println("== State machine POS v1.0 ==");

System.out.println("== Peter Valencic (c) ==");

System.out.println("== 03.04.2012 ==");

System.out.println("============================");

try {

res.load(this.getClass().getResourceAsStream(

"/res/language.properties")); // load language file

} catch (Exception ex) {

System.err.println("Err loading language.properties file: "

+ ex.toString());

private void doTransaction() throws Exception {

String phase = null; // initial null value for state machine phase

long l_ack_timeout = 0; //initial value for acknowledge timeout


// com port check

if (getComPort().trim().equalsIgnoreCase("")) {

this.showError(res.getProperty("s_dlg_err_title"),

res.getProperty("s_com_invalid"));

return;

// transaction type chek

System.out.println(this.getTransactionType());

if (!getTransactionType().equalsIgnoreCase("REFUND")

& !getTransactionType().equalsIgnoreCase("SALE")) {

this.showError(res.getProperty("s_dlg_err_title"),

res.getProperty("s_tran_invalid_type"));

return;

portList = portId.getPortIdentifiers();

while (portList.hasMoreElements()) {

portId = (CommPortIdentifier) portList.nextElement();

if (portId.getName().equalsIgnoreCase(this.getComPort())) {

System.out.println("Port is used : "

+ portId.isCurrentlyOwned());

serialPort = (SerialPort) portId.open("ComDriver", 2000);


serialPort.setSerialPortParams(9600, SerialPort.DATABITS_7,

SerialPort.STOPBITS_1, SerialPort.PARITY_EVEN);

// serialPort.addEventListener(this);

serialPort.notifyOnDataAvailable(true);

serialPort.notifyOnOutputEmpty(true);

os = serialPort.getOutputStream();

is = serialPort.getInputStream();

break;

if (portId == null) {

throw new Exception(res.getProperty("s_com_not_found")

+ this.getComPort() + "\n");

// state machine infinite loop

while (true) {

// SEND DATA TO POS TERMINAL

if (phase == null) {

System.out.println("start phase");

byte[] req = null;


//verify transaction type to be SALE or REFUND

//if REFUND then transaction number must be specified

if (getTransactionType().equalsIgnoreCase("SALE")) {

System.out.println("--> SALE send message to the pos terminal");

System.out.println("--> amount: " + amount);

req = protocolStream("000000123401100" + FS + amount + FS

+ FS + "+0" + FS + "978" + FS + FS + FS + FS + FS

+ FS + FS + ETX);

else if (getTransactionType().equalsIgnoreCase("REFUND")) {

System.out.println("--> REFUND send message to the pos terminal");

System.out.println("--> amount: " + amount);

System.out.println("--> transaction number: " + getTransactionNumber());

req = protocolStream("000000123405100" + getTransactionNumber() + FS + amount

+ FS + FS + "+0" + FS + "978" + FS + FS + FS + FS

+ FS + FS + FS + ETX);

} else {

// maybe VOID in the future..

os.write(req);

os.flush();

l_ack_timeout = System.currentTimeMillis() + 1500;

//wait for half second

try {

Thread.sleep(500);
} catch (Exception ee) {

l_timeout = System.currentTimeMillis() + l_wait_for; //add some time for timeout

phase = "TO_POS_ACK";

System.out.println("phase: " + phase);

}//phase null

//CHECK IF THE TIMEOUT OCCURED

if (phase.equalsIgnoreCase("TO_POS_ACK") &

(l_timeout < System.currentTimeMillis()) & (b_retry < 4)) {

b_retry += 1;

System.out.println("TIMEOUT: " + b_retry);

l_timeout = System.currentTimeMillis() + l_wait_for;

if (b_retry >= 4) {

System.out.println("Timeout occured");

try {

serialPort.close();

is.close();

os.close();

} catch (Exception ee) {

}
//Timeout occured show error

//s_timeout

this.showError(res.getProperty("s_dlg_err_title"),

res.getProperty("s_timeout"));

break;

//CHECK FOR THE ACKNOWLEDGE (FIRST RESPONSE FROM POS TERMINAL)

if (phase.equalsIgnoreCase("TO_POS_ACK") &

(l_ack_timeout < System.currentTimeMillis())) {

try {

int numBytes = 0;

dataValue = "";

while ((numBytes = is.read(readBuffer)) > 0) {

dataValue += new String(readBuffer, 0, numBytes, "ASCII");

if (dataValue.getBytes().length > 0) {

System.out.println("->first byte: " +

dataValue.getBytes()[0]);

System.out.println("total length: " +

dataValue.getBytes().length);
//check for ack byte

if (dataValue.getBytes()[0] == 6) {

System.out.println(

"<--ACKNOWLEDGE received from pos terminal");

phase = "WAIT_FOR_TRANSACTION";

l_timeout = System.currentTimeMillis() +

l_wait_for_transaction;

} catch (IOException ev) {

//WAIT FOR TIMEOUT ON MESSAGE

if (phase.equalsIgnoreCase("WAIT_FOR_TRANSACTION") &

(l_timeout < System.currentTimeMillis())) {

System.out.println(

"Error receiving response from pos terminal!!!");

try {

serialPort.close();

is.close();

os.close();

} catch (Exception ee) {

}
this.showError(res.getProperty("s_dlg_err_title"),

res.getProperty("s_response_error"));

break;

//WAIT FOR SOME DATA TO COME FROM POS TERMINAL OVER RS232

if (phase.equalsIgnoreCase("WAIT_FOR_TRANSACTION")) {

try {

int numBytes = 0;

dataValue = "";

while ((numBytes = is.read(readBuffer)) > 0) {

dataValue += new String(readBuffer, 0, numBytes, "ASCII");

if (dataValue.getBytes().length > 0) {

System.out.println("->first byte: " +

dataValue.getBytes()[0] + "|" +

dataValue.getBytes()[1]);

System.out.println("->ascii: " + dataValue);

System.out.println("total length: " +

dataValue.getBytes().length);
if (dataValue.indexOf("PREKINIL UPORABNIK") != -1) {

System.out.println(

"Uporabnik je prekinil povezavo!");

try {

serialPort.close();

is.close();

os.close();

} catch (Exception ee) {

//transaction cancelled by user s_user_cancel

this.showError(res.getProperty("s_dlg_err_title"),

res.getProperty("s_user_cancel"));

break;

if (dataValue.indexOf("NAPACEN VNOS") != -1) {

System.out.println("Napacen vnos");

try {

serialPort.close();

is.close();

os.close();
} catch (Exception ee) {

//invalid user entry

this.showError(res.getProperty("s_dlg_err_title"),

res.getProperty("s_user_invalid_entry"));

break;

if (dataValue.indexOf("PROSIM POCAKAJ") != -1) {

System.out.println("<-- PROSIM POCAKAJ");

continue;

//preberemo podatke iz stringe terminala

if (dataValue.indexOf("SPREJETO") != -1) {

try {

serialPort.close();

is.close();

os.close();

} catch (Exception ee) {

System.out.println("<-- TRANSAKCIJA SPREJETA");

System.out.println(dataValue);
System.out.println("Proimo event v formse");

this.transactionProcessed = dataValue.substring(1,
3); //podatek mora biti 10

this.transactionFlag = dataValue.substring(13, 15);

this.transactionNumber = dataValue.substring(16, 21);

System.out.println("transaction number: " +


this.transactionNumber);

this.transactionDate = dataValue.substring(25, 31);

this.transactionTime = dataValue.substring(31, 37);

this.transactionBatchNumber = dataValue.substring(21,
25);

StringTokenizer st = new StringTokenizer(dataValue, ""


+ FS);

System.out.println(st.nextToken());

System.out.println(st.nextToken());

System.out.println(st.nextToken());

System.out.println(st.nextToken());

System.out.println(st.nextToken());

System.out.println(st.nextToken());

this.terminalTid = st.nextToken();

System.out.println(st.nextToken());

System.out.println(st.nextToken());

System.out.println(st.nextToken());

this.terminalCard = st.nextToken();
if (transactionProcessed.equalsIgnoreCase("10")) {

else

CustomEvent ce = new CustomEvent(mHandler,

EVT_ERR);

if (transactionProcessed.equalsIgnoreCase("00")) {

System.out.println(

"Error in the format of the request


message");

this.errDesc = res.getProperty("s_tf_00");

} else if (transactionProcessed.equalsIgnoreCase(

"01")) {

System.out.println(

"Transaction accepted without authorization


code");

this.errDesc = res.getProperty("s_tf_01");

} else if (transactionProcessed.equalsIgnoreCase(

"02")) {

System.out.println(

"Transaction accepted with authorization


code");

this.errDesc = res.getProperty("s_tf_02");

} else if (transactionProcessed.equalsIgnoreCase(

"03")) {

System.out.println("Needs voice referall");

this.errDesc = res.getProperty("s_tf_03");

} else if (transactionProcessed.equalsIgnoreCase(
"04")) {

System.out.println("Transaction refused");

this.errDesc = res.getProperty("s_tf_04");

} else if (transactionProcessed.equalsIgnoreCase(

"05")) {

System.out.println(

"Needs manual card data entry");

this.errDesc = res.getProperty("s_tf_05");

} else if (transactionProcessed.equalsIgnoreCase(

"06")) {

System.out.println(

"Authorization call failure");

this.errDesc = res.getProperty("s_tf_06");

dispatchCustomEvent(ce);

return;

//ce gre skozi potem je vse ok

CustomEvent ce = new CustomEvent(mHandler, EVT_OK);

dispatchCustomEvent(ce);

return;

}
}

} catch (IOException ev) {

//wait 200 ms

try {

Thread.sleep(200);

} catch (InterruptedException ex) {

ex.printStackTrace();

System.out.print('*');

}//end state machine loop

/**

* protocolStream prepare the stream to be send over RS232 to POS terminal

* with LRC cheksum control

* @param data

* @return byte[]
*/

private byte[] protocolStream(String data) {

char STX = (char) 0x02;

String tmp = "" + STX + STX + data + "" + getLRC(data);

System.out.println("PStream: " + tmp);

for (int i = 0; i < tmp.getBytes().length; i++) {

System.out.print(tmp.getBytes()[i] + ":");

// System.out.println("ceksum: " + chksm);

return tmp.getBytes();

/**

* Longitudinal Redundancy Check (LRC)

* @param packet

* @return String

*/

private String getLRC(String packet) {

char[] splitPacket = packet.toCharArray();

char lrc = 0x00;

for (int x = 0; x < splitPacket.length; x++) {

lrc = (char) (lrc ^ splitPacket[x]);

return "" + (char) lrc;


}

private String paddingString(String s, int n, char c, boolean paddingLeft) {

if (s == null) {

return s;

int add = n - s.length(); // may overflow int size... should not be a

if (add <= 0) {

return s;

StringBuffer str = new StringBuffer(s);

char[] ch = new char[add];

Arrays.fill(ch, c);

if (paddingLeft) {

str.insert(0, ch);

} else {

str.append(ch);

return str.toString();

}
/**

* Display error message inside oracle form

* @param title

* @param exceptionString

*/

private void showError(String title, String exceptionString) {

JOptionPane.showMessageDialog(this, exceptionString, title, 0);

public String getComPort() {

return comPort;

public void setComPort(String comPort) {

this.comPort = comPort;

public String getTransactionType() {

return transactionType;

public void setTransactionType(String transactionType) {

this.transactionType = transactionType;
}

public String getAmount() {

return amount;

public void setAmount(String amount) {

this.amount = amount;

public String getTransactionNumber() {

return transactionNumber;

public void setTransactionNumber(String transactionNumber) {

this.transactionNumber = transactionNumber;

public static void main(String[] args) {

PosTerminalPjc pjc = new PosTerminalPjc();

pjc.setComPort("COM1");

pjc.setTransactionType("SALE");

pjc.setAmount("1000");

try

pjc.doTransaction();

}
catch(Exception ex)

System.err.println(ex.toString());

[/code]

Das könnte Ihnen auch gefallen