__init__.py 7.04 KB
import transaction
from ISO8583.ISOErrors import BitNotSet
from deform import (
    ValidationFailure,
)
from iso8583_web.scripts.logger import (
    log_web_info,
    log_web_debug)
from iso8583_web.scripts.views import WebJob
from opensipkd.string import (
    FixLength,
)

from .structure import INVOICE_PROFILE
from .structure import Transaksi
from .. import View as BaseView
from ..linkaja import (
    WebJob,
    # View as BaseView,
    is_inquiry, get_db_session, is_reversal, is_payment, get_method,
    get_form, date_from_str, csv_method, get_template_response, get_inquiry, get_payment)
from ..linkaja.exceptions import (
    InvoiceIdError,
    NeedPostError,
    InternalError,
    HostError,
    AlreadyPaidError,
    BaseError,
    AmountError,
    BillRefNotFound,
    PaymentNotFound,
)
from ..linkaja.models import (Rpc, LogSam)

ROUTE = 'linkaja/sambat'

conf = dict()


class View(BaseView):
    def get_web_job_cls(self):  # Override
        return WebJob

    def not_found_error(self, hostname):  # Override
        return HostError(hostname)

    def not_running_error(self, hostname):  # Override
        msg = 'Host {} belum terhubung'.format(hostname)
        return InternalError(msg, 'Sedang offline')

    def create_iso_log(self, iso, rpc):
        conf = self.get_iso_conf()
        iso_log = LogSam(
            mti=iso.mti,
            rpc_id=rpc.id,
            ip=conf['ip'],
            conf_name=conf['name'],
            message=iso.data,
            bit_003=iso.data["processingCode"])
        try:
            data = iso.data["additionalData"]
            profile = FixLength(INVOICE_PROFILE)
            profile.set_raw(data)
            iso_log.bit_062_data = profile.to_dict()
        except BitNotSet:
            pass
        return iso_log

    def before_send_iso(self, data, inq, pay, req):
        DBSession = get_db_session()
        web_conf = self.get_web_conf()
        row = Rpc(
            ip=self.request.client_addr,
            conf_name=web_conf['name'],
            merchant=data['merchant'],
            terminal=data['terminal'],
            trx_type=data['trx_type'],
            msisdn=data['msisdn'],
            acc_no=data['acc_no'],
            stan=req.get_stan())
        row.trx_date = date_from_str(data['trx_date']),
        if data.get('msg'):
            row.msg = data['msg']
        if data.get('amount'):
            row.amount = int(data['amount'])
        if not is_inquiry(data):
            row.inquiry_id = inq and inq.id or pay.inquiry_id
            row.ntb = data['trx_id']
        with transaction.manager:
            DBSession.add(row)
            DBSession.flush()
            DBSession.expunge_all()  # Agar dapat row.id
            iso_log = self.create_iso_log(req, row)
            DBSession.add(iso_log)
        return row

    def after_send_iso(self, data, inq, pay, row, iso_resp):
        DBSession = get_db_session()
        iso_log = self.create_iso_log(iso_resp, row)
        iso_data = iso_resp.response
        web_data = get_template_response(data)
        if iso_data["responseCode"] == '00':
            web_data['Response Code'] = '00'
            if is_inquiry(data):
                web_data['Bill Ref'] = str(row.id)
            if iso_data["additionalData"]:
                profile = FixLength(INVOICE_PROFILE)
                profile.set_raw(iso_data["additionalData"])
                iso_log.bit_062_data = profile.to_dict()
                web_data['Biller Name'] = row.biller_name = \
                    ' '.join([profile['NOMOR POLISI'], profile['NAMA PEMILIK'].strip()])
            web_data['Bill Amount'] = iso_data["amountTransaction"].lstrip('0')
            if "numberTransactionP" in iso_data and iso_data["numberTransactionP"]:
                web_data['Transaction ID'] = row.ntp = iso_data["numberTransactionP"]  # NTP
            err = None
        elif iso_data["responseCode"] in ['33', '55']:
            err = InvoiceIdError()
        elif iso_data["responseCode"] == '54':
            if is_reversal(data):
                err = PaymentNotFound()
            else:
                err = AlreadyPaidError()
        elif iso_data["responseCode"] == '51':
            err = AmountError()
        else:
            err = BaseError()

        if err:
            web_data.from_err(err)
            row.resp_msg = web_data['Notification Message']
        self.log_send(web_data.values)
        row.resp_code = web_data['Response Code']
        row.resp_msg = web_data['Notification Message']
        with transaction.manager:
            DBSession.add(row)
            DBSession.add(iso_log)
        return web_data

    def get_response(self, data):
        # todo: merubah get response
        log_web_debug("Start Response")
        p = dict(invoice_id=data['acc_no'])
        inq = pay = None
        if not is_inquiry(data):
            p['amount'] = data['amount']
            p['ntb'] = data['trx_id']
            if is_payment(data):
                inq = get_inquiry(data)
                if not inq:
                    print("Inquiry Not Found")
                    raise BillRefNotFound()
            else:
                pay = get_payment(data)
                if not pay:
                    print("Payment Not Found")
                    raise BillRefNotFound()
                p['stan'] = pay.stan

        # conn = self.get_connection()
        method = get_method(data)
        # iso_func = getattr(conn.job, method)
        iso_req = Transaksi(p, method, inq, pay, conf)
        row = self.before_send_iso(data, inq, pay, iso_req)
        iso_req.send()
        if type(iso_req.response) != dict:
            raise BaseError
        iso_req.data = iso_req.response
        return self.after_send_iso(data, inq, pay, row, iso_req)

    @csv_method(route_name=ROUTE)
    def view_trx_sambat(self):
        self.validate()
        if not self.request.POST:
            self.log_receive('GET {}'.format(self.request.GET))
            raise NeedPostError()

        items = self.request.POST.items()
        self.log_receive('POST {}'.format(dict(items)))
        items = self.request.POST.items()
        form = get_form()
        try:
            c = form.validate(items)
        except ValidationFailure as e:
            d = e.error.asdict()
            msg = e.error
            for field, err in d.items():
                msg = '{} {}'.format(field, err)
                break
            raise InternalError(msg)
        data = dict(c)
        return self.get_response(data)


# Dipanggil read_conf.py
def init(cfg):
    conf.update(cfg)


# Dipanggil forwarder.py
def pyramid_init(config):
    # config.add_renderer(RENDERER, 'iso8583_web.scripts.views.linkaja.Renderer')
    config.add_route(ROUTE, conf['route_path'])
    log_web_info('LinkAja Sambat route path {}'.format(conf['route_path']))
    # pool_size = int(conf.get('db_pool_size', 50))
    # max_overflow = int(conf.get('db_max_overflow', 100))
    # engine = create_engine(
    #     conf['db_url'], pool_size=pool_size, max_overflow=max_overflow)
    # session_factory = sessionmaker(bind=engine)
    # conf['db_session'] = scoped_session(session_factory)
    # register(conf['db_session'])