Name Last Update
alembic Loading commit data...
contrib Loading commit data...
iso8583_web Loading commit data...
.gitignore Loading commit data...
CHANGES.txt Loading commit data...
MANIFEST.in Loading commit data...
README.rst Loading commit data...
alembic.ini.tpl Loading commit data...
development.ini Loading commit data...
iso8583-aggregator.ini Loading commit data...
iso8583-bank.ini Loading commit data...
iso8583-pemda.ini Loading commit data...
msgfmt.sh Loading commit data...
production.ini Loading commit data...
pytest.ini Loading commit data...
requirements.txt Loading commit data...
setup.py Loading commit data...

Daemon ISO8583

Daemon ISO8583 ini bisa sebagai client maupun server. Berikut ini cara pemasangannya. Nama paketnya mengandung web karena ia bisa dihubungi melalui web service JSON-RPC untuk inquiry, payment, dan reversal.

Pemasangan

Buat Python virtual environment:

$ python3 -m venv ~/env

Awali dengan memasang paket ebcdic yang dibutuhkan ISO8583:

$ ~/env/bin/pip install ebcdic

Pemasangan yang tidak otomatis ini agar tidak menimbulkan kegagalan. Lanjut:

$ ~/env/bin/pip install git+https://git.opensipkd.com/sugiana/iso8583-web

Selanjutnya kita membutuhkan tiga terminal untuk simulasi:

  1. ISO8583 daemon sebagai pemda. Ini akan mengakses bank ke port 10002.
  2. ISO8583 daemon sebagai bank. Ini akan listen di port 10002, dan pada saat yang sama dia listen di port 7000 sebagai web server.
  3. Web client sebagai simulasi aplikasi teller yang akan mengakses web server tadi.

Sebagai Pemda

Berikut ini diagram komunikasi ISO8583 Pemda dengan BJB:

+----------------+         +-------+
| BJB port 10002 | <-----> | Pemda |
+----------------+         +-------+

Buat file konfigurasi test-pemda.ini:

[loggers]
keys = root, iso8583_web

[handlers]
keys = console, file

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console, file

[logger_iso8583_web]
level = DEBUG
handlers =
qualname = iso8583_web

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[handler_file]
class = FileHandler
args = ('/home/sugiana/log/pemda.log', 'a')
level = DEBUG
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)s %(message)s

[module_opensipkd.iso8583.bjb.pbb.bogor_kota]
db_url = postgresql://user:pass@localhost/db
persen_denda = 2
nip_pencatat = 999999999
kd_kanwil = 01
kd_kantor = 01
kd_tp =
    bit42:TOKOPEDIA:46
    bit42:BUKALAPAK:47
    bit43:INDOMARET:48
    bit43:ALFAMART:49
    bit18:6010:69
    bit18:6011:71
    bit18:6012:72
    bit18:6013:73
    bit18:6014:74
    bit18:6015:75
    bit18:6016:76
    bit18:6017:77
    bit0:default:20

[host_bjb]
ip = 127.0.0.1
port = 10002
listen = false
streamer = bjb_with_suffix
timeout = 60
module = opensipkd.iso8583.bjb.pbb.bogor_kota

Kita bisa menambahkan host lainnya dengan menambahkan awalan host_ pada section, misalnya host_mitracomm.

Modul opensipkd.iso8583.bjb.pbb.bogor_kota tidak ada di paket ini sehingga kita perlu memasangnya:

$ ~/env/bin/pip install git+https://git.opensipkd.com/sugiana/opensipkd-iso8583-bjb

Modul ini memerlukan tabel untuk mencatat transaksi. Terlebih dahulu buat file konfigurasi iso8583-pbb.ini yang merupakan non daemon:

[main]
module = opensipkd.iso8583.bjb.pbb.bogor_kota
db_url = postgresql://user:pass@localhost/db

Buat tabelnya:

$ ~/env/bin/iso8583_bjb_pbb_initdb iso8583-pbb.ini

Pastikan tidak ada kesalahan. Lalu jalankan daemon-nya:

$ ~/env/bin/iso8583 test-pemda.ini

Anda akan mendapat pesan seperti ini:

2019-02-07 20:41:30,180 INFO Connect to 127.0.0.1 port 10002
2019-02-07 20:41:30,180 ERROR [Errno 111] Connection refused

Abaikan dulu refused itu karena daemon bank memang belum ada. Biarkan ini aktif.

Sebagai Bank

Melanjutkan diagram sebelumnya maka kini ada simulasi teller yang menghubungi kantor pusatnya:

                  +--------------------+
                  | BJB                |         +-------+
+--------+        | ISO8583 port 10002 | <-----> | Pemda |
| Teller | -----> | HTTP port 7000     |         +-------+
+------- +        +--------------------+

HTTP atau web service merupakan komunikasi satu arah, oleh karena itu hanya digambarkan satu panah saja. Selanjutnya buka terminal ke-2, dan buat file test-bank.ini:

[loggers]
keys = root, iso8583_web, jsonrpc

[handlers]
keys = console, file

[formatters]
keys = generic

[logger_root]
level = INFO
handlers = console, file

[logger_iso8583_web]
level = DEBUG
handlers =
qualname = iso8583_web

[logger_jsonrpc]
level = DEBUG
handlers = console, file
qualname = pyramid_rpc.jsonrpc

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[handler_file]
class = FileHandler
args = ('/home/sugiana/log/bank.log', 'a')
level = DEBUG
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)s %(message)s

[host_kota_bogor]
ip = 127.0.0.1
port = 10002
listen = true
streamer = bjb_with_suffix
module = opensipkd.iso8583.bjb.pbb.test

[web]
port = 7000
threads = 12

[web_teller]
route_path = /rpc
host = kota_bogor
module = iso8583_web.scripts.views.jsonrpc
allowed_ip =
    127.0.0.1
    10.8.20.1

Perbedaannya adalah pada:

  1. Log file
  2. listen = true yang berarti bank sebagai server-nya
  3. Penggunaan modul opensipkd.iso8583.bjb.pbb.test dimana modul ini tidak menggunakan database sehingga tidak perlu konfigurasi tambahan.

Juga ada konfigurasi terkait web server yang merupakan gerbang aplikasi teller untuk transaksi. Perhatikan section web ini:

[web]
port = 7000
threads = 12

dimana:

  • port adalah network port yang listen. Tentu saja yang dimaksud adalah HTTP port.
  • threads adalah jumlah worker yang siaga. Ini artinya pada saat yang sama web server ini sanggup menangani 12 web client.

Selanjutnya section web_teller:

[web_teller]
route_path = /rpc
host = kota_bogor
module = iso8583_web.scripts.views.jsonrpc
allowed_ip =
    127.0.0.1
    10.8.20.1

Section yang berawalan web_ adalah konfigurasi untuk setiap jenis web client. Bandingkan dengan section yang berawalan host_ yang berarti konfigurasi untuk ISO8583. Berikut penjelasannya:

  • route_path merupakan URL path, selalu awali dengan /
  • host = kota_bogor berarti harus ada section host_kota_bogor. Ini merupakan routing, akan diarahkan ke ISO8583 mana HTTP request ini.
  • module merupakan modul Pyramid yang akan digunakan untuk menanggapi HTTP request
  • allowed_ip berisi IP yang diperkenankan menggunakan jalur ini. Jika dikosongkan maka diperkenankan diakses dari IP manapun.

Bila konfigurasi web ini digabungkan maka URL-nya menjadi http://127.0.0.1:7000/rpc.

Sekarang jalankan:

$ ~/env/bin/iso8583 test-bank.ini

Seharusnya ada penampakan seperti ini:

2020-07-18 22:27:44,360 INFO Web server JSON-RPC route path /rpc
2020-07-18 22:27:44,373 INFO Web server listen at 0.0.0.0:7000 with 12 workers
2020-07-18 22:27:44,373 INFO ISO8583 server listen at 0.0.0.0:10002
2020-07-18 22:27:46,592 INFO 127.0.0.1 allowed
2020-07-18 22:27:51,595 INFO 127.0.0.1 kota_bogor 140197249940784 Receive [b'00560800822000000000000004000000000000000718222751222236301\x03']
2020-07-18 22:27:51,596 INFO 127.0.0.1 kota_bogor 140197249940784 Raw to ISO8583 [b'0800822000000000000004000000000000000718222751222236301']
2020-07-18 22:27:51,598 INFO 127.0.0.1 kota_bogor 140197249940784 -> 140197249940688 Decode MTI 0800 Data {7: '0718222751', 11: '222236', 70: '301'}
2020-07-18 22:27:51,602 INFO 127.0.0.1 kota_bogor 140197249940784 -> 140197249940688 Encode MTI 0810 Data {7: '0718222751', 11: '222236', 39: '00', 70: '301'}
2020-07-18 22:27:51,602 INFO 127.0.0.1 kota_bogor 140197249940784 ISO8583 to raw [b'081082200000020000000400000000000000071822275122223600301']
2020-07-18 22:27:51,603 INFO 127.0.0.1 kota_bogor 140197249940784 Send [b'0058081082200000020000000400000000000000071822275122223600301\x03']

Berikut penjelasannya:

  1. Baris Receive bermakna ada raw stream yang diterima, yaitu dari pemda yang berada di terminal pertama tadi.
  2. Baris Raw to ISO8583 bermakna hapus network header dari raw stream agar menjadi dokumen ISO8583 saja.
  3. Baris Decode bermakna terjemahkan dokumen itu agar mudah dibaca manusia.

Sampai di sini ketiga baris log tersebut dinamakan request. Dalam kasus ini disebut echo request karena:

  1. MTI bernilai 0800
  2. Bit 70 bernilai 301

Setiap request perlu mendapat response berarti perlu disiapkan echo response yaitu:

  1. MTI bernilai 0810
  2. Bit 70 bernilai 301

Kembali ke log tadi, baris berikutnya adalah Encode yang berarti dokumen ISO8583 akan disiapkan hingga Send. Ini kebalikan sebelumnya dimana Receive hingga Decode.

Keenam baris tersebut sering disebut dengan kondisi echo established yang menandakan tidak ada masalah network sehingga siap transaksi.

Setelah echo established dengan daemon pemda selanjutnya lakukan inquiry (cek tagihan) dengan cara:

$ ~/env/bin/iso8583_web_client --url=http://127.0.0.1:7000/rpc --invoice-id=3271010001007002701995

Hasilnya:

2020-07-18 23:53:03.150 Request: {'id': 1, 'method': 'inquiry', 'params': [{'invoice_id': '3271010001007002701995'}], 'jsonrpc': '2.0'}
2020-07-18 23:53:04.494 Response: {'jsonrpc': '2.0', 'id': 1, 'result': {'code': 0, 'message': 'OK', 'data': {'3': '341019', '4': '000000019536', '7': '0718235304', '11': '235069', '12': '235303', '13': '0718', '18': '6010', '33': '00110', '39': '00', '61': '3271010001007002701995', '62': '3271010001007002701995UW** *****SNA                      JL LINCAR I                        TEGAL GUNDIL                       BOGOR UTARA                        JAWA BARAT                         00000000012300000000007219951130000000019536000000009378000000028914000000009378'}}}
2020-07-18 23:53:04.499 thread 1 1.3430681228637695 detik stan 235069
2020-07-18 23:53:04.499 Tidak ada yang gagal

Pastikan bit 39 bernilai 00 yang berarti siap dibayar. Lanjutkan dengan --payment dimana opsi --amount juga harus disertakan, nilainya diperoleh dari inquiry response bit 4:

$ ~/env/bin/iso8583_web_client --url=http://127.0.0.1:7000/rpc --invoice-id=3271010001007002701995 --payment --amount=19536

Hasilnya:

2020-07-19 05:49:51.532 Request: {'id': 1, 'method': 'payment', 'params': [{'invoice_id': '3271010001007002701995', 'amount': 19536, 'ntb': '0719054951', 'stan': '054951'}], 'jsonrpc': '2.0'}
2020-07-19 05:49:52.217 Response: {'jsonrpc': '2.0', 'id': 1, 'result': {'code': 0, 'message': 'OK', 'data': {'3': '541019', '4': '000000019536', '7': '0719054952', '11': '054237', '12': '054951', '13': '0719', '18': '6010', '33': '00110', '39': '00', '41': '', '42': '', '43': '', '47': '010192430486', '48': '0719054951', '61': '3271010001007002701995', '62': '3271010001007002701995UW** *****SNA                      JL LINCAR I                        TEGAL GUNDIL                       BOGOR UTARA                        JAWA BARAT                         00000000012300000000007219951130000000019536000000009378000000028914000000009378'}}}
2020-07-19 05:49:52.222 thread 1 0.6849231719970703 detik stan 054237
2020-07-19 05:49:52.222 Tidak ada yang gagal

Lagi, pastikan bit 39 bernilai 00 yang berarti pembayaran berhasil. Selanjutnya gunakan opsi --reversal untuk membatalkan pembayaran ini. Selain --amount kita juga membutuhkan opsi --stan dan --ntb yang diperoleh saat payment request yaitu bit 11 dan bit 48 pada baris Response di atas:

$ ~/env/bin/iso8583_web_client --url=http://127.0.0.1:7000/rpc --invoice-id=3271010001007002701995 --reversal --amount=19536 --ntb=0719054951 --stan=054237

Hasilnya:

2020-07-19 06:10:58.334 Request: {'id': 1, 'method': 'reversal', 'params': [{'invoice_id': '3271010001007002701995', 'amount': 19536, 'ntb': '0719054951', 'stan': '054237'}], 'jsonrpc': '2.0'}
2020-07-19 06:10:58.847 Response: {'jsonrpc': '2.0', 'id': 1, 'result': {'code': 0, 'message': 'OK', 'data': {'3': '541019', '4': '000000019536', '7': '0719061058', '11': '054237', '39': '00', '48': '0719054951', '61': '3271010001007002701995'}}}
2020-07-19 06:10:58.852 thread 1 0.5126473903656006 detik stan 054237
2020-07-19 06:10:58.852 Tidak ada yang gagal

Pastikan bit 39 bernilai 00 yang menandakan pembatalan berhasil.

Stress Test

Ini adalah tentang mendapatkan jumlah maksimal transaksi yang berhasil pada saat bersamaan. Gunakan opsi --count=12 yang berarti 12 transaksi pada saat yang sama:

$ ~/env/bin/iso8583_web_client --url=http://127.0.0.1:7000/rpc --invoice-id=3271010001007002701995 --count=12

Hasil akhirnya akan tampak statistik:

2020-07-18 23:56:09.246 Tercepat thread 4 0.6237032413482666 detik stan 235419
2020-07-18 23:56:09.246 Terlama thread 8 2.6911497116088867 detik stan 236181
2020-07-18 23:56:09.246 Rerata 1.9630980730056762 detik / request
2020-07-18 23:56:09.246 Tidak ada yang gagal

Pastikan kita mendapat pesan Tidak ada yang gagal. Angka 12 dipilih sesuai dengan jumlah threads pada file konfigurasi test-bank.ini. Silakan naikkan angkanya hingga:

  1. Ada yang gagal, biasanya karena timeout.
  2. Kecepatan transaksi rata-rata melampaui ambang batas. Biasanya jangan sampai lebih dari 15 detik.

Jika salah satu kondisi di atas tercapai maka turunkan nilai threads.

LinkAja

LinkAja merupakan produk PT Telkom yang berkomunikasi dengan Agratek. Melanjutkan diagram sebelumnya maka berikut ini alurnya:

                                              +--------------------+
                                              | BJB                |         +------------------+
                   +----------------+         | ISO8583 port 10002 | <-----> | Pemda Kota Bogor |
+---------+        | Agratek        | <-----> | ISO8583 port 10001 |    |    +------------------+
| LinkAja | -----> | HTTP port 7001 |         |                    |    |
+---------+        +----------------+         |                    |    |    +-------------------+
                                              |                    |    +--> | Pemda Kota Bekasi |
                            +--------+        |                    |         +-------------------+
                            | Teller | -----> | HTTP port 7000     |
                            +------- +        +--------------------+

Perhatikan kini BJB juga listen di port 10001 untuk berkomunikasi dengan Agratek menggunakan ISO8583. Sehingga kini daemon bank mendapat julukan ISO8583 Forwarder. Di terminal ke-2 matikan daemon bank. Tambahkan di file test-bank.ini baris berikut ini:

[host_agratek]
ip = 127.0.0.1
port = 10001
listen = true
streamer = bjb
module = opensipkd.iso8583.bjb.pbb.test_aggregator
db_url = postgresql://user:pass@localhost/db
# Routing dari 4 digit awal InvoiceID
host =
  3271:kota_bogor
  3275:kota_bekasi

Meski ini hanya simulasi namun daemon bank membutuhkan database untuk pemetaan STAN (bit 11) payment request dari Agratek dengan STAN saat ke Pemda. Informasi ini digunakan saat reversal request. Kini buatlah tabelnya:

$ ~/env/bin/iso8583_bjb_pbb_test_aggregator_initdb

Hidupkan lagi daemon-nya:

$ ~/env/bin/iso8583 test-bank.ini

Selanjutnya kita siapkan daemon Agratek.

Aggregator

Dari sisi bank Agratek ini dikategorikan sebagai aggregator. Bila simulasi aplikasi teller sebelumnya menggunakan format JSON-RPC maka kali ini akan menggunakan format yang sudah ditentukan LinkAja. Siapkan terminal ke-3. Modul linkaja membutuhkan database untuk pencatatan transaksi. Buatlah database-nya terlebih dahulu. Lalu buatlah file test-agratek.ini:

[loggers]
keys = root, iso8583_web

[handlers]
keys = console, file

[formatters]
keys = generic

[logger_root]
level = DEBUG
handlers = console, file

[logger_iso8583_web]
level = DEBUG
handlers =
qualname = iso8583_web

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = DEBUG
formatter = generic

[handler_file]
class = FileHandler
args = ('/home/sugiana/log/agratek.log', 'a')
level = DEBUG
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)s %(message)s

[web]
port = 7001
threads = 12

[web_linkaja]
route_path = /linkaja
module = iso8583_web.scripts.views.linkaja
host = bjb
timeout = 30
db_url = postgresql://user:pass@localhost/db
allowed_ip =
    127.0.0.1
    10.8.30.1
# Notification Message sesuai prefix Invoice ID
notification_message =
    3271:PBB Kota Bogor
    3676:PBB Kota Tangerang Selatan
    3275:PBB Kota Bekasi

[host_bjb]
ip = 127.0.0.1
port = 10001
listen = false
timeout = 15
streamer = bjb
module = opensipkd.iso8583.bjb.pbb.agratek
request_bits =
    2:622011888888888888
    18:6025
    22:010
    32:015
    35:622011888888888888=9912?
    37:000000000000
    41:AGRATEK
    42:LINKAJA
    43:AGRATEK-LINKAJA
    49:360
    59:PAY
    60:123
    63:214

Buat tabelnya:

$ ~/env/bin/init_db_linkaja test-agratek.ini

Jalankan daemon-nya:

$ ~/env/bin/iso8583 test-agratek.ini

Restart daemon-nya. Buka terminal ke-4 dan coba inquiry:

$ ~/env/bin/iso8583_web_client_linkaja --url=http://127.0.0.1:7001/linkaja --invoice-id=3271010001007002701995

Hasilnya:

2020-07-19 06:17:17.944 Request: {'merchant': 'ldm***1', 'terminal': 'Terminal Name', 'pwd': 'ldm***ss', 'msisdn': '628111234567', 'acc_no': '3271010001007002701995', 'trx_date': '20200719061717', 'trx_type': '021'}
2020-07-19 06:17:18.604 Response 200: ['00:UW** *****SNA:19536:16:'] -> {'Response Code': '00', 'Biller Name': 'UW** *****SNA', 'Bill Amount': '19536', 'Bill Ref': '16', 'Notification Message': ''}
2020-07-19 06:17:18.609 thread 1 0.654482364654541 detik 00:UW** *****SNA:19536:16:
2020-07-19 06:17:18.609 Tidak ada yang gagal

Pastikan Response Code bernilai 00 yang menandakan tagihan siap dibayar. Lanjut --payment, kali ini sertakan --bill-ref dan --amount yang diperoleh dari inquiry response:

$ ~/env/bin/iso8583_web_client_linkaja --url=http://127.0.0.1:7000/linkaja --invoice-id=3271010001007002701995 --payment --bill-ref=16 --amount=19536

Hasilnya:

2020-07-19 06:21:00.333 Request: {'merchant': 'ldm***1', 'terminal': 'Terminal Name', 'pwd': 'ldm***ss', 'msisdn': '628111234567', 'acc_no': '3271010001007002701995', 'trx_date': '20200719062100', 'trx_type': '022', 'amount': 19536, 'bill_ref': '16', 'trx_id': '0719062100'}
2020-07-19 06:21:01.056 Response 200: ['00:010123882462:16:'] -> {'Response Code': '00', 'Transaction ID': '010123882462', 'Bill Ref': '16', 'Notification Message': ''}
2020-07-19 06:21:01.061 thread 1 0.717498779296875 detik 00:010123882462:16:
2020-07-19 06:21:01.061 Tidak ada yang gagal

Lagi, pastikan Response Code bernilai 00 yang berarti pembayaran berhasil. Lanjut coba reversal, kali ini sertakan --trx-id yang diperoleh dari payment request:

$ ~/env/bin/iso8583_web_client_linkaja --url=http://127.0.0.1:7000/linkaja --invoice-id=3271010001007002701995 --reversal --bill-ref=16 --amount=19536 --trx-id=0719062100

Hasilnya:

2020-07-19 06:25:13.546 Request: {'merchant': 'ldm***1', 'terminal': 'Terminal Name', 'pwd': 'ldm***ss', 'msisdn': '628111234567', 'acc_no': '3271010001007002701995', 'trx_date': '20200719062513', 'trx_type': '023', 'amount': 19536, 'bill_ref': '16', 'trx_id': '0719062100'}
2020-07-19 06:25:14.121 Response 200: ['00::16:'] -> {'Response Code': '00', 'Transaction ID': '', 'Bill Ref': '16', 'Notification Message': ''}
2020-07-19 06:25:14.126 thread 1 0.5694727897644043 detik 00::16:
2020-07-19 06:25:14.127 Tidak ada yang gagal

Pastikan Response Code bernilai 00 yang bermakna pembatalan pembayaran berhasil. Script ini juga menerima opsi --count untuk stress test.

Selamat mencoba.