The ATM Simulator (People Hate Pearl!)

So, this is a proof-of-concept of ISO 8583 messaging in PHP. Everything you want to know about ISO 8583 (a complete) theory you can read at wikipedia page: http://en.wikipedia.org/wiki/ISO_8583. Anyway, article below will describe you a practical thing and technical work on how to understanding PHP socket programming - which is the core of ISO 8583. In short words: creating the ATM simulator with PHP!

Basically, ATM a.k.a ISO 8583 messaging using network socket to communicate between server and client. Take a look at general system activity defined below:


At first, server listening at specified address and port number, then client (for example: ATM) providing a block of ISO 8583 code to server (let say, client sending an account number). Server accepting command and parsing the code, continued to querying to backend. The result will returned back to client. Client accepting and parsing it again, and finally delivering a human-readable characters to the ATM screen.

To understand on how to developing the application, make sure that you:
  1. Familiar with PHP language.
  2. Able to use your favorite database client to create a single table.
  3.  Know the ISO 8583 philosophy.
  4. Having a PC with Apache & PHP enabled, also telnet client ready will help you much further. Windows (WAMP) and Mac OS (MAMP) is a great idea!

To start to build the application, keep in mind that there's 2 sequence things to create: SOCKET COMMUNICATION and ISO 8583 INTEGRATION.

SOCKET COMMUNICATION
This is a framework, since we need to create both different server and client applications that can interact using network socket. A server is listening and responding while client is sending and accepting. This is server code, save it with svr.php and store somewhere in your web server:

<?
error_reporting(E_ALL);
ob_implicit_flush();
$address = '10.2.2.212';
$port = 1234;
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
if (socket_bind($sock, $address, $port) === false)
{
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1))
{
echo socket_strerror(socket_last_error($sock));
exit;
}
}
if (socket_listen($sock, 5) === false)
{
echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}
do
{
if (($msgsock = socket_accept($sock)) === false)
{
echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
break;
}
$msg = "\nPOC-ISO Telnet Test. \n" .
"ketik 'quit' buat keluar, cuy...\n";
        socket_write($msgsock, $msg, strlen($msg));
        do
        {
        if (false === ($buf = socket_read($msgsock, 2048)))
        {
echo "socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)) . "\n";
break 2;
}
if (!$buf = trim($buf))
{
continue;
}
if ($buf == 'quit')
{
break;
}
$talkback = 'Response Server: ' . $buf;
$talkback = $talkback . "\n";br /> socket_write($msgsock, $talkback, strlen($talkback));
//===========================================
echo "$talkback\n";
}
while (true);
socket_close($msgsock);
}
while (true);
socket_close($sock);
?>

Run svr.php code with -q parameter and try to connect to server from telnet command. What? Telnet? Yup, that's why telnet client needed in our existing article - to test the svr.php code. Look at picture below:


Send a free-string and look what the server response from telnet window or simply type 'quit' to quit. If svr.php looks fine, now you can continue to client code. Below is the client code socket core, save it with cli.php and store it to a path in your pub html web server.

<?
$host="10.2.2.212";
$port = 1234;
$message = 'HELLO 1234, apa bisa di copy ganti?';
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Error: SOCKET\n");
$result = socket_connect($socket, $host, $port) or die("Error: JARINGAN\n");
socket_read ($socket, 2048) or die("Error: RESP\n");

$message = $message . "\n";socket_write($socket, $message, strlen($message)) or die("Error: DATA\n");
$result = socket_read($socket, 2048) or die("Error: RESP\n");
socket_write($socket, "quit", 4) or die("Error: QUIT\n");

echo $result;?>

Also, run client code cli.php with -q parameter from second terminal while svr.php still remains active in first terminal window. If the code is right, both will response the same message sent from cli.php. And finally the first thing of socket communication is done!

ISO 8583 INTEGRATION
Before we implement ISO 8583 method in both codes above, we need to define a table test which simulate the back-end storage. In my experiment, it's only a single table. Look ak the picture below:


After creating table, continue to download a PHP class named by JAK8583 from PHPClasses.org. Download it from http://www.phpclasses.org/package/5398-PHP-Generate-and-parse-ISO-8583-transaction-messages.html. This class mainly purposed for ISO 8583 builder and parser, so you need to attach both svr.php and cli.php to this class.

Meanwhile, prepare client code (cli.php) into an ATM look-a-like interface. Contains several pages start from initiation until finish transaction (index, input, resp, output and error landing page). Let say, this below is a welcome interface (index):


The rule of this simulator is simple. User typing in 10 digit account number from input page, server will validating it from database and returning back the result to the simulator screen. So, here below is the input page.


Now, let's modify cli.php with sending and catching capabilities. Note that it also containing ISO 8583 builder and parser (and client side validation) :


<?php
if ($_POST['submit'])
{
$host="10.2.2.212";
$port = 1234;
$no_rek = $_POST['no_rek'];
//===========================================
// =========== ISO-8583 BUILDER =============
//===========================================
include_once('JAK8583.class.php');
$jak = new JAK8583();
$jak->addMTI('1800');
$jak->addData(2, $no_rek);
$jak->addData(54, '000000');
$jak->addData(43, 'XXXXXXXXX');
$jak->addData(7, '000000');
$message = $jak->getISO();
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Error: SOCKET\n");
$result = socket_connect($socket, $host, $port) or die("Error: JARINGAN\n");
socket_read ($socket, 2048) or die("Error: RESP\n");
$message = $message . "\n";
socket_write($socket, $message, strlen($message)) or die("Error: DATA\n");
$result = socket_read($socket, 2048) or die("Error: RESP\n");
socket_write($socket, "quit", 4) or die("Error: QUIT\n");
//===========================================
// =========== ISO-8583 PARSER ==============
//===========================================
//echo $result;
$jak = new JAK8583();
$jak->addISO($result);
if ($jak->getMTI()=='1810')
{
$data_element=$jak->getData();
$no_id=$data_element[2];
$nama=$data_element[43];
$nominal=$data_element[54];
$bln=$data_element[7];

if ($nama=='XXXXXXXXX')
{
header('Location: err.php');
exit;
}
}
else
{
header('Location: err.php');
exit;
}
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>POC-ISO</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>


<body bgcolor="#0066CC">
<p align="center"><font color="#FFFFFF"><strong><font size="3">KONFIRMASI PEMBAYARAN
  <br>
  ========================= </font></strong></font></p>
<p align="center">&nbsp;</p>
<form name="fInput" method="post" action="output.php">
  <div align="center">
    <table width="75%" border="0" cellspacing="0" cellpadding="0">
      <tr>
        <td width="90%" rowspan="3"><div align="center">
            <table width="100%" border="0" cellspacing="0" cellpadding="0">
              <tr>
                <td width="53%"><font color="#FFFFFF" size="3"><strong>ID PELANGGAN</strong></font></td>
                <td width="2%"><font color="#FFFFFF" size="3"><strong>:</strong></font></td>
                <td width="45%"><font color="#FFFFFF" size="3"><strong><?=$no_id?></strong></font></td>
              </tr>
              <tr>
                <td><font color="#FFFFFF" size="3"><strong>NAMA</strong></font></td>
                <td><font color="#FFFFFF" size="3"><strong>:</strong></font></td>
                <td><font color="#FFFFFF" size="3"><strong><?=$nama?></strong></font></td>
              </tr>
              <tr>
                <td><font color="#FFFFFF" size="3"><strong>BULAN TAGIHAN</strong></font></td>
                <td><font color="#FFFFFF" size="3"><strong>:</strong></font></td>
                <td><font color="#FFFFFF" size="3"><strong><?=$bln?></strong></font></td>
              </tr>
              <tr>
                <td><font color="#FFFFFF" size="3"><strong>JUMLAH TAGIHAN</strong></font></td>
                <td><font color="#FFFFFF" size="3"><strong>:</strong></font></td>
                <td><font color="#FFFFFF" size="3"><strong><?=$nominal?></strong></font></td>
              </tr>
            </table>
          </div></td>
        <td width="10%"><div align="right">
            <input type="submit" name="submit" value="--&gt; BAYAR">
          </div></td>
      </tr>
      <tr>
        <td><div align="right"> </div></td>
      </tr>
      <tr>
        <td><div align="right">
            <input type="button" name="Button3" value="--&gt; BATAL" onClick="document.location.href='input.php'">
          </div></td>
      </tr>
    </table>
  </div>
</form>


<table width="75%" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td><font color="#FFFFFF" size="3"><strong>RESP :</strong></font><font color="#FFFFFF" size="3"><strong>
      <br>
      <?=$message?>
      </strong></font></td>
  </tr>
  <tr>
    <td><font color="#FFFFFF" size="3"><strong>RECP :</strong></font><font color="#FFFFFF" size="3"><strong>
      <br><?=$result?>
      </strong></font></td>
  </tr>
</table>
</body>
</html>


Saved it as resp.php (means response). If validation returned false - for example entering only 3 digit from input box, the screen will automatically redirecting to error page, just like picture below:


Picture above displayed after we input a wrong account number. There's no such "123" account number on database. Try to typing a correct account number and re-submit again. The response page will displayed like picture below:


Take a note at both ISO 8583 code in a red box above (RESP and RECP). RESP (response) code is ISO 8583 builder code sent from client to server. While RECP (receipt) code is parser code sent from server to client. Anyway, here's below svr.php code improvement containing connection to the database (MySQL) :

<?
error_reporting(E_ALL);
ob_implicit_flush();
$address = '10.2.2.212';
$port = 1234;

//===========================================
// DB
//===========================================
include_once('JAK8583.class.php');
ini_set('display_error',1);
define("DB_HOST", "your.db.svr.host");
define("DB_USER", "db_user_name");
define("DB_PASS", "db_passwd");define("DB_NAME", "db_name");
$link=mysql_connect(DB_HOST,DB_USER,DB_PASS);
mysql_select_db(DB_NAME);
mysql_query("SET time_zone='Asia/Jakarta'");
//===========================================

$sock = socket_create(AF_INET, SOCK_STREAM, 0);
if (socket_bind($sock, $address, $port) === false)
{
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1))
{
echo socket_strerror(socket_last_error($sock));
exit;
}
}
if (socket_listen($sock, 5) === false)
{
echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}


do
{
if (($msgsock = socket_accept($sock)) === false)
{
echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
break;
}
$msg = "\nPOC-ISO Telnet Test. \n" .
"ketik 'quit' buat keluar, cuy...\n";
        socket_write($msgsock, $msg, strlen($msg));
        do
        {
        if (false === ($buf = socket_read($msgsock, 2048)))
        {
echo "socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)) . "\n";
break 2;
}
if (!$buf = trim($buf))
{
continue;
}
if ($buf == 'quit')
{
break;
}
$jak = new JAK8583();
$jak->addISO($buf);

if ($jak->getMTI()=='1800') // Dari Client
{
$data_element=$jak->getData();
$no_id=$data_element[2];

$perintah="select * from trx where no_id='$no_id'";

$hasil=mysql_query($perintah);
$n_data=mysql_num_rows($hasil);
$jak = new JAK8583();
$jak->addMTI('1810');
if ($n_data==1)
 {  while ($row=mysql_fetch_array($hasil))
{
$no_id=$row["no_id"];
$nama=$row["nama"];
$bln=$row["bln"];
$nominal=$row["nominal"];
}
>
$jak->addData(2, $no_id);

$jak->addData(43, $nama);
$jak->addData(54, $nominal);
$jak->addData(7, $bln);
}
else
{
$no_id = 'ERR000';$jak->addData(2, $no_id);
$jak->addData(43, 'XXXXXXXXX');
$jak->addData(54, '000000');
$jak->addData(7, '000000');
}
}
$talkback = $jak->getISO(); $talkback = $talkback . "\n"; socket_write($msgsock, $talkback, strlen($talkback)); //===========================================
echo "$n_data|$buf|$perintah|$buf|$talkback|$no_id|$nama|$bln|$nominal\n";
}
while (true);
socket_close($msgsock);
}
while (true);
socket_close($sock);
?>

Ok, so far you can learn on how to validate input from database and returning back the result to client screen. Now you can also try to extend the functionality to create a valid payable transaction if user submit from the simulator that will simulated balance subtraction. For example, after submitted, the screen will change to greeting screen or notification which say that the transaction is over and also displaying the last balance, just like picture below :


That's it for the client simulator. Meanwhile from svr.php code above, we can monitoring the throughput of the transaction in server terminal window. The red box sign tell that validation returning false result, while green color is a valid transaction.


CONCLUSION:
Since ISO 8583 messaging interoperability involving 2 or more companies (in fact the bank and merchant eventually) in a real world, each from both programmer must deal with such formats; ISO 8583 year version, header, MTI, Data Element format, server address and port. The rest, it's a character manipulation module anyway! Have a great ISO 8583 coding and share your experience below. Thank's for ever coming here.

Labels: , , , ,

  Post a Comment

Auto-Synchronize Over FTP Link (RedHat & Ubuntu)

In a spesific programming case, database synchronization method will needed to accomodate data transfer between 2 or more servers. There are so much techniques we can adopt to make it work. And that's all depends on needs, business requirement, infrastructure availability & of course skill of you're own self.

Anyway, I don't wanna talk about synchronization techniques but actually, this latest article was begun from my previous one - Simple MySQL Replication Using FTP - when I implement automatically SQL file synchronization - using FTP protocol & by the help of crond daemon - between 2 RedHat (RHEL) server. The goal is that both servers having the same databases & tables (server A sending data to server B, server B sending data to server A).

However, the problem arises when one of the server changed the OS from RHEL to debian based (Ubuntu). While the automatic script I made from RHEL won't work on Ubuntu - especially the lines referring to FTP commands - bash shell script.

So, how to make the synchronization running again? No doubt, rewrite the script ASAP! Take a look at below script:

echo machine your.domain.or.ip > /root/.netrc
echo login your_username >> /root/.netrc
echo password your_password >> /root/.netrc
chmod 600 /root/.netrc

ftp your.domain.or.ip <<_FTP_
binary
put name.of.the.file
bye
_FTP_


Above is the code that only work on RHEL. While the FTP account created on separated file named by .netrc, this is not compatible to Ubuntu.

ftp -n -i <<_FTP_
open your.domain.or.ip
user your_username your_password
binary
put name.of.the.file
quit
_FTP_


Somehow, the FTP account initialization right on above script is integrated in the same script. And it just succedded running in Ubunru server. Moreover, there's no script affected in other servers. So, lesson of learning today is: never change server OS except you're ready for the impact. Deal?

Labels: , , , , , , ,

  Post a Comment

A Stumble Between Cloud Drive

What exactly is a cloud drive? in my opinion - It’s a virtual disk drive placed on a wide network or internet. In other words, there’s no necessity to carry up a USB drive anymore, but everywhere you need is an internet connection. I can say that cloud drive is a small part of cloud computing or any kind of this. I thought it was departed from FTP link mechanism, while you need your own domain to get it start. But with cloud drive, everything looks more portable now.

There are 2 big players on cloud drive; Google (GDrive) and Microsoft (SkyDrive). While Google integrating it with Google Mail (GMail), Microsoft combined it with Microsoft Live. It’s a different, but similar. Okay anyone know that Gmail has 8GB storage to archives email on each account, it’s a more than enough to save 2 DVD drives on that way. Since it takes lot of time to use up the spaces, this probably boiled down as a new Google product inherited.



Officially – AFAIK - Google has integrated GDrive into Windows shell by a small kit named Gmail Drive (click the link to get it), while others OS supported by each hardware vendors (such Acer Aspire One for their netbook products which came with Linux) or with Firefox add-ons which is support multi-platform. Anyway - after installing it - your Windows Explorer now enhanced with supplement folder named with Gmail Drive. As it has the same behavior as disk drive, this Gmail Drive also has properties window. Just point to it, right click & select properties. See, it has the same size with your Gmail space.



By the way you can do above way after you have an internet link. Further, try to go into the drive, click the Gmail Drive & it’ll appear a login window. Enter your account, and then verification window will show, just like picture below.



To take example, try to copy & paste a file or folder. After it copied, the drive will send an email alert inform you that you or someone using your account had store a thing(s) on GDrive. Now, how about SkyDrive? It’s resemble with GDrive (with extra drive additional & extra space!), but the software kit was develop from 3rd party (not officially from Microsoft).



You can try to download the kit named by SDExplorer from this link. Install it (an extra drive will available named with SDExplorer) & try to log on with your Windows Live ID (create one if you doesn’t have).



Login to it & - as I say - you’ll have an extra 25GB drive space! Is any provider can supply more than this? However, this SkyDrive has the same operation treatment as GDrive, as it simply as copy, cut or paste.

Conclusion
From example on this article, no need to spare money to buy an extra USB disk, since you’ll have additional 33GB for free on the net accessed precisely from your Windows Explorer.



Those “virtual” drive above hit a bit benefit on me, it’s a secondary storage to store my micro files (like configuration files or something else) just in case if you forget to carry your USB disk. While it contains micro files, it doesn’t take long time to download it from the cloud drive. Share your comment below, thanks for reading & good day.

Labels: , , , , , ,

  Post a Comment

Internet Connection Sharing via Wifi

Having two or more personal laptop or PC on home nowadays is not an extraordinary thing. Especially for those who play in rough with IT sector or gadget freakier, I called it “a-must have”. Survey research result found on internet clarify that 91 percent of those who have a netbook also own a laptop and 87 percent own a desktop. Some husband also equip their house with two laptop for their wife, so that there’s no more problem for both of them to kill their each pleasure time – husband working on his spread sheet business and wife sharing minds with her facebook page. But, how about if husband need to send email his work immediately while his wife still browsing for her lingerie on the internet? No problem at all if they have both modem, but troubling wife for her modem might become a big problem. This article will assist you how to setting up internet connection over wireless signal built-in on common laptop or PC, it’s a cheap trick than buying a new modem and more practice than using a cross cable.

First of all, make sure that both wifi on each PC or laptop is currently exist and active. Set wifi IP address on host machine where the modem plugged in (I used my 12” Travelmate 6291 for this) with 192.168.0.1 and subnet mask with 255.255.255.0 just like picture below:



From Wireless Network tab on the same Wireless Network Properties window, click Add button to add wifi network identification name. From example, I named it with “TravelMate” and configured it with Open Network Authentication. Don’t forget to check “This is a computer to computer (ad hoc) network“ on bottom of the window.



To test whether it succeeded or not, let the machine search for current wifi signal. It will found at least with your existing network name you made already. On example, it will display “TravelMate” wifi connection.



Next, plugged in the modem and activate the internet connection link. Mine was particularly Huawei E160 dongle USB modem with Unlimited IM2 Broom ISP SIM card. After the link is up, click on Advanced tab from properties window, check for Internet Connection Sharing and make sure to share it over wireless network connection.



Done for the host connection, now get ready to switch to guest device. Set wifi IP address from guest device to 192.168.0.2 with same subnet mask but point to host IP address as both gateway and DNS address (192.168.0.1).



Now, let the guest search for existing signal. It will found host wifi network signal (example: “TravelMate”) and make it try to connect to host.



After it succeeded “paired”, try to pinging an internet host from command prompt or you can open a page from browser directly. That’s all, if there’s nothing left, both device will have internet connection from single modem plugged in on one of the computer.



PS: I dedicated this article to my buddy and blessed for his brand new 10” Lenovo Ideapad S10 with Veriface Recognition software that I finally cracked and working on my Aspire One.

Labels: , , ,

  Post a Comment

Again, Connecting to YM!

For everyone who has connection troubles with Yahoo Messenger (YM) especially blocked link by the network administrator, there are several solutions to be done. This problem & answer are comes out based on my own experiences about how to connecting to the YM blocked port in a large configured company LAN. Each solutions referring a succeeded connection, give a try before rolling to the next stage.
  1. As you might know, the YM installer are comes with online process which resulting an error in a downloading setup data. This error appeared as a part of a forbidden network. Try to download the YM offline installer from Yahoo download pages & have a try to run it. After installation, make a connection preferences set to no proxy & give a right account to log in.
  2. If you have failed in step #1, take off the network cables & continued to connect the internet from dial up process. Do this stage for only once. After you succeeded to log on, remove the dial up & plug in the network cables. You might also try this step from YM online installer too.
  3. Again, if you have a no connection result after tried solution #2, have a try with Windows Live Messenger (WLM). This new messenger application from Microsoft are comes with it's new feature and able to communicate to the YM (via http?) port. First, download the WLM from Microsoft download page & get the account from .NET Passport. Just follow the wizard to make it done. After succeeded logged in from WLM, make a test connection with your YM friend account. This yet last solution are more practical & successful on me. Good luck!

Labels:

  Post a Comment

FC4

  Post a Comment