Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Owo Sugiana
/
iso8583-web
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit db249bb3
authored
Feb 21, 2019
by
Owo Sugiana
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Thread web service yang sebenarnya
1 parent
1f950e88
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
277 additions
and
33 deletions
MANIFEST.in
README.rst
alembic/env.py
alembic/versions/074b33635316_alter_users_date_fields_with_time_zone.py
contrib/bank-teller.py
iso8583.ini
iso8583_web/read_conf.py
iso8583_web/scripts/forwarder.py
setup.py
MANIFEST.in
View file @
db249bb
include
*.txt *.ini *
.rst
recursive-include
web_starter *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak
include
CHANGES.txt production.ini development.ini README
.rst
recursive-include
iso8583_web *.py *.png *.css *.pt *.tpl *.mako
README.rst
View file @
db249bb
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 JsonRPC untuk melakukan inquiry, payment, dan reversal.
...
...
@@ -21,11 +20,8 @@ Salinlah file konfigurasi::
$ cp iso8583.ini test-pemda.ini
Sesuaikan isi section ``[host_bjb]``. Anda bisa menambahkan host lainnya baik
bank, pemda, bahkan payment gateway dengan menambahkan awalan ``host_`` pada
section.
Kemudian lakukan uji coba::
Sesuaikan isi section ``[host_bjb]``. Anda bisa menambahkan host lainnya
dengan menambahkan awalan ``host_`` pada section. Kemudian lakukan uji coba::
$ ../env/bin/pip install -e '.[testing]'
$ ../env/bin/pytest iso8583_web/test-conf.py
...
...
@@ -48,9 +44,6 @@ Biarkan ini aktif. Buka konsol lain. Sekarang kita buat simulator BJB::
Ubah file ``test-bjb.ini`` pada baris::
[web]
port = 6543
[host_bjb]
ip = 127.0.0.1
port = 10002
...
...
@@ -59,9 +52,6 @@ Ubah file ``test-bjb.ini`` pada baris::
menjadi::
[web]
port = 6544
[host_pemda]
ip = 127.0.0.1
port = 10002
...
...
@@ -71,3 +61,79 @@ menjadi::
Simpan, lalu jalankan::
../env/bin/iso8583 test-bjb.ini
Log File
--------
Untuk menyimpan log ke dalam file lakukan perubahan pada file konfigurasi (INI
file). Pada section ``[handlers]`` baris ``keys`` tambahkan ``file`` sehingga
menjadi::
[handlers]
keys = console, file
Pada section ``[logger_root]`` baris ``handlers`` tambahkan ``file`` sehingga
menjadi::
[logger_root]
level = INFO
handlers = console, file
Setelah section ``[handler_console]`` tambahkan section ``[handler_file]``
seperti ini::
[handler_file]
class = FileHandler
args = ('/home/sugiana/tmp/pemda.log', 'a')
level = NOTSET
formatter = generic
Lalu jalankan lagi daemon seperti di atas.
JsonRpc
-------
Ini adalah web service untuk memudahkan pembuatan client. Misalkan kita ingin
membuat aplikasi teller bank. Pada ``test-bjb.ini`` aktifkan section
``[web]``::
[web]
port = 7000
Kemudian restart daemon-nya. Setelah *echo established* dengan daemon pemda
lakukan *echo request* dengan cara::
$ ../env/bin/python contrib/bank-teller.py
Hasilnya menjadi seperti ini::
{'id': 0,
'jsonrpc': '2.0',
'result': {'code': 0,
'data': {'11': '163105',
'39': '00',
'7': '0221163106',
'70': '301'},
'message': 'OK'}}
JsonRpc Log File
----------------
Biasanya tahap awal pembuatan web client terjadi kesalahan yang tampak di
client namun tak nampak di log web server. Untuk mengatasi hal ini lakukan
penambahan di file konfigurasi section ``[loggers]`` menjadi seperti ini::
[loggers]
keys = root, iso8583_web, jsonrpc
Lalu tambahkan section ``[logger_jsonrpc]`` berikut ini::
[logger_jsonrpc]
level = DEBUG
handlers = console, file
qualname = pyramid_rpc.jsonrpc
Kemudian jalankan lagi daemon-nya. Misalkan client memanggil method ``eco``
yang seharusnya ``echo`` maka di log akan tampil seperti ini::
2019-02-21 14:00:47,135 DEBUG handling id:0 method:eco
2019-02-21 14:00:47,135 DEBUG json-rpc method not found rpc_id:0 "eco"
Semoga dipahami.
alembic/env.py
View file @
db249bb
...
...
@@ -64,6 +64,7 @@ def run_migrations_online():
with
context
.
begin_transaction
():
context
.
run_migrations
()
if
context
.
is_offline_mode
():
run_migrations_offline
()
else
:
...
...
alembic/versions/074b33635316_alter_users_date_fields_with_time_zone.py
View file @
db249bb
"""alter users date fields with time zone
Revision ID: 074b33635316
Revises:
Revises:
Create Date: 2018-10-11 12:00:48.568483
"""
...
...
@@ -17,13 +17,16 @@ depends_on = None
def
upgrade
():
op
.
alter_column
(
'users'
,
'last_login_date'
,
op
.
alter_column
(
'users'
,
'last_login_date'
,
type_
=
sa
.
DateTime
(
timezone
=
True
),
existing_type
=
sa
.
DateTime
(
timezone
=
False
))
op
.
alter_column
(
'users'
,
'registered_date'
,
op
.
alter_column
(
'users'
,
'registered_date'
,
type_
=
sa
.
DateTime
(
timezone
=
True
),
existing_type
=
sa
.
DateTime
(
timezone
=
False
))
op
.
alter_column
(
'users'
,
'security_code_date'
,
op
.
alter_column
(
'users'
,
'security_code_date'
,
type_
=
sa
.
DateTime
(
timezone
=
True
),
existing_type
=
sa
.
DateTime
(
timezone
=
False
))
...
...
contrib/bank-teller.py
0 → 100644
View file @
db249bb
import
requests
import
json
from
pprint
import
pprint
url
=
'http://localhost:7000/rpc'
headers
=
{
'content-type'
:
'application/json'
}
p
=
{
'host'
:
'pemda'
}
data
=
{
'method'
:
'echo'
,
'params'
:
[
p
],
'jsonrpc'
:
'2.0'
,
'id'
:
0
,
}
resp
=
requests
.
post
(
url
,
data
=
json
.
dumps
(
data
),
headers
=
headers
)
json_resp
=
resp
.
json
()
pprint
(
json_resp
)
iso8583.ini
View file @
db249bb
...
...
@@ -30,8 +30,10 @@ formatter = generic
[formatter_generic]
format
=
%(asctime)s %(levelname)s %(message)s
[web]
port
=
6543
# Aktifkan JsonRPC server jika ingin simulasi sebagai bank dimana inquiry dkk
# bisa dilakukan melalui JsonRPC client.
# [web]
# port = 7000
[host_bjb]
ip
=
127.0.0.1
...
...
iso8583_web/read_conf.py
View file @
db249bb
...
...
@@ -13,6 +13,7 @@ except ImportError:
listen_ports
=
[]
ip_conf
=
{}
name_conf
=
{}
allowed_ips
=
[]
web
=
{}
...
...
@@ -23,7 +24,7 @@ def get_conf(ip, port):
def
get_web_port
():
return
web
[
'port'
]
return
'port'
in
web
and
web
[
'port'
]
def
get_str
(
conf
,
section
,
option
,
default
):
...
...
@@ -94,7 +95,7 @@ def read_conf(conf_file):
cfg
=
dict
()
cfg
[
'ip'
]
=
ip
cfg
[
'port'
]
=
port
cfg
[
'name'
]
=
section
.
split
(
'_'
)[
1
]
cfg
[
'name'
]
=
name
=
section
.
split
(
'_'
)[
1
]
cfg
[
'streamer'
]
=
get_str
(
conf
,
section
,
'streamer'
,
'none'
)
cfg
[
'streamer_cls'
]
=
get_streamer_class
(
cfg
[
'streamer'
])
cfg
[
'module'
]
=
get_str
(
conf
,
section
,
'module'
,
'opensipkd.iso8583.network'
)
...
...
@@ -109,4 +110,4 @@ def read_conf(conf_file):
listen_ports
.
append
(
port
)
if
ip
not
in
allowed_ips
:
allowed_ips
.
append
(
ip
)
ip_conf
[
ip_port
]
=
dict
(
cfg
)
ip_conf
[
ip_port
]
=
name_conf
[
name
]
=
dict
(
cfg
)
iso8583_web/scripts/forwarder.py
View file @
db249bb
...
...
@@ -2,12 +2,15 @@ import os
import
sys
import
logging
import
signal
from
time
import
sleep
from
time
import
(
sleep
,
time
,
)
from
threading
import
Thread
from
wsgiref.simple_server
import
make_server
from
pyramid.config
import
Configurator
from
pyramid.response
import
Response
from
pyramid.paster
import
setup_logging
from
pyramid_rpc.jsonrpc
import
jsonrpc_method
from
opensipkd.tcp.connection
import
(
ConnectionManager
as
BaseConnectionManager
,
join_ip_port
,
...
...
@@ -21,6 +24,11 @@ from opensipkd.tcp.server import (
RequestHandler
as
BaseRequestHandler
,
)
from
opensipkd.tcp.client
import
Client
as
BaseClient
from
opensipkd.jsonrpc.exc
import
(
JsonRpcInvalidParams
,
JsonRpcBankNotFound
,
JsonRpcBillerNetwork
,
)
from
..read_conf
import
(
read_conf
,
ip_conf
,
...
...
@@ -28,6 +36,7 @@ from ..read_conf import (
listen_ports
,
allowed_ips
,
get_conf
,
name_conf
,
)
...
...
@@ -295,6 +304,15 @@ class Parser(Log):
self
.
log_encode
(
iso
)
raw
=
iso
.
getRawIso
()
self
.
connection
.
send
(
raw
)
else
:
# dapat response
ip_port
=
join_ip_port
(
self
.
conf
[
'ip'
],
self
.
conf
[
'port'
])
if
ip_port
in
web_process
:
stan_list
=
web_process
[
ip_port
]
stan
=
from_iso
.
get_stan
()
if
stan
in
stan_list
:
i
=
stan_list
.
index
(
stan
)
del
stan_list
[
i
]
append_web_response
(
ip_port
,
stan
,
from_iso
)
self
.
running
=
False
...
...
@@ -308,18 +326,139 @@ class ConnectionManager(BaseConnectionManager):
conn_mgr
=
ConnectionManager
()
#######
# Web #
#######
def
log_web_msg
(
s
):
return
'Web server {}'
.
format
(
s
)
def
log_web_info
(
s
):
msg
=
log_web_msg
(
s
)
log
=
get_log
()
msg
=
'Web server {}'
.
format
(
s
)
log
.
info
(
msg
)
def
hello_world
(
request
):
return
Response
(
'Hello World!'
)
def
log_web_error
(
s
):
msg
=
log_web_msg
(
s
)
log
=
get_log
()
log
.
error
(
msg
)
def
conn_by_name
(
name
):
conf
=
name_conf
[
name
]
found_conn
=
None
for
ip_port
,
conn
in
conn_mgr
:
ip
,
port
=
ip_port
.
split
(
':'
)
if
conf
[
'ip'
]
!=
ip
:
continue
port
=
int
(
port
)
if
conf
[
'port'
]
!=
port
:
continue
found_conn
=
conn
if
not
found_conn
:
raise
JsonRpcBankNotFound
()
if
not
found_conn
.
running
:
raise
JsonRpcBankNotFound
(
message
=
'Disconnected'
)
return
found_conn
# Daftar job dari web request, berisi iso request
# key: ip:port, value: list of iso
web_request
=
{}
# Daftar job yang sedang diproses, yaitu menunggu iso response
# key: ip:port, value: list of stan (bit 11)
web_process
=
{}
# Daftar job yang sudah selesai, berisi iso response
# key: ip:port, value: dict of (key: stan, value: iso)
web_response
=
{}
def
append_web_process
(
ip_port
,
iso
):
stan
=
iso
.
get_stan
()
if
ip_port
in
web_process
:
web_process
[
ip_port
]
.
append
(
stan
)
else
:
web_process
[
ip_port
]
=
[
stan
]
def
append_web_response
(
ip_port
,
stan
,
iso
):
if
ip_port
in
web_response
:
web_response
[
ip_port
][
stan
]
=
iso
else
:
web_response
[
ip_port
]
=
{
stan
:
iso
}
def
web_job
(
conn
,
iso
):
ip_port
=
join_ip_port
(
conn
.
conf
[
'ip'
],
conn
.
conf
[
'port'
])
if
ip_port
in
web_request
:
web_request
[
ip_port
]
.
append
(
iso
)
else
:
web_request
[
ip_port
]
=
[
iso
]
stan
=
iso
.
get_stan
()
awal
=
time
()
while
True
:
sleep
(
1
)
if
time
()
-
awal
>
5
:
raise
JsonRpcBillerNetwork
(
message
=
'Timeout'
)
if
ip_port
not
in
web_response
:
continue
result
=
web_response
[
ip_port
]
if
stan
in
result
:
iso
=
result
[
stan
]
del
result
[
stan
]
data
=
iso_to_dict
(
iso
)
return
dict
(
code
=
0
,
message
=
'OK'
,
data
=
data
)
def
validate_rpc
(
p
):
if
'host'
not
in
p
:
raise
JsonRpcInvalidParams
()
return
conn_by_name
(
p
[
'host'
])
def
log_web_receive
(
request
,
method
,
p
,
flow
=
'Receive'
):
msg
=
'{} {} {} {}'
.
format
(
request
.
client_addr
,
flow
,
method
,
p
)
log_web_info
(
msg
)
def
log_web_send
(
request
,
method
,
p
):
log_web_receive
(
request
,
method
,
p
,
'Send'
)
@jsonrpc_method
(
endpoint
=
'rpc'
)
def
echo
(
request
,
p
):
log_web_receive
(
request
,
'echo'
,
p
)
conn
=
validate_rpc
(
p
)
iso
=
conn
.
job
.
echo_request
()
r
=
web_job
(
conn
,
iso
)
log_web_send
(
request
,
'echo'
,
r
)
return
r
@jsonrpc_method
(
endpoint
=
'rpc'
)
def
inquiry
(
request
,
p
):
conn
=
validate_rpc
(
p
)
iso
=
conn
.
job
.
inquiry
(
p
)
return
web_job
(
conn
,
iso
)
@jsonrpc_method
(
endpoint
=
'rpc'
)
def
payment
(
request
,
p
):
conn
=
validate_rpc
(
p
)
iso
=
conn
.
job
.
payment
(
p
)
return
web_job
(
conn
,
iso
)
@jsonrpc_method
(
endpoint
=
'rpc'
)
def
reversal
(
request
,
p
):
conn
=
validate_rpc
(
p
)
iso
=
conn
.
job
.
reversal
(
p
)
return
web_job
(
conn
,
iso
)
web_server
=
{}
...
...
@@ -327,18 +466,24 @@ web_server = {}
def
start_web_server
():
port
=
get_web_port
()
if
not
port
:
return
with
Configurator
()
as
config
:
config
.
add_route
(
'hello'
,
'/'
)
config
.
add_view
(
hello_world
,
route_name
=
'hello'
)
config
.
include
(
'pyramid_tm'
)
config
.
include
(
'pyramid_rpc.jsonrpc'
)
config
.
add_jsonrpc_endpoint
(
'rpc'
,
'/rpc'
)
config
.
scan
(
__name__
)
app
=
config
.
make_wsgi_app
()
web_server
[
'listener'
]
=
server
=
make_server
(
'0.0.0.0'
,
port
,
app
)
web_server
[
'thread'
]
=
Thread
(
target
=
server
.
serve_forever
)
web_server
[
'thread'
]
=
create_thread
(
server
.
serve_forever
)
web_server
[
'thread'
]
.
start
()
ip_port
=
web_server
[
'listener'
]
.
server_address
log_web_info
(
'listen at {}:{}'
.
format
(
*
ip_port
))
def
stop_web_server
(
reason
):
if
'listener'
not
in
web_server
:
return
msg
=
'stop because {}'
.
format
(
reason
)
log_web_info
(
msg
)
# shutdown() ini kadang tidak segera mengakhiri web server. Akan cepat
...
...
@@ -401,7 +546,14 @@ def check_job():
continue
iso
=
connection
.
job
.
get_iso
()
if
not
iso
:
continue
if
ip_port
not
in
web_request
:
continue
jobs
=
web_request
[
ip_port
]
if
not
jobs
:
continue
iso
=
jobs
[
0
]
del
jobs
[
0
]
append_web_process
(
ip_port
,
iso
)
connection
.
log_encode
(
iso
)
raw
=
iso
.
getRawIso
()
connection
.
send
(
raw
)
...
...
setup.py
View file @
db249bb
...
...
@@ -30,12 +30,14 @@ requires = [
'pyramid_beaker'
,
'pyramid_mailer'
,
'requests'
,
'pyramid_rpc'
,
]
customs_require
=
[
'http://repo.opensipkd.com/pip/opensipkd-base-0.2.tar.gz'
,
'http://repo.opensipkd.com/pip/opensipkd-hitung-0.1.tar.gz'
,
'http://repo.opensipkd.com/pip/opensipkd-iso8583-0.1.tar.gz'
,
'http://repo.opensipkd.com/pip/opensipkd-jsonrpc-0.1.tar.gz'
,
]
tests_require
=
[
...
...
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment