Commit 65d347e1 by Solo Group

init

0 parents
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
env2/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
inventori/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# bat file
*.bat
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
*.ini
.idea/
.project/
.DS_Store
20-07-2018 Initialil Beta 0.1.0
File mode changed
include *.txt *.ini *.cfg *.rst
recursive-include opensipkdrpc *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
Aplikasi Agratek API MERCHANT
=============================
api-merchant ini adalah apliksi untuk integrasi dengan merchant:. Berikut cara
pemasangannya:
1. Requirement::
http://git.opensipkd.com/pasar/base.git
2. Instalasi dengan menggunakan ``pip``::
$ ./env/bin/pip install git+http://git.opensipkd.com/pasar/api-merchant.git
3. Instalasi dengan git::
$ mkdir apps
$ cd apps
$ git clone http://git.opensipkd.com/pasar/api-merchant.git
$ cd api-merchant
$ ~/env/bin/python setup.py develop-use-pip
4. Sesuaikan konfigurasi pada baris berikut ini::
modules = opensipkd.api.merchant
5. Initialize tabel::
$ ../env/bin/initialize_api_merchant_db live.ini
6. Jalankan daemon-nya::
$ ../env/bin/pserve --reload live.ini
Paket Pendukung
---------------
sudo apt-get install libxml2-dev libxslt1-dev libtiff4-dev libjpeg8-dev
sudo apt-get install zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev
[alembic]
script_location = alembic
sqlalchemy.url = {{db_url}}
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = alembic
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
# max length of characters to apply to the
# "slug" field
#truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version location specification; this defaults
# to alembic/versions. When using multiple version
# directories, initial revisions must be specified with --version-path
# version_locations = %(here)s/bar %(here)s/bat alembic/versions
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
sqlalchemy.url = {{db_url}}
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
20 JanuaryChange Project Structure
+opensipkd
+--api
+--views
+--models
+--reports
+--tools
+--statics
+--scripts
15-Nov Pemindahan Departemen dan Partner dari Core ke opensipkd
5-november-2018
Penambahan fungsi request._host
[nosetests]
match = ^test
nocapture = 1
cover-package = opensipkd
with-coverage = 1
cover-erase = 1
[compile_catalog]
directory = opensipkd/locale
domain = opensipkd
statistics = true
[extract_messages]
add_comments = TRANSLATORS:
output_file = opensipkd/locale/opensipkd.pot
width = 80
mapping_file = message-extraction.ini
[init_catalog]
domain = opensipkd-rpc
input_file = opensipkdrpc/locale/opensipkd-rpc.pot
output_dir = opensipkdrpc/locale
[update_catalog]
domain = opensipkd-rpc
input_file = opensipkd/locale/opensipkd-rpc.pot
output_dir = opensipkd/locale
previous = true
import os
import sys
import subprocess
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.txt')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires=[
"opensipkd.base",
"opensipkd.pasar.models"
]
dev_requires = [
'pyramid_debugtoolbar',
'pytest',
]
if sys.argv[1:] and sys.argv[1] == 'develop-use-pip':
bin_ = os.path.split(sys.executable)[0]
pip = os.path.join(bin_, 'pip')
for package in requires:
cmd = [pip, 'install', package]
subprocess.call(cmd)
cmd = [sys.executable, sys.argv[0], 'develop']
subprocess.call(cmd)
sys.exit()
setup(
name='agratek.api.merchant',
version='0.1.0',
url='',
license='',
description='Api Merhant PasarQu',
long_description=README + '\n\n' + CHANGES,
author='',
author_email='',
classifiers=[
"Programming Language :: Python",
"Framework :: Pylons",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
keywords='web pyramid pylons',
package = find_packages('src'),
package_dir={'': 'src'},
# namespace_packages=['opensipkd',],
include_package_data=True,
zip_safe=False,
install_requires=requires,
tests_require=requires,
extras_require={
'dev': dev_requires,
},
test_suite="agratek.api.merchant.test",
entry_points="""\
[console_scripts]
initialize_agratek_api_merchant_db = agratek.api.merchant.scripts.initializedb:main
""",
)
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
\ No newline at end of file
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
\ No newline at end of file
def main(config, **settings):
pass
from opensipkd.base.models import *
from opensipkd.pasar.models import *
kode,path,nama,status,type
api-merchant,/api/merchant,Api Merchant,1,1
api-vendor-notify,/api/vendor/{name}/notify,Api Vendor Notify,1,0
api-merchant-list,/api/merchant/list,Test Api Merchant,1,0
api-merchant-add,/api/merchant/add,Add Api Merchant,1,0
api-merchant-edit,/api/merchant/{id}/edit,Edit Api Merchant,1,0
api-merchant-delete,/api/merchant/{id}/delete,Delete Api Merchant,1,0
api-merchant-view,/api/merchant/{id}/view,View Api Merchant,1,0
api-merchant-doc,/api/merchant/doc,Doc Api Merchant,1,0
api-vendor-list,/api/vendor/list,Test Api Vendor,1,0
api-vendor-add,/api/vendor/add,Add Api Vendor,1,0
api-vendor-edit,/api/vendor/{id}/edit,Edit Api Vendor,1,0
api-vendor-delete,/api/vendor/{id}/delete,Delete Api Vendor,1,0
api-vendor-view,/api/vendor/{id}/view,View Api Vendor,1,0
api-vendor-doc,/api/vendor/doc,Doc Api Vendor,1,0
api-vendor-test,/api/vendor/{vendor}/test,Test Api Vendor,1,0
import os
import transaction
import sys
import subprocess
from sqlalchemy import (
engine_from_config,
)
from pyramid.paster import (
get_appsettings,
setup_logging,
)
from opensipkd.base.models import (DBSession as ModuleDBSession, Base as ModuleBase)
from opensipkd.base.scripts.initializedb import append_csv, read_file, reset_sequences, create_schema
from opensipkd.base.models import Route
def get_file(filename):
base_dir = os.path.split(__file__)[0]
fullpath = os.path.join(base_dir, 'data', filename)
return open(fullpath)
def usage(argv):
pass
def main(argv=sys.argv):
def alembic_run(ini_file, url):
s = read_file(ini_file)
s = s.replace('{{db_url}}', url)
f = open('alembic.ini', 'w')
f.write(s)
f.close()
subprocess.call(command)
os.remove('alembic.ini')
if len(argv) != 2:
usage(argv)
config_uri = argv[1]
setup_logging(config_uri)
settings = get_appsettings(config_uri)
bin_path = os.path.split(sys.executable)[0]
alembic_bin = os.path.join(bin_path, 'alembic')
command = (alembic_bin, 'upgrade', 'head')
alembic_run('alembic.ini.tpl', settings['sqlalchemy.url'])
alembic_run('alembic_upgrade.ini.tpl', settings['sqlalchemy.url'])
engine = engine_from_config(settings, 'sqlalchemy.')
ModuleDBSession.configure(bind=engine)
# init_model()
ModuleBase.metadata.bind = engine
# create_schema(engine, 'pasar')
ModuleBase.metadata.create_all()
reset_sequences()
print('>>Append Table')
append_csv(Route, 'routes.csv', ['kode'], get_file_func=get_file, update_exist=True)
transaction.commit()
print('>>Appended')
print('****API CREATED****')
from opensipkd.base.tools.api import *
from opensipkd.base.tools.buttons import *
from opensipkd.base.tools import *
\ No newline at end of file
from opensipkd.base.models import Departemen, User
from opensipkd.base.tools.api import auth_from_rpc, check_token_rpc, update_token, JsonRpcParameterNotFound
from pyramid_rpc.jsonrpc import jsonrpc_method
from opensipkd.pasar.models import DepartemenProduk, Produk, PartnerProduk
from opensipkd.pasar.models import ProdukCategory
from opensipkd.base.views import BaseView
@jsonrpc_method(method='get_product', endpoint='api-merchant')
def get_product(request, token, data ):
"""
Digunakan untuk mendapatkan daftar produk
:param request:
:param data:
{
product_kd: string, //optional
page:integer, //optional
length:integer, //optional
category:string, //optional
search:string //optional
}
:return: [
{
product_kd:string,
product_nm:string,
harga:integer
}
]
"""
auth_from_rpc(request)
i =0
qry = DepartemenProduk.query() \
.filter(Departemen.kode == '100000')
for dat in data:
page = 'page' in dat and dat['page'] or 1
length = 'length' in dat and dat['length'] or 5
product_kd = 'product_kd' in dat and dat['product_kd'] or None
search = 'search' in dat and dat['search'] or None
category = 'category' in dat and dat['category'] or None
if product_kd :
rst = qry.join(Produk).filter(Produk.kode == product_kd)
elif search:
rst = qry.join(Produk).filter(Produk.nama.ilike("".join(['%',search,'%' ])))
elif category:
rst = qry.join(Produk).join(ProdukCategory) \
.filter(ProdukCategory.nama.ilike("".join(['%',category,'%' ])))
else:
rst = qry
rst = rst.limit(length).offset((page-1)*length)
result = []
for row in rst.all():
result.append(dict(product_kd=row.produk.kode,
produk_nm=row.produk.nama,
harga=row.harga ))
r_data = dat
r_data.update(dict(data=result))
data[i]=r_data
i += 1
return data
@jsonrpc_method(method='get_biaya', endpoint='api-merchant')
def get_biaya(request, data, token=None):
"""
Digunakan untuk mencari methode pembayaran dan biaya layanan
:param request:
:param data:
{
biaya_kd: string,
harga:integer,
cname:string,
cid:string,
cvv:string, optional
}
:param token:
user_token
:return:
{
product_kd:string,
product_nm:string,
harga:integer
}
"""
user = auth_from_rpc(request, token)
i =0
qry = DepartemenProduk.query() \
.filter(Departemen.kode == '100000')
for dat in data:
product_kd = 'biaya_kd' in dat and dat['biaya_kd'] or None
cid = 'cid' in dat and dat['cid'] or None
if not product_kd :
raise JsonRpcParameterNotFound(message='Paramter product_kd wajib di isi')
rst = qry.join(Produk).filter(Produk.kode == product_kd)
result = []
for row in rst.all():
if row.is_cid and not cid:
raise JsonRpcParameterNotFound(message="Parameter cid wajib di isi")
if row.produk.fixed:
harga = row.harga
else:
harga = dat['harga']*row.harga
result.append(dict(biaya_kd=row.produk.kode,
produk_nm=row.produk.nama,
harga=harga))
r_data = dat
r_data.update(dict(data=result))
data[i]=r_data
i += 1
return data
@jsonrpc_method(method='inquiry', endpoint='api-merchant')
def inquiry(request, token, data ):
"""
Digunakan untuk mendapatkan daftar produk
:param request:
:param data:
{
product_kd: string, //optional
cid:string //optional
}
:param token:
user_token
:return:
{
product_kd:string,
product_nm:string,
harga:integer,
admin:integer,
discount:integer
}
"""
auth_from_rpc(request)
i =0
qry = DepartemenProduk.query() \
.filter(Departemen.kode == '100000')
dat = data and data is list and data[0] or data
for dat in data:
product_kd = 'product_kd' in dat and dat['product_kd'] or None
cid = 'cid' in dat and dat['cid'] or None
if not product_kd :
raise JsonRpcParameterNotFound(message='Paramter product_kd wajib di isi')
rst = qry.join(Produk).filter(Produk.kode == product_kd)
result = []
for row in rst.all():
if row.is_cid and not cid:
raise JsonRpcParameterNotFound(message="Parameter cid wajib di isi")
result.append(dict(product_kd=row.produk.kode,
produk_nm=row.produk.nama,
harga=row.harga ))
r_data = dat
r_data.update(dict(data=result))
data[i]=r_data
i += 1
return data
@jsonrpc_method(method='payment', endpoint='api-merchant')
def payment(request, token, data):
"""
Digunakan untuk mendapatkan daftar produk
:param request:
:param data:
{
product_kd: string,
cid:string
payment_kd: string optional
}
:param token:
user_token
:return:
{
product_kd:string,
product_nm:string,
harga:integer,
admin:integer,
discount:integer
}
"""
auth_from_rpc(request, token)
i = 0
qry = DepartemenProduk.query() \
.filter(Departemen.kode == '100000')
dat = data and data is list and data[0] or data
for dat in data:
product_kd = 'product_kd' in dat and dat['product_kd'] or None
cid = 'cid' in dat and dat['cid'] or None
if not product_kd:
raise JsonRpcParameterNotFound(message='Paramter product_kd wajib di isi')
rst = qry.join(Produk).filter(Produk.kode == product_kd)
result = []
for row in rst.all():
if row.is_cid and not cid:
raise JsonRpcParameterNotFound(message="Parameter cid wajib di isi")
result.append(dict(product_kd=row.produk.kode,
produk_nm=row.produk.nama,
harga=row.harga))
r_data = dat
r_data.update(dict(data=result))
data[i] = r_data
i += 1
return data
# """
# Module proses:
# Save
# Invoice To Vendor
# Invoice To Customer
# """
# import os
# import re
# from datetime import datetime
#
# import colander
# import requests
# from deform import FileData, widget, Form, ValidationFailure
# from pyramid.httpexceptions import HTTPFound
# from pyramid.renderers import render_to_response
# from pyramid.view import view_config
#
# from . import BaseView #, save_file_upload
# from ..models import (DBSession, flush_row, save_row, Partner)
# from ..models import (Produk, ProdukCategory)
#
# from ..tools import (btn_next, date_from_str, get_ext,
# btn_save, btn_cancel, get_settings, btn_reset,
# dmy, btn_upload, btn_inquiry, btn_advice, btn_payment, get_random_number)
#
#
# def vendor():
# return DBSession.query(Partner.id, Partner.nama)\
# .filter(Partner.is_vendor == 1).all()
#
# def customer():
# return DBSession.query(Partner.id, Partner.nama)\
# .filter(Partner.is_customer == 1).all()
#
# def produk():
# return DBSession.query(Produk.id, Produk.nama)\
# .join(ProdukCategory, Produk.kategori_id==ProdukCategory.id)\
# .filter(ProdukCategory.kode.in_('e-pulsa', 'e-voucher', 'e-payment')).all()
#
#
# @colander.deferred
# def deferred_vendor(node, kw):
# values = kw.get('vendor', [])
# return widget.SelectWidget(values=values)
#
#
# @colander.deferred
# def deferred_customer(node, kw):
# values = kw.get('customer', [])
# return widget.SelectWidget(values=values)
#
#
# @colander.deferred
# def deferred_produk(node, kw):
# values = kw.get('produk', [])
# return widget.SelectWidget(values=values)
#
#
# class PageSchema(colander.Schema):
# customer_id = colander.SchemaNode(
# colander.Integer(), title='Customer',
# oid="customer_id", widget=deferred_customer)
#
# produk_id = colander.SchemaNode(
# colander.Integer(), title='Produk',
# oid="produk_id", widget=deferred_produk)
#
# destination = colander.SchemaNode(
# colander.Integer(), title='No.Tujuan/ID Pelanggan',
# oid="destination", widget=widget.TextInputWidget())
#
# vendor_id = colander.SchemaNode(
# colander.Integer(), title='Vendor',
# oid="vendor_id", widget=deferred_produk)
# trx_id = colander.SchemaNode(
# colander.Integer(), title='TRX ID',
# missing=colander.drop,
# oid="trx_id",
# # widget=widget.HiddenWidget()
# )
#
#
# class PageEditSchema(PageSchema):
#
# id = colander.SchemaNode(
# colander.Integer(), title='ID',
# missing=colander.drop,
# oid="id", widget=widget.HiddenWidget())
#
#
# def form_validator(form, value):
# pass
#
#
# def get_form(request, class_form, buttons=None, row=None):
# schema = class_form(validator=form_validator)
# schema = schema.bind(customer=customer(),
# vendor=vendor())
# schema.request = request
# if row:
# schema.deserialize(row)
# if not buttons:
# buttons = (btn_inquiry, btn_reset)
# return Form(schema, buttons=buttons)
#
#
# def upload_form(request, values, form):
# docs = PartnerDocs.query() \
# .filter(PartnerDocs.partner_id == values['partner_id'])
# uploads = []
# preview_url = "{host}/simkel/api_download?partner_id={partner_id}&jdoc_id={jdoc_id}"
# for doc in docs:
# uploads.append(dict(jdoc_id=doc.jdoc_id,
# upload=dict(filename=doc.doc_name,
# uid=doc.id, )))
#
# values['uploads'] = uploads
# form = form.render(values)
# return render_to_response('templates/form-upload.pt', dict(form=form),
# request=request)
#
#
# def route_list(request):
# return HTTPFound(location=request.route_url('simkel-permohonan'))
#
#
# def save(values, row):
# if not row:
# row = Penduduk()
# kode = re.sub("\D", "", values["kode"])
# values['kode'] = kode
# values['is_vendor'] = 0
# values['is_customer'] = 1
# row.create_uid = values['uid']
# row.created = datetime.now()
# else:
# row.update_uid = values['uid']
# row.updated = datetime.now()
#
# row.from_dict(values)
# flush(row)
# return row
#
#
# def save_permohonan(values, partner, row=None):
# if not row:
# row = Permohonan()
# row.partner_id = partner.id
# row.jenis_id = values['jenis_id']
# row.tgl_permohonan = datetime.now()
# row.create_uid = values['uid']
# row.created = datetime.now()
# else:
# row.update_uid = values['uid']
# row.updated = datetime.now()
#
# flush(row)
# return row
#
#
# def save_request(request, values, row=None):
# values['tgl_lahir'] = date_from_str(values['tgl_lahir'])
# values['uid'] = request.user.id
# row = save(values, row)
# row_permohonan = Permohonan.query(). \
# filter(Permohonan.partner_id == row.id,
# Permohonan.status == 0,
# Permohonan.jenis_id == values['jenis_id']). \
# first()
# if not row_permohonan:
# row_permohonan = save_permohonan(values, row)
#
# request.session.flash('Data %s Berhasil disimpan' % values['nama'])
# return row_permohonan
#
#
# form_params_edit = dict(scripts="""
# $(document).ready(function(){
# $(".tanggal").datepicker({format:"dd-mm-yyyy"});
# $(".tanggal").attr("readonly", true);
#
# });
# """)
#
# form_params_view = dict(scripts="""
# $(document).ready(function(){
# $("#nip_penerima, #nopel").attr("readonly", true);
# });
# """)
#
#
# def query_id(request):
# id = request.matchdict['id']
# return ApInvoice.query_id(id)
#
#
# class ViewHome(BaseView):
# @view_config(route_name='api-merchant-doc',
# permission="api-merchant-doc",
# renderer='templates/merchan_doc.pt')
# def view_merchant_doc(self):
# return dict()
#
# @view_config(route_name='api-merchant-add',
# permission="api-merchant-add",
# renderer='templates/form.pt')
# def view_home(self):
# request = self.req
# session = self.ses
# form = get_form(request, PageSchema, (btn_inquiry, btn_payment, btn_advice, btn_next))
# form_params = dict(scripts=None)
# settings = get_settings()
# if request.POST:
# if 'inquiry' in request.POST:
# controls = request.POST.items()
# try:
# c = form.validate(controls)
# except ValidationFailure as e:
# form.set_appstruct(e.cstruct)
# return dict(form=form, params=form_params)
#
# values = dict(c.items())
# values['trx_id'] = get_random_number(10)
# form.render(values)
# return dict(form=form, params=form_params)
#
#
# # values = dict(partner_id=71)
# # return upload_form(request, values)
# return dict(form=form, params=form_params)
import base64
import json
import requests
from opensipkd.base import get_settings
from opensipkd.base.models import Partner
from opensipkd.pasar.models import PartnerProduk, Produk, PartnerLog, flush_row
from pyramid.view import view_config
from pyramid_rpc.jsonrpc import JsonRpcError
from .vendor import VendorClass
class Vendor(VendorClass):
def __init__(self, product_kd, cid):
VendorClass.__init__(self, product_kd, cid)
settings = get_settings()
self.mid = 'odeoo_cid' in settings and settings['odeo_cid'] or None
self.key = 'odeoo_key' in settings and settings['odeoo_key'] or None
self.url = 'odeoo_url' in settings and settings['odeoo_url'] or None
self.cid = cid
key = ":".join([self.cid, self.key])
self.auth = base64.b64encode(key)
qry = PartnerProduk.query()\
.join(Partner, Partner.id==PartnerProduk.partner_id)\
.join(Produk, Produk.id==PartnerProduk.produk_id)\
.filter(Produk.kode == product_kd,
Partner.kode == "odeoo")
row = qry.first()
self.product_kd = row and row.kode or None
def inquiry(self):
pass
def payment(self):
# request = Request('https://api.odeo.co.id/v1/affiliate/prepaid/purchase', data=values, headers=headers)
#
# response_body = urlopen(request).read()
# print
# response_body
#
"""
Digunakan untuk melakukan inquory ke server odeoo
:return:
"""
if not self.product_kd or not self.cid:
return
params = dict(
data=dict(
denom=self.product_kd,
number=self.cid
)
)
with requests.session():
headers = {'Authorization': 'Bearer {key}'.format(key=self.key)}
resp = requests.post(url=self.url, data=json.dump(params, None),
verify=False, headers=headers)
content = resp.json()
if resp != "200":
raise JsonRpcError(data=content)
return content
return
<html metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<style>
button {
margin:0px 3px;
}
#main{min-height: 1px;
padding-bottom: 1px;}
</style>
</div>
<div metal:fill-slot="scripts">
<div class="panel-body col-md-12">
<div class="col-md-8 col-md-offset-3 col-xs-12 well">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">ADDITIONAL</h3>
<h3 class="panel-title">SISTEM INFORMASI KELURAHAN</h3>
<h5 class="panel-title">Version Beta 0.1</h5>
</div>
</div>
</div>
</div>
</div>
</html>
<html metal:use-macro="load: opensipkd.base:views/templates/base3-no-menu.pt">
</html>
<html metal:use-macro="load: opensipkd.base:views/templates/base3.pt">
<ul metal:fill-slot="navs">
<li>
<a href="${request._host}/api/merchant/add">
<i class="fa fa-lg fa-fw fa-home"></i>
<span class="menu-item-parent">Add Merchant Invoice</span>
</a>
</li>
<li>
<a href="${request._host}/api/merchant/list">
<i class="fa fa-lg fa-fw fa-home"></i>
<span class="menu-item-parent">List Merchant Invoice</span>
</a>
</li>
<li>
<a href="${request._host}/api/vendor/add">
<i class="fa fa-lg fa-fw fa-home"></i>
<span class="menu-item-parent">Add Vendor Invoice</span>
</a>
</li>
<li>
<a href="${request._host}/api/vendor/list">
<i class="fa fa-lg fa-fw fa-home"></i>
<span class="menu-item-parent">List Vendor Invoice</span>
</a>
</li>
</ul>
</html>
<html metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">${request.title}</h3>
</div>
<div class="panel-body">
<div tal:content="structure form"/>
</div>
</div>
</div>
</html>
\ No newline at end of file
<html metal:use-macro="load: opensipkd.base:views/templates/base3.1.pt">
<div metal:fill-slot="content">
<div id="content">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">${request.title}</h3>
</div>
<div class="panel-body">
<div tal:content="structure form"/>
</div>
</div>
</div>
</div>
<div metal:fill-slot="scripts">
<div id="main2" role="main">
</div>
</div>
</html>
\ No newline at end of file
<html metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<style>
button {
margin:0px 3px;
}
#main{min-height: 1px;
padding-bottom: 1px;}
</style>
</div>
<div metal:fill-slot="scripts">
<div class="panel-body col-md-12">
<div class="col-md-6 col-md-offset-3 col-xs-12 well">
<!-- Proses Template Form -->
<form method="post" accept-charset="utf-8" id="deform" class="form-horizontal"
enctype="multipart/form-data" tal:define="field form"
style="background-color:white;"
autocomplete="off">
<input type="hidden" name="_charset_">
<input type="hidden" value="deform" name="__formid__">
<!-- Tampilan untuk general error -->
<div class="alert alert-danger" tal:condition="field.error">
<div class="errorMsgLbl" i18n:translate="">
Terdapat kesalahan pengisian
</div>
<p class="errorMsg">${field.errormsg}</p>
</div>
<!-- END Tampilan untuk general error -->
<div class="col-md-12">
<!-- Looping Semua Field-->
<div tal:repeat="f form">
<div tal:condition="f.widget.hidden">
<!-- Proses Saat Field hidden-->
${structure:f.serialize()}
</div>
<div tal:condition="not f.widget.hidden and not f.children"
class="form-group" >
<!-- Proses Saat Field Normal dan bukan Children-->
<!-- Field Reqired menggunakan class required -->
<label for="${f.oid}"
class="control-label col-md-4 ${f.required and 'required' or ''}"
id="req-${f.oid}">
${f.title}</label>
<div class="col-md-8">
${structure:f.serialize()}
<p tal:condition="f.error" id="error-${f.oid}" class="help-block"
tal:repeat="error f.error.messages()">
${error}</p>
</div>
</div>
<div tal:condition="f.children and f.name=='upload_files'">
<!-- Proses saat Form Adalah File Upload-->
${f.start_sequence()}
${structure:f.serialize()}
${f.end_sequence()}
</div>
<div tal:condition="f.children and f.name!='upload_files'">
<!-- Proses saat Form Adalah Children -->
${f.start_mapping()}
<div tal:repeat="g f.children" class="form-group" >
<label for="${g.oid}"
class="control-label col-md-4 ${g.required and 'required' or ''}"
id="req-${g.oid}">
${g.title}</label>
<div class="col-md-8">
${structure:g.serialize()}
<p tal:condition="g.error" id="error-${g.oid}" class="help-block"
tal:repeat="error g.error.messages()">
${error}</p>
</div>
</div>
${f.end_mapping()}
</div>
</div>
<div class="input-group-btn">
<button tal:repeat="fb form.buttons" type="${fb.type}"
class="btn ${fb.css_class} pull-right"
name="${fb.name}">${fb.title}</button>
</div>
</div>
</form>
<!-- End Template Form -->
<!-- </div> -->
</div>
</div>
<script>
${params.scripts}
</script>
</div>
</html>
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<!--<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">-->
<title>${request.app_name} | ${request.company}</title>
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- GOOGLE FONT -->
<link rel="stylesheet" href="${request._host}/static/v3/css/gf_open_sans-400italic_700italic_300_400_700.css">
<!-- Basic Styles -->
<link rel="stylesheet" type="text/css" media="screen" href="${request._host}/static/v3/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${request._host}/static/v3/css/font-awesome.min.css">
<!-- SmartAdmin Styles : Caution! DO NOT change the order -->
<link rel="stylesheet" type="text/css" media="screen" href="${request._host}/static/v3/css/smartadmin-production-plugins.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${request._host}/static/v3/css/smartadmin-production.min.css">
<link rel="stylesheet" type="text/css" media="screen" href="${request._host}/static/v3/css/smartadmin-skins.min.css">
<!-- We recommend you use "your_style.css" to override SmartAdmin
specific styles this will also ensure you retrain your customization with each SmartAdmin update. -->
<link rel="stylesheet" type="text/css" media="screen" href="${request._host}/static/v3/css/osipkd.css">
<!-- FAVICONS -->
<link rel="shortcut icon" href="${request._host}/static/v3/img/favicon.png" type="image/x-icon">
<link rel="icon" href="${request._host}/static/v3/img/favicon.png" type="image/x-icon">
<!-- OTHER CSS -->
<link href="${request._host}/static/v3/js/plugin/bootstrap-datepicker/css/bootstrap-datepicker.min.css" rel="stylesheet">
<link href="${request._host}/deform_static/css/form.css" rel="stylesheet">
<link href="${request._host}/deform_static/css/typeahead.css" rel="stylesheet">
<link href="${request._host}/static/css/custom.css" rel="stylesheet" type="text/css">
<link href="${request._host}/static/v3/css/select2.min.css" rel="stylesheet" type="text/css">
<metal:css define-slot="css_files"></metal:css>
</head>
<body class="fixed-header">
Sistem Informasi Kelurahan<br>
Version Beta 0.1<br>
(c) Copyright ${request.company} 2019
</body>>
</html>
<html metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<style>
button {
margin:0px 3px;
}
#main{min-height: 1px;
padding-bottom: 1px;}
</style>
</div>
<div metal:fill-slot="scripts">
<div class="panel-body col-md-12">
<div class="col-md-8 col-md-offset-3 col-xs-12 well">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">SISTEM INFORMASI KELURAHAN</h3>
<h5 class="panel-title">Version Beta 0.1</h5>
</div>
</div>
</div>
</div>
</div>
</html>
<html metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<style>
button {
margin:0px 3px;
}
#main{min-height: 1px;
padding-bottom: 1px;}
</style>
</div>
<div metal:fill-slot="scripts">
<div class="panel-body col-md-12">
<div class="col-md-8 col-md-offset-3 col-xs-12 well">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">SISTEM INFORMASI KELURAHAN</h3>
</div>
</div>
</div>
</div>
</div>
</html>
<div metal:use-macro="load: base.pt">
<!-- content -->
<div metal:fill-slot="content">
<div class="jarviswidget" style="border-top:1px solid #ccc!important">
<div role="content">
<table id="table1" class="table table-bordered table-hover table-condensed">
<thead>
<tr>
<th tal:repeat="f params.columns">${f.title}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<table tal:condition="'spm_kode' in request.session">
<tr>
<th>SPM</th>
</tr>
<tr>
<td>${request.session['spm_kode']}</td>
</tr>
</table>
</div>
<!-- end content -->
<script type="text/javascript" metal:fill-slot="scripts">
var mID;
var oTable;
var oTableUri = "${request._host}${params.route}"
var oTableUrl = oTableUri + "/grid/act";
$(document).ready(function() {
oTable = $('#table1').DataTable({
dom: '<"row"<"col-md-8"<"toolbar">l><"col-md-4"f>>rtip',
processing: true,
serverSide: true,
ajax: oTableUrl,
stateSave: true,
//scrollCollapse: true,
//sort: true,
//info: false,
filter: true,
autoWidth: false,
paginate: true,
paginationType: "full_numbers",
lengthMenu: [
[10, 25, 50, 100],
[10, 25, 50, 100]
],
columns: ${params.column_data},
columnDefs: [{
searchable: false,
visible: false,
targets: [0]
}],
"language": {
"search": "Cari : ",
"paginate": {
"first": "Pertama ",
"last": "Akhir ",
"previous": "",
"next": "",
},
"lengthMenu": "Tampil _MENU_ baris "
},
});
var buttons=${params.buttons};
var tb_array=[];
tb_array.push('<div class="btn-group pull-left">');
for (i=0; i<buttons.length; i++){
tb_array.push('<button id="'+buttons[i].id+'" class="' +buttons[i].cls+
'" type="button">'+buttons[i].title+'</button>')
}
tb_array.push(' &nbsp;');
tb_array.push('</div>');
var tb = tb_array.join(' ');
$("div.toolbar").html(tb);
$("div.toolbar").attr('style', 'display:block; float: left; margin-bottom:6px; line-height:16px;');
//events
$('#table1 tbody').on('click', 'tr', function() {
if ($(this).hasClass('selected')) {
$(this).removeClass('selected');
} else {
var aData = oTable.row(this).data();
oTable.$('tr.selected').removeClass('selected');
$(this).addClass('selected');
mID = aData.id;
console.log(mID);
oTable.$('tr.row_selected').removeClass('row_selected');
$(this).addClass('row_selected');
/*oTable2.fnReloadAjax("egaji/grid2?id=" + mID);*/
}
});
${params.scripts}
});
</script>
</div>
<html metal:use-macro="load: base.pt">
<div metal:fill-slot="content">
<div class="well">
<h1>Web Service SP2D ${request.company} </h1>
<p><img src="${request._host}/static/img/logo.png" class="img-float img-thumbnail"/>
Selamat datang di module <code>Web Service SP2D</code> ${request.company} module ini di desain untuk
untuk mengekspose methode yang diperlukan untuk System Informasi Lain dalam Menerima atau Mengirim data.
Web Service Sangat Bergunakan seingga interopabilitas system sehingga antar system yang
berbeda bahasa pemrograman maupun database dapat saling berkomunikasi.
<h3>Spesifikasi system</h3>
<p>Aplikasi pajak daerah terdiri dari module:</p>
<ul>
<li>Format yang digunakan adalah <a href="http://www.jsonrpc.org/specification" target="_blank">json-rpc 2.0</a></li>
<li>Access methode dengan request.post</li>
<li>Alamat Web Service ${request.url}/api</li>
<li>Method adalah method yang akan di akses</li>
</ul>
<h3>Autentikasi</h3>
Setiap HTTP POST yang dikirim harus mengandung HTTP Header seperti berikut ini.
<table border="1">
<tr>
<td width="150px">Nama header</td>
<td width="400px">Keterangan</td>
<td>Contoh Data</td>
</tr>
<tr>
<td>userid</td>
<td>User ID yang akan mengakses </td>
<td>user-ws</td>
</tr>
<tr>
<td>signature</td>
<td>Signature dengan pola HMAC-256</td>
<td>wtl7nDjOGWqVFS/oESUbEoOyQWyJItLIFWMZvASYpmQ=</td>
</tr>
<tr>
<td>key</td>
<td>Time Stamp dengan format Unix-Based</td>
<td>1424087283</td>
</tr>
</table>
<h3>Signature Generator</h3>
Signature Generator adalah pengacak data dengan menggunakan enkripsi HMAC-256. Penggunaan signature ini untuk meningkatkan keamanan karena transaksi dalam bentuk HTTP. Signature ini dihasilkan dengan mengkombinasikan userid dan password client.
<h4>PHP</h4>
<pre>
function json_rpc_header($userid, $password){
date_default_timezone_set('UTC');
$inttime = strval(time()-strtotime('1970-01-01 00:00:00'));
$value = "admin&" . $inttime;
$key = $password;
$signature = hash_hmac('sha256', $value, $key, true);
$signature64 = base64_encode($signature);
headers = {'userid':userid,
'signature':signature64,
'key':inttime}
return headers
}
</pre>
<h3>Python</h3>
<pre>
def json_rpc_header(userid, password):
utc_date = datetime.utcnow()
inttime = int((utc_date-datetime.strptime('19700101 000000', '%Y%m%d %H%M%S')).total_seconds())
value = "%s&%s" % (str(userid),str(inttime))
key = str(password)
signature = hmac.new(key, msg=value, digestmod=hashlib.sha256).digest()
signature64 = base64.encodestring(signature).replace('\n', '')
headers = {'userid':userid,
'signature':signature64,
'key':inttime}
return headers
</pre>
<h3>Pengiriman Data dengan Format JSON-RPC 2.0</h3>
<pre>
{
"jsonrpc": "2.0",
"method": "set_antrian",
"params": data,
"id":1
}
</pre>
<h3>Contoh aplikasi client dalam python</h3>
<pre>
row_dicted = [{'penerima':'081311045668','pesan':'Test 1'},
{'penerima':'087775477775','pesan':'Test 2'}]
rows = {"data":row_dicted}
headers = json_rpc_header('admin','$2a$10$EjDrW6Fk0g5')
data = {
"jsonrpc": "2.0",
"method": "set_antrian",
"params": rows,
"id":1
}
jsondata=json.dumps(data, ensure_ascii=False)
results = requests.post(rpc_url, data=jsondata,headers=headers)
row_results = json.loads(results.text)
</pre>
<h4>Contoh</h4>
<pre>
userid : admin
password: admin
timestamp = '1442495331'
signature = 'ix/9W9AV38NbOBxPMxMRUl8moiYmnC1nUlbou0WmrZ8='
header = {'userid': 'admin',
'key': 1442495331,
'signature': 'ix/9W9AV38NbOBxPMxMRUl8moiYmnC1nUlbou0WmrZ8='}
</pre>
<h4>Result</h4>
<ul>
<li>Sukses
<p>
Setiap request yang sukses akan dibalas degan struktur seperti berikut ini:
<pre>
{
"jsonrpc" : "2.0",
"id" : 3,
"result" : {
"message" : "Data Submitted",
"code" : 0,
"params" : {
"data" : [{
"field1" : NNNN,
"field2" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
"dst" : "dst"
}
],
}
}
}
</pre>
</li>
<li> Error
<pre>
{
"jsonrpc" : "2.0",
"id" : 3,
"error" : {
"code" : 123432432,
"message" : "Error Message",
}
}
</pre>
</li>
</ul>
<h4>Method</h4>
<ul>
<li>
<code>get_sp2d</code>
<h5>Input Param:</h5>
<pre>
{
"jsonrpc" : "2.0",
"id" : 1,
"method" : "get_sp2d"
"params" : {
"data" : [{
"kode" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
}
]
},
}
</pre>
</li>
<li>
<code>get_spm</code>
<h5>Input Param:</h5>
<pre>
{
"jsonrpc" : "2.0",
"id" : 1,
"method" : "get_spm"
"params" : {
"data" : [{
"kode" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
}
]
},
}
</pre>
</li>
<li>
<code>get_perusahaan</code>
<h5>Input Param:</h5>
<pre>
{
"jsonrpc" : "2.0",
"id" : 1,
"method" : "get_perusahaan"
"params" : {
"data" : [{
"nama" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
"nilai": 123456789
}
]
},
}
</pre>
</li>
<li>
<code>get_kegiatan</code>
<h5>Input Param:</h5>
<pre>
{
"jsonrpc" : "2.0",
"id" : 1,
"method" : "get_kegiatan"
"params" : {
"data" : [{
"nama" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
"nilai": 123456789
}
]
},
}
</pre>
</li>
</ul>
<h5>Output Params:</h5>
<pre>
{
"jsonrpc" : "2.0",
"id" : 3,
"result" : {
"message" : "Data Submitted",
"code" : 0,
"params" : {
"data" : [{
"tahun" : NNNN,
"no_spm" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
"tgl_spm" : "DD-MM-YYYY"
"no_sp2d" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
"tgl_sp2d" : "DD-MM-YYYY",
"nilai" : NNNNNNNNNNNN,
"potongan" : NNNNNNNNNNNN,
"tgl_penguji" : "DD-MM-YYYY", #or null
"status" : 0, # 0 blm cair, 1 cair
"tgl_cair" : "DD-MM-YYYY, #or null
"bank_penerima" : "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS",
}
],
}
}
}
</pre>
</div><!--well-->
<br>
</div>
</html>
\ No newline at end of file
VOUCHER
1. Inquiry: protokol untuk melakukan pengecekan data pembelian
REQ :
cid={CLIENT_ID}
dt={DATE}
hc={HASHCODE}
modul=ISI
command=INQ
tujuan=nomor
voucherid={VOUCHERID}
trxid={TRXID}
resp=XML
Contoh response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>[0] Cek Tagihan Sukses ke:628523123789</text>
<refnum>Cek pulsa TN5 berhasil dengan nominal 5.000,
refnum 4DB3DC0A2539419F8C50000000000000</refnum>
<voucherid>4DB3DC0A2539419F8C50000000000000</voucherid>
<destnum>TN5</destnum>
<nominal>628523123789</nominal>
</root>
Contoh response Error:
ERROR#0053#[53] ERROR Produk tidak ditemukan
2. Auto Payment: protokol untuk melakukan pembayaran/pembelian tanpa harus
melakukan inquiry terlebih dahulu
REQ :
cid={CLIENT_ID}
dt={DATE}
hc={HASHCODE}
modul=ISI
command=PAY
tujuan=nomor
voucherid={VOUCHERID}
trxid={TRXID}
resp=XML
Contoh request :
cid=btsp6ffacfed-6293-11e6-8325-
002590495dna&dt=20180723&hc=a85a020f3896298140c99a8509afcfad6272a717cc2aba8f842e68485e0a2642&
modul=ISI&command=PAY&tujuan=08572120002&voucherid=TN25&trxid=xxx1&resp=XML
RESP :
Contoh response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>[0] Pembayaran Sukses ke:08527778889</text>
<date>Isi pulsa TN10 berhasil untuk nomor 628527778889 sebesar 10.000, refnum
F148919BB5F4093A0F40000000000000 pada tgl 17/04/17 15:40</date>
<refnum>2017-04-17 15:40:28</refnum>
<voucherid>47C6DEFB60A34939B18DDBE2FE86D5D3</voucherid>
<destnum>TN10</destnum>
<nominal>628527778889</nominal>
<serial>10000</serial>
</root>
Contoh response Error:
ERROR#0056#[56] Nomor Telpon tidak diketahui
3. Advice: protokol untuk melakukan pengecekan transaksi dengan input payment refnum
REQ :
cid={CLIENT_ID}&dt={DATE}&hc={HASHCODE}&modul=ISI&command=ADV&tujuan=nomor&
voucherid={VOUCHERID}&trxid={TRXID}&resp=XML
Contoh request :
cid=btsp6ffacfed-6293-11e6-8325-
002590495dna&dt=20180723&hc=a85a020f3896298140c99a8509afcfad6272a717cc2aba8f842e68485e0a2642&
modul=ISI&command=ADV&tujuan=08572120002&voucherid=TN25&trxid=xxx1&resp=XML
RESP :
STATUS#RC#RCMESSAGE ke: TUJUAN #RESPTEXT#DT#REFNUM#VOUCHERID#NOMINAL#SERIALNUMBER
Contoh Response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>[0] Pembayaran Sukses</text>
<date>Isi pulsa TN10 berhasil untuk nomor 628527778889 sebesar 10.000, refnum
F148919BB5F4093A0F40000000000000 pada tgl 17/04/17 15:32</date>
<refnum>2017-04-17 15:40:28</refnum>
<voucherid>4A61D574138A2D6B4B6 </voucherid>
<destnum>TN10</destnum>
<nominal>10000</nominal>
<serial>4A61D574138A2D6B4B6 </serial>
</root>
Contoh response Error:
ERROR#0051# [51] ERROR Transaksi Gagal dari Mesin Vending
4. Info : protokol untuk melakukan pengecekan informasi produk dan harga
REQ :
cid={CLIENT_ID}&dt={DATE}&hc={HASHCODE}&resp={XML}&command=INFO&voucherid={VOUCHERID1,
VOUCHERID2}&tujuan={NO TUJUAN}
Contoh request :
cid=87ba9xzc-c7ex-8793-c7e5-
0225901955v7&dt=20160405&hc=057db24273f1bf2ffabad292504c2071cd01dd26c1715aec6f261a43bc1b38cb&
resp=xml&command=info&voucherid=TN10&tujuan=08527778889
6
RESP :
STATUS#RC#RESPTEXT
Contoh Response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>INFO HARGA:
TN10(TELKOMSEL AS/SIMPATI 10):Rp. 11.325
*Belum termasuk margin agen</text>
</root>
Contoh response Error:
ERROR#0053#[53] ERROR Produk tidak ditemukan
5. Respon Sukses Diantrikan : Menunggu Respon Biller.
XML :
7
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[1000] PEMBAYARAN SUKSES DIANTRIKAN ke:085934111000</rcm>
<text>
Isi pulsa TN25 berhasil untuk nomor 6285934111000 sebesar 25.000, refnum
3D5C50E06B5ED9AAB7B0000000000000 pada tgl 18/09/18 15:07</text>
<date>2018-09-18 15:07:33</date>
<refnum>DACC5EAC69EC4049AD4129C20E294C06</refnum>
<voucherid>TN25</voucherid>
<destnum>6285934111000</destnum>
<nominal>25000</nominal>
<serial></serial>
</root>
6. Callback :
http://mitra.url/callback?user_id=DEF56C3E6E3B4B6EBF88015AC25D3BFE&trxid=2134&status=S&dt=201
8-09-24%2010%3A22%3A23&info=ID%3A%202134%20TN5%20ke%206285334111000%20SUKSES%20SN%3A%20123423123%2
0%402018-09-24%2010%3A22%3A23;
user_id : client ID
trxid : transaction ID
status : S = sukses, R= Refund (gagal)
dt : tanggal format YYYY-mm-dd hh:ii:ss contoh diatas 2018-09-24 10:22:23
info: informasi, ID: 2134 TN5 ke 6285334111000 SUKSES SN: 123423123 @2018-09-24 10:22:23
Keterangan:
1. cid = identitas mitra, akan diinfokan ke mitra pada saat test maupun production
2. dt = tanggal transaksi (YYYYMMDD)
3. hc = SHA256(cid+dt+secret key) , secret key dan cid akan diinfokan ke mitra pada saat test maupun production
4. STATUS berisi status response SUCCESS atau ERROR
5. RCMESSAGE adalah Pesan Transaksi
6. RESPTEXT dan data lainnya akan ada jika STATUS=SUCCESS
7. \n di RESPTEXT adalah garis baru
8. Semua info/nilai yang diapit oleh {…}wajib diganti dengan nilai yang seharusnya (tanpa mengandung {}).
9. trxid merupakan unique id dari mitra per transaksi dengan panjang maksimum 50 character
Pesan Transaksi :
Pembayaran Sukses
[4] ERROR Biller Tidak terdaftar
[5] ERROR Lainnya
[6] ERROR Sentral diblok
[7] ERROR PPID diblok
[8] ERROR Waktu akses tidak valid
[9] ERROR Akun tidak aktif
[11] ERROR NEED TO SIGN ON
[12] ERROR Tidak bisa dibatalkan
[13] ERROR Nilai Transaksi tidak valid
[14] ERROR ID Tidak Terdaftar
[15] ERROR No Meter Tidak Terdaftar
[16] ERROR PRR SUBSCRIBER
[17] ERROR ID Punya Tunggakan
[18] ERROR Permintaan Sedang diproses
[26] Quota Transaksi Agen Tidak Mencukupi. Silahkan Kontak Agen.
[29] ERROR Kode Hash tidak valid
[30] ERROR Pesan tidak valid
[31] ERROR Kode Bank tidak terdaftar
[32] ERROR Sentral tidak terdaftar
[33] ERROR Produk tidak terdaftar
[34] ERROR PPID Tidak terdaftar
[35] ERROR Akun Tidak Terdaftar
[41] ERROR Nilai Transaksi dibawah Nilai Minimum
[42] ERROR Nilai Transaksi diatas Nilai Maximum
[43] ERROR Daya Baru Lebih Kecil dari Daya Sekarang
[44] ERROR Nilai Daya Tidak Valid
[45] ERROR Nilai Biaya Administrasi Tidak Valid
[46] ERROR Deposit Tidak Mencukupi
[47] ERROR Diluar Batas KWH
[48] ERROR Permintaan sudah kadaluarsa
[51] ERROR Transaksi Gagal dari Mesin Vending
[52] ERROR Transaksi dipending dari Mesin Vending
[53] ERROR Produk tidak ditemukan
[54] ERROR Jawaban dari Biller Tidak ditemukan
[55] ERROR Lainnya Mesin Vending
[56] ERROR Nomor Telpon Tidak diketahui
[63] ERROR Tidak ada Pembayaran
[60] ERROR Akun sudah didaftarkan
[67] ERROR CANNOT CONNECT
[68] ERROR Timeout
[69] ERROR Sertifikat tidak dikenal
[70] ERROR Timeout tidak refund
[72] ERROR Permintaan tidak mungkin dilayani
[73] ERROR Request dipending di Biller
[77] ERROR Id di suspend
[88] ERROR Tagihan sudah dibayar
[89] ERROR Tagihan tidak tersedia
[90] ERROR sedang proses CUT OFF
[91] ERROR Database
[92] ERROR Nomor Referensi Switching tidak ditemukan
[93] ERROR Nomor Referensi Switching tidak valid
[94] ERROR Pembatalan sudah dilakukan
[95] ERROR Kode Merchant tidak terdaftar
[96] ERROR Transaksi tidak ditemukan
[97] ERROR SW BANK Tidak identik
[98] ERROR Nomor Referensi Switching tidak valid
[146] ERROR di servis deposit
\ No newline at end of file
import base64
import hashlib
import json
from datetime import datetime
import requests
import xmltodict
from opensipkd.base import get_settings
from opensipkd.pasar.models import Partner, PartnerProduk, Produk
from pyramid_rpc.jsonrpc import JsonRpcError
from .vendor import VendorClass
class Vendor(VendorClass):
def __init__(self, produk_kd, cid, trx_id, vendor_id):
"""
:param produk_kd:
merupakan kode produk versi vendor
:param trx_id:
kode unik transaksi
:param cid:
merupakan customer id seperti MSN dan atu id pelanggaan
"""
VendorClass.__init__(self, cid, vendor_id)
settings = self.settings
self.mid = 'vsi_mid' in settings and settings['vsi_mid'] or None
self.key = 'vsi_key' in settings and settings['vsi_key'] or None
self.url = 'vsi_url' in settings and settings['vsi_url'] or None
self.trx_id = trx_id
self.produk_kd = produk_kd
def get_hc(self, tanggal):
hash_string = "".join([self.mid, tanggal, self.key])
self.auth = hashlib.sha256(hash_string.encode()).hexdigest()
return self.auth
def get_params(self, cmd, msn=None, idpel=None, modul=None):
tanggal = datetime.now().strftime('YYYYMMDD')
params = dict(
cid=self.mid,
dt=tanggal,
hc=self.get_hc(tanggal),
modul=modul,
command=cmd,
resp='XML',
trxid=self.trx_id,
)
if msn:
params['msn']=msn
if idpel:
params['idpel'] = idpel
return params
\ No newline at end of file
import base64
import hashlib
import json
from datetime import datetime
import requests
import xmltodict
from opensipkd.base import get_settings
from opensipkd.pasar.models import Partner, PartnerProduk, Produk
from pyramid_rpc.jsonrpc import JsonRpcError
from .vsi import Vendor as VendorClass
class Vendor(VendorClass):
def __init__(self, product_kd, trx_id=None, cid=None):
VendorClass.__init__(self, product_kd, cid)
def inquiry(self):
"""
:return:
:parameter url tobe submitted
cid = {CLIENTID}
dt = {DATE}
hc = {HASHCODE}
modul = pln
command = INQ
idpel = {IDPELANGGAN}
resp = XML
trxid = {IDTRANSAKSI}
:sukses response
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>
[0] CEK TAGIHAN SUKSES ke:532110000060 refnum:33ECE3543E62474AA0C6C3147D94A31D
</rcm>
<text>532110000060
DU'MMY-VSI-532110000
1 BLN
JUN16
RP TAG PLN RP 887.817
ADM RP 1.600
TOTAL RP 890.929
</text>
<refnum>33ECE3543E62474AA0C6C3147D94A31D</refnum>
<idpel>532110000060</idpel>
<nama>DU'MMY-VSI-532110000060</nama>
<bulan>1 BLN</bulan>
<blntagihan>JUN16</blntagihan>
<admin>1600</admin>
<tagihan>889329</tagihan>
<total>890929</total>
</root>
:error response
<?xml version = "1.0"?>
<root>
<status>ERROR</status>
<rc>0014</rc>
<rcm>
[14] IDPEL YANG ANDA MASUKKAN SALAH, MOHON TELITI KEMBALI.
</rcm>
< / root >
: notes
1. cid = identitas mitra, akan diinfokan ke mitra pada saat test
maupun production.
2. dt = tanggal jam transaksi (YYYYMMDD).
3. hc = SHA256(cid+dt+secret key) , secret key dan cid akan
diinfokan ke mitra pada saat test maupun production.
4. Semua info/nilai yang diapit oleh {…} wajib diganti dengan
nilai yang seharusnya (tanpa mengandung {}).
5. trxid merupakan unique id dari mitra per transaksi dengan
panjang maksimum 50 character.
6. resp merupakan format respon yang diinginkan (XML), secara
default jika dikosongkan maka responnya merupakan format plaintext.
"""
params = self.get_params(cmd='INQ', modul='pln', idpel=self.cid)
result = requests.get(self.url, params=params)
data = xmltodict(result)
return data
def payment(self):
"""
:parameter
cid = {CLIENTID}
dt = {DATE}
hc = {HASHCODE}
modul = pln
command = PAY
idpel = {IDPELANGGAN}
resp = XML
trxid = {IDTRANSAKSI}
:response sukses
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[0] PEMBAYARAN SUKSES ke:532110000060 refnum:0506213515100D3399B27293E3DBC535</rcm>
<text>22/06/16 14:29
0506213515100D3399B27293E3DBC535
532110000060
DU'MMY-VSI-532110000
R1/450
BLN JUN16
RP 887.729
ADM RP 1.600
TOTAL RP 890.929
SUKSES
</text>
<date>2016-06-22 14:29:25</date>
<refnum>0506213515100D3399B27293E3DBC535</refnum>
<idpel>532110000060</idpel>
<nama>DU'MMY-VSI-532110000060</nama>
<segmenpower>R1/450</segmenpower>
<startend>888800-889900</startend>
<blntagihan>JUN16</blntagihan>
<ppn>0</ppn>
<denda>0</denda>
<totaltagihanpln>887729</totaltagihanpln>
<admin>1600</admin>
<total>890929</total>
<info1>Informasi Hubungi Call Center: 123 Atau Hub. PLN Terdekat:</info1>
<info2>Terima Kasih</info2>
</root>
:response error
<?xml version="1.0"?>
<root>
<status>ERROR</status>
<rc>0088</rc>
<rcm>[88] TAGIHAN SUDAH TERBAYAR</rcm>
</root>
"""
params = self.get_params(cmd='PAY', modul='pln', idpel=self.cid)
result = requests.get(self.url, params=params)
data = xmltodict(result)
return data
"""
XML-HTTP
PARTNER
PLN-PREPAID MODULE
Version 1.0.0 (June 2016)
2016
REVISIONS
VERSION DATE DESCRIPTION
1.0.0 June 7th, 2016 Initial release
1
PREPAID
"""
# 1. Inquiry: protokol untuk melakukan pengecekan data tagihan/pembelian
"""
REQ :
?
modul=PRE
command=INQ
msn={IDPEL/MSN}
cid={CLIENTID}
dt={DTTRX}
hc={HASH}
trxid={UniqueID}
resp=XML
Contoh response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[0] CEK TAGIHAN SUKSES ke:88888888888 refnum:D0EE65CAB0C04601878612867541EEA5</rcm>
<text>88888888888
TestDu''mmyP
R2/7000 VA
Token Unsold: 0
Adm 1.600,00
*Denom Belum Termasuk Admin
</text>
<refnum>D0EE65CAB0C04601878612867541EEA5</refnum>
<msn>88888888888</msn>
<idpel>885555555555</idpel>
<nama>TestDu''mmyPanjang8855555</nama>
<tarifdaya>R2/7000</tarifdaya>
<adm>1600</adm>
<jmltokenunsold>0</jmltokenunsold>
</root>
Contoh response Error:
<?xml version="1.0"?>
<root>
<status>ERROR</status>
<rc>0014</rc>
<rcm>[14] IDPEL YANG ANDA MASUKKAN SALAH, MOHON TELITI KEMBALI. ke:888888888</rcm>
</root>
"""
# 2. Payment:
"""
modul=PRE
command=PAY
nominal={NOMINAL}
refnum={INQREF}
cid={CLIENTID}
dt={DTTRX}
hc={HASH}
trxid={UniqueID}
resp=XML
Contoh response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[0] PEMBAYARAN SUKSES ke:88888888888 refnum:05062135116139A54A95CCC549DDA94C</rcm>
<text>08/06/16 11:50
05062135116139A54A95CCC549DDA94C
TestDu''mmyP
88888888888
881111111111
R2/6600 VA
RP 201.600
KWH352,0
STROOM/TOKEN 2593 0960 8106 1072 1376
ADM 1.600,00</text>
<tanggal>2016-06-08 11:50:22</tanggal>
<nama>TestDu''mmyPanjang8811111</nama>
<msn>88888888888</msn>
<idpel>881111111111</idpel>
<tarifdaya>R2/6600</tarifdaya>
<nominal>201600</nominal>
<jmlkwh>352</jmlkwh>
<token>2593-0960-8106-1072-1376</token>
<ppn>0</ppn>
<ppj>0</ppj>
<adm>1600</adm>
<angsuran>24000</angsuran>
<materai>0</materai>
</root>
Contoh response Error:
<?xml version="1.0"?>
<root>
<status>ERROR</status>
<rc>0068</rc>
<rcm>[68] TRANSAKSI TIDAK BISA DILAKUKAN SAAT INI, SILAHKAN LAKUKAN MANUAL
ADVICE BEBERAPA SAAT LAGI. ke:233313211212
</rcm>
</root>
"""
# 3. Advice: protokol untuk melakukan pengecekan transaksi dengan input payment refnum
"""
REQ :
?
modul=PRE
command=ADV
nominal={NOMINAL}
refnum={PAYREF}
cid={CLIENTID}
dt={DTTRX}&hc={HASH}
trxid={UniqueID}
resp=XML
Contoh Response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[0] PEMBAYARAN SUKSES ke:88888888888 refnum:051158BB9F2741AB893DCE972396DB59</rcm>
<text>08/06/16 11:50
05062135116139A54A95CCC549DDA94C
TestDu''mmyP
88888888888
881111111111
R2/6600
RP 201.600
KWH352,0
STROOM/TOKEN 2593 0960 8106 1072 1376
ADM 1.600,00
</text>
<tanggal>2016-06-08 11:50:22</tanggal>
<nama>TestDu''mmyPanjang8811111</nama>
<msn>88888888888</msn>
<idpel>881111111111</idpel>
<tarifdaya>R2/6600</tarifdaya>
<nominal>201600</nominal>
<jmlkwh>352</jmlkwh>
<token>2593-0960-8106-1072-1376</token>
<ppn>0</ppn>
<ppj>0</ppj>
<adm>1600</adm>
<angsuran>24000</angsuran>
<materai>0</materai>
</root>
Contoh response Error:
<?xml version="1.0"?>
<root><status>ERROR</status><rc>0096</rc><rcm>[96] ERROR TRANSAKSI TIDAK DITEMUKAN
ke:23331321121</rcm></root>
"""
# 4. Auto Payment :protokol untuk melakukan pembayaran/pembelian dengan tanpa melakukan inquiry
"""
REQ :
?
modul=PRE
command=PAY
msn={22222222222}
nominal={NOMINAL}
cid={CLIENTID}
dt={DTTRX}
hc={HASH}
trxid={UniqueID}
resp=XML
Contoh Response Sukses:
Contoh response Error:
<?xml version="1.0"?>
<root><status>ERROR</status><rc>0068</rc><rcm>[68] TRANSAKSI TIDAK BISA DILAKUKAN SAAT INI,
SILAHKAN LAKUKAN MANUAL ADVICE BEBERAPA SAAT LAGI. ke:233313211212</rcm></root>
5. Advice Tanpa PAYREF: protokol untuk melakukan pengecekan transaksi tanpa input payment refnum
REQ :
?modul=PRE&command=ADV&msn={22222222222}&nominal={NOMINAL}&cid={CLIENTID}&dt={DTTRX}&hc={HASH
}&trxid={UniqueID}&resp=XML
Contoh Response:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[0] PEMBAYARAN SUKSES ke:88888888888
refnum:051158BB9F2741AB893DCE972396DB59</rcm><text>08/06/16 11:50
05062135116139A54A95CCC549DDA94C
TestDu''mmyP
88888888888
881111111111
R2/6600
RP 201.600
KWH 352,0
STROOM/TOKEN 2593 0960 8106 1072 1376
ADM 1.600,00</text>
<tanggal>2016-06-08 11:50:22</tanggal>
<nama>TestDu''mmyPanjang8811111</nama>
<msn>88888888888</msn>
<idpel>881111111111</idpel>
<tarifdaya>R2/6600</tarifdaya>
<nominal>201600</nominal>
<jmlkwh>352</jmlkwh>
<token>2593-0960-8106-1072-1376</token>
<ppn>0</ppn>
<ppj>0</ppj>
<adm>1600</adm>
<angsuran>24000</angsuran>
<materai>0</materai>
</root>
Contoh response Error:
<?xml version="1.0"?>
<root>
<status>ERROR</status>
<rc>0096</rc>
<rcm>[96] ERROR TRANSAKSI TIDAK DITEMUKAN ke:23331321121</rcm>
</root>
Keterangan:
1. cid = identitas mitra, akan diinfokan ke mitra pada saat test maupun production.
2. dt = tanggal jam transaksi (YYYYMMDD).
3. hc = SHA256(cid+dt+secret key) , secret key dan cid akan diinfokan ke mitra pada saat test maupun production.
4. Semua info/nilai yang diapit oleh {…} wajib diganti dengan nilai yang seharusnya (tanpa mengandung {}).
5. trxid merupakan unique id dari mitra per transaksi dengan panjang maksimum 50 character.
6. resp merupakan format respon yang diinginkan (XML), secara default jika dikosongkan maka responnya merupakan format plaintext.Pesan Transaksi :
Pembayaran Sukses
[4] ERROR Biller Tidak terdaftar
[5] ERROR Lainnya
[6] ERROR Sentral diblok
[7] ERROR PPID diblok
[8] ERROR Waktu akses tidak valid
[9] ERROR Akun tidak aktif
[11] ERROR NEED TO SIGN ON
[12] ERROR Tidak bisa dibatalkan
[13] ERROR Nilai Transaksi tidak valid
8
[14] ERROR ID Tidak Terdaftar
[15] ERROR No Meter Tidak Terdaftar
[16] ERROR PRR SUBSCRIBER
[17] ERROR ID Punya Tunggakan
[18] ERROR Permintaan Sedang diproses
[26] Quota Transaksi Agen Tidak Mencukupi. Silahkan Kontak Agen.
[29] ERROR Kode Hash tidak valid
[30] ERROR Pesan tidak valid
[31] ERROR Kode Bank tidak terdaftar
[32] ERROR Sentral tidak terdaftar
[33] ERROR Produk tidak terdaftar
[34] ERROR PPID Tidak terdaftar
[35] ERROR Akun Tidak Terdaftar
[41] ERROR Nilai Transaksi dibawah Nilai Minimum
[42] ERROR Nilai Transaksi diatas Nilai Maximum
[43] ERROR Daya Baru Lebih Kecil dari Daya Sekarang
[44] ERROR Nilai Daya Tidak Valid
[45] ERROR Nilai Biaya Administrasi Tidak Valid
[46] ERROR Deposit Tidak Mencukupi
[47] ERROR Diluar Batas KWH
[48] ERROR Permintaan sudah kadaluarsa
[51] ERROR Transaksi Gagal dari Mesin Vending
[52] ERROR Transaksi dipending dari Mesin Vending
[53] ERROR Produk tidak ditemukan
[54] ERROR Jawaban dari Biller Tidak ditemukan
[55] ERROR Lainnya Mesin Vending
[56] ERROR Nomor Telpon Tidak diketahui
[63] ERROR Tidak ada Pembayaran
[60] ERROR Akun sudah didaftarkan
[67] ERROR CANNOT CONNECT
[68] ERROR Timeout
[69] ERROR Sertifikat tidak dikenal
[70] ERROR Timeout tidak refund
[72] ERROR Permintaan tidak mungkin dilayani
[73] ERROR Request dipending di Biller
[77] ERROR Id di suspend
[88] ERROR Tagihan sudah dibayar
[89] ERROR Tagihan tidak tersedia
[90] ERROR sedang proses CUT OFF
[91] ERROR Database
[92] ERROR Nomor Referensi Switching tidak ditemukan
[93] ERROR Nomor Referensi Switching tidak valid
[94] ERROR Pembatalan sudah dilakukan
[95] ERROR Kode Merchant tidak terdaftar
[96] ERROR Transaksi tidak ditemukan
[97] ERROR SW BANK Tidak identik
[98] ERROR Nomor Referensi Switching tidak valid
[146] ERROR di servis deposit
"""
import requests
import xmltodict
from .vsi import Vendor as VendorClass
class Vendor(VendorClass):
def __init__(self, product_kd, cid=None, trx_id=None):
VendorClass.__init__(self, product_kd, cid, trx_id)
def inquiry(self):
params = self.get_params('INQ')
params["msn"] = self.cid
result = requests.get(self.url, params=params)
data = xmltodict(result)
return data
def payment(self):
params = self.get_params('PAY')
params["msn"] = self.cid
result = requests.get(self.url, params=params)
data = xmltodict(result)
return data
# 1. Inquiry: protokol untuk melakukan pengecekan data pembelian
"""
VOUCHER
REQ :
cid={CLIENT_ID}
dt={DATE}
hc={HASHCODE}
modul=ISI
command=INQ
tujuan=nomor
voucherid={VOUCHERID}
trxid={TRXID}
resp=XML
Contoh response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>[0] Cek Tagihan Sukses ke:628523123789</text>
<refnum>Cek pulsa TN5 berhasil dengan nominal 5.000,
refnum 4DB3DC0A2539419F8C50000000000000</refnum>
<voucherid>4DB3DC0A2539419F8C50000000000000</voucherid>
<destnum>TN5</destnum>
<nominal>628523123789</nominal>
</root>
Contoh response Error:
ERROR#0053#[53] ERROR Produk tidak ditemukan
"""
# 2. Auto Payment: protokol untuk melakukan pembayaran/pembelian tanpa harus
# melakukan inquiry terlebih dahulu
"""
REQ :
cid={CLIENT_ID}
dt={DATE}
hc={HASHCODE}
modul=ISI
command=PAY
tujuan=nomor
voucherid={VOUCHERID}
trxid={TRXID}
resp=XML
Contoh request :
cid=btsp6ffacfed-6293-11e6-8325-002590495dna
&dt=20180723
&hc=a85a020f3896298140c99a8509afcfad6272a717cc2aba8f842e68485e0a2642
&modul=ISI
&command=PAY
&tujuan=08572120002
&voucherid=TN25
&trxid=xxx1
&resp=XML
RESP :
Contoh response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>[0] Pembayaran Sukses ke:08527778889</text>
<date>Isi pulsa TN10 berhasil untuk nomor 628527778889 sebesar 10.000, refnum
F148919BB5F4093A0F40000000000000 pada tgl 17/04/17 15:40</date>
<refnum>2017-04-17 15:40:28</refnum>
<voucherid>47C6DEFB60A34939B18DDBE2FE86D5D3</voucherid>
<destnum>TN10</destnum>
<nominal>628527778889</nominal>
<serial>10000</serial>
</root>
Contoh response Error:
ERROR#0056#[56] Nomor Telpon tidak diketahui
"""
# 3. Advice: protokol untuk melakukan pengecekan transaksi dengan input payment refnum
"""
REQ :
cid={CLIENT_ID}
dt={DATE}
hc={HASHCODE}
modul=ISI
command=ADV
tujuan=nomor
voucherid={VOUCHERID}
trxid={TRXID}
resp=XML
Contoh request :
cid=btsp6ffacfed-6293-11e6-8325-002590495dna
dt=20180723
hc=a85a020f3896298140c99a8509afcfad6272a717cc2aba8f842e68485e0a2642
modul=ISI
command=ADV
tujuan=08572120002
voucherid=TN25
trxid=xxx1
resp=XML
RESP :
STATUS#RC#RCMESSAGE ke: TUJUAN #RESPTEXT#DT#REFNUM#VOUCHERID#NOMINAL#SERIALNUMBER
Contoh Response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>[0] Pembayaran Sukses</text>
<date>Isi pulsa TN10 berhasil untuk nomor 628527778889 sebesar 10.000, refnum
F148919BB5F4093A0F40000000000000 pada tgl 17/04/17 15:32</date>
<refnum>2017-04-17 15:40:28</refnum>
<voucherid>4A61D574138A2D6B4B6 </voucherid>
<destnum>TN10</destnum>
<nominal>10000</nominal>
<serial>4A61D574138A2D6B4B6 </serial>
</root>
Contoh response Error:
ERROR#0051# [51] ERROR Transaksi Gagal dari Mesin Vending
"""
# 4. Info : protokol untuk melakukan pengecekan informasi produk dan harga
"""
REQ :
cid={CLIENT_ID}
dt={DATE}
hc={HASHCODE}
resp={XML}
command=INFO
voucherid={VOUCHERID1,VOUCHERID2}
tujuan={NO TUJUAN}
Contoh request :
cid=87ba9xzc-c7ex-8793-c7e5-0225901955v7
dt=20160405
hc=057db24273f1bf2ffabad292504c2071cd01dd26c1715aec6f261a43bc1b38cb
resp=xml
command=info
voucherid=TN10
tujuan=08527778889
RESP :
STATUS#RC#RESPTEXT
Contoh Response Sukses:
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>0000</rcm>
<text>INFO HARGA:
TN10(TELKOMSEL AS/SIMPATI 10):Rp. 11.325
*Belum termasuk margin agen</text>
</root>
Contoh response Error:
ERROR#0053#[53] ERROR Produk tidak ditemukan
"""
# 5. Respon Sukses Diantrikan : Menunggu Respon Biller.
"""
XML :
<?xml version="1.0"?>
<root>
<status>SUCCESS</status>
<rc>0000</rc>
<rcm>[1000] PEMBAYARAN SUKSES DIANTRIKAN ke:085934111000</rcm>
<text>
Isi pulsa TN25 berhasil untuk nomor 6285934111000 sebesar 25.000, refnum
3D5C50E06B5ED9AAB7B0000000000000 pada tgl 18/09/18 15:07</text>
<date>2018-09-18 15:07:33</date>
<refnum>DACC5EAC69EC4049AD4129C20E294C06</refnum>
<voucherid>TN25</voucherid>
<destnum>6285934111000</destnum>
<nominal>25000</nominal>
<serial></serial>
</root>
"""
# 6. Callback :
"""
http://mitra.url/callback?user_id=DEF56C3E6E3B4B6EBF88015AC25D3BFE&trxid=2134&status=S&dt=201
8-09-24%2010%3A22%3A23&info=ID%3A%202134%20TN5%20ke%206285334111000%20SUKSES%20SN%3A%20123423123%2
0%402018-09-24%2010%3A22%3A23;
http://mitra.url/callback?
user_id=DEF56C3E6E3B4B6EBF88015AC25D3BFE
trxid=2134
status=S
dt=2018-09-24 10:22:23
info=ID: 2134 TN5 ke 6285334111000 SUKSES SN: 123423123 @2018-09-24 10:22:23;
user_id : client ID
trxid : transaction ID
status : S = sukses, R= Refund (gagal)
dt : tanggal format YYYY-mm-dd hh:ii:ss contoh diatas 2018-09-24 10:22:23
info: informasi, ID: 2134 TN5 ke 6285334111000 SUKSES SN: 123423123 @2018-09-24 10:22:23
"""
# Keterangan:
"""
1. cid = identitas mitra, akan diinfokan ke mitra pada saat test maupun produkion
2. dt = tanggal transaksi (YYYYMMDD)
3. hc = SHA256(cid+dt+secret key) , secret key dan cid akan diinfokan ke mitra pada saat test maupun produkion
4. STATUS berisi status response SUCCESS atau ERROR
5. RCMESSAGE adalah Pesan Transaksi
6. RESPTEXT dan data lainnya akan ada jika STATUS=SUCCESS
7. \n di RESPTEXT adalah garis baru
8. Semua info/nilai yang diapit oleh {…}wajib diganti dengan nilai yang seharusnya (tanpa mengandung {}).
9. trxid merupakan unique id dari mitra per transaksi dengan panjang maksimum 50 character
"""
# Pesan Transaksi :
"""
Pembayaran Sukses
[4] ERROR Biller Tidak terdaftar
[5] ERROR Lainnya
[6] ERROR Sentral diblok
[7] ERROR PPID diblok
[8] ERROR Waktu akses tidak valid
[9] ERROR Akun tidak aktif
[11] ERROR NEED TO SIGN ON
[12] ERROR Tidak bisa dibatalkan
[13] ERROR Nilai Transaksi tidak valid
[14] ERROR ID Tidak Terdaftar
[15] ERROR No Meter Tidak Terdaftar
[16] ERROR PRR SUBSCRIBER
[17] ERROR ID Punya Tunggakan
[18] ERROR Permintaan Sedang diproses
[26] Quota Transaksi Agen Tidak Mencukupi. Silahkan Kontak Agen.
[29] ERROR Kode Hash tidak valid
[30] ERROR Pesan tidak valid
[31] ERROR Kode Bank tidak terdaftar
[32] ERROR Sentral tidak terdaftar
[33] ERROR Produk tidak terdaftar
[34] ERROR PPID Tidak terdaftar
[35] ERROR Akun Tidak Terdaftar
[41] ERROR Nilai Transaksi dibawah Nilai Minimum
[42] ERROR Nilai Transaksi diatas Nilai Maximum
[43] ERROR Daya Baru Lebih Kecil dari Daya Sekarang
[44] ERROR Nilai Daya Tidak Valid
[45] ERROR Nilai Biaya Administrasi Tidak Valid
[46] ERROR Deposit Tidak Mencukupi
[47] ERROR Diluar Batas KWH
[48] ERROR Permintaan sudah kadaluarsa
[51] ERROR Transaksi Gagal dari Mesin Vending
[52] ERROR Transaksi dipending dari Mesin Vending
[53] ERROR Produk tidak ditemukan
[54] ERROR Jawaban dari Biller Tidak ditemukan
[55] ERROR Lainnya Mesin Vending
[56] ERROR Nomor Telpon Tidak diketahui
[63] ERROR Tidak ada Pembayaran
[60] ERROR Akun sudah didaftarkan
[67] ERROR CANNOT CONNECT
[68] ERROR Timeout
[69] ERROR Sertifikat tidak dikenal
[70] ERROR Timeout tidak refund
[72] ERROR Permintaan tidak mungkin dilayani
[73] ERROR Request dipending di Biller
[77] ERROR Id di suspend
[88] ERROR Tagihan sudah dibayar
[89] ERROR Tagihan tidak tersedia
[90] ERROR sedang proses CUT OFF
[91] ERROR Database
[92] ERROR Nomor Referensi Switching tidak ditemukan
[93] ERROR Nomor Referensi Switching tidak valid
[94] ERROR Pembatalan sudah dilakukan
[95] ERROR Kode Merchant tidak terdaftar
[96] ERROR Transaksi tidak ditemukan
[97] ERROR SW BANK Tidak identik
[98] ERROR Nomor Referensi Switching tidak valid
[146] ERROR di servis deposit"""
import requests
import xmltodict
from .vsi import Vendor as VendorClass
# todo: result harus distandarisasi
class Vendor(VendorClass):
def inquiry(self):
params = self.get_params(cmd='INQ', modul='ISI')
params["tujuan"] = self.cid
params["voucherid"] = self.produk_kd
result = requests.get(self.url, params=params)
if result.ok:
data = xmltodict.parse(result.text)["root"]
else:
data = dict(error=result.status_code)
self.save_log('inquiry')
return data
def payment(self):
params = self.get_params(cmd='PAY', modul='ISI')
self.request = params
result = requests.get(self.url, params=params)
if result.ok:
data = xmltodict.parse(result.text)["root"]
self.response = data
else:
data = dict(error=result.status_code)
self.save_log('payment')
return data
def advice(self):
params = self.get_params(cmd='ADV', modul='ISI')
self.request = params
result = requests.get(self.url, params=params)
if result.ok:
data = xmltodict.parse(result.text)["root"]
self.response = data
else:
data = dict(error=result.status_code)
self.save_log('advice')
return data
def info(self):
params = self.get_params(cmd='info', modul='ISI')
self.request = params
result = requests.get(self.url, params=params)
if result.ok:
data = xmltodict.parse(result.text)["root"]
self.response = data
else:
data = dict(error=result.status_code)
self.save_log('info')
return data
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!