api_payment.py 10.9 KB
import logging
from importlib import import_module

import colander
from agratek.api.merchant.views.api_merchant import get_vendor_produk
from deform import widget, Form
from opensipkd.base.models import Partner, flush_row
from opensipkd.base.tools.api import (auth_from_rpc,
                                      JsonRpcProdukNotFoundError, JsonRpcCustomerNotFoundError,
                                      JsonRpcParameterNotFound)
from opensipkd.base.views import BaseView
from opensipkd.pasar.models import Produk, PartnerProduk
from opensipkd.pasar.models.produk import H2hArInvoice, H2hArInvoiceDet, PartnerLog, PartnerPay
from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config
from pyramid_rpc.jsonrpc import jsonrpc_method
from ..tools import JsonRpcInvoiceFoundError, JsonRpcError, get_settings, get_qs

log = logging.getLogger(__name__)


def build_request(typ, vendor_produk, partner_log=None, **kwargs):
    # produk_id = values['produk_id']
    # vendor_id = values['vendor_id']
    # bill_no = values['destination']
    # customer_id = 'customer_id' in values and values['customer_id'] or None
    # cust_trx_id = 'cust_trx_id' in values and values['cust_trx_id'] or None
    pckgs = 'agratek.api.merchant.views'
    moduls = vendor_produk.modules.split('.')
    if len(moduls) > 1:
        pckg = ".".join(moduls[:-1])
        pckgs = ".".join([pckgs, pckg])
        moduls = moduls[-1:]
    modul = moduls[0]
    log.info("Module: %s Pckgs: %s" % (modul, pckgs))
    modul = '.' + modul
    modules = import_module(modul, pckgs)
    cls_module = modules.Vendor(vendor_produk, partner_log, **kwargs)
    cls = hasattr(cls_module, typ) and getattr(cls_module, typ) or None
    if cls:
        result = cls()
    else:
        message = "Module %s Not Found" % vendor_produk.modules
        log.info(message)
        result = dict(message=message,
                      code=9999)
    return result


def save_partner_pay(values, vendor_produk, row=None):
    if not row:
        row = PartnerPay()

    row.from_dict(values)
    row.vendor_id = vendor_produk.partner_id
    row.produk_id = vendor_produk.produk.id
    flush_row(row)
    return row


def build_register(vendor_produk, partner_pay=None, **kwargs):
    return build_request('register', vendor_produk, partner_pay, **kwargs)


def build_payment(vendor_produk, partner_pay=None, **kwargs):
    return build_request('payment', vendor_produk, partner_pay, **kwargs)


def set_register_values(dat, customer):
    billing = dat["customer"]
    deliver_to = dat["deliver_to"]
    biller = dat["biller"]
    server = dat["server"]
    produk = 'produk' in dat and dat["produk"] or ''
    values = dict(
        customer_id=customer.id,
        # id_pel=dat['id_pel'],
        cart=produk or {},
        cust_inv_no=dat["invoice_no"],
        amt_sell=dat['amount'],
        notes=dat['description'],
        inv_cust_nm=billing['name'],
        inv_cust_phone=billing['phone'],
        inv_cust_email=billing['email'],
        inv_cust_city=billing['city'],
        inv_cust_state=billing['state'],
        inv_cust_pos=billing['post_code'],
        inv_cust_country=billing['country'],
        inv_cust_addr=billing['address'],
        inv_cust_agent=billing['agent'],
        inv_cust_ip=billing['ip'],
        inv_cust_session=billing['session_id'],

        domain=server['domain'],
        server_ip=server['ip'],
        description=dat['description'],

        delivery_addr=deliver_to['address'],
        delivery_city=deliver_to['city'],
        delivery_country=deliver_to['country'],
        delivery_nm=deliver_to['name'],
        delivery_phone=deliver_to['phone'],
        delivery_pos=deliver_to['post_code'],
        delivery_state=deliver_to['state'],
        # delivery_email=deliver_to['email'],

        biller_name = biller['name'],
        biller_phone = biller['phone'],
        biller_email = biller['email'],
        biller_address = biller['address'],
        biller_city = biller['city'],
        biller_state = biller['state'],
        biller_post_code = biller['post_code'],
        biller_country = biller['country'],

        fee=dat['fee'],
        vat=dat['vat'],
        req_dt=dat['req_dt'],
        req_tm=dat['req_tm'],
        inv_time_stamp=dat['time_stamp'] or '',
        # va
        inv_valid_date='valid_date' in dat and dat['valid_date'] or '',
        inv_valid_time='valid_time' in dat and dat['valid_time'] or '',
        inv_cust_va='cust_va' in dat and dat['cust_va'] or '',

        # m_ref_no=dat['m_ref_no'] or '',
        # notax_amt=dat['notax_amt'],
        # pay_valid_dt=dat['pay_valid_dt'],
        # pay_valid_tm=dat['pay_valid_tm'],
        # out
        # tx_id=dat['tx_id'],
        # trans_dt=dat['trans_dt'],
        # trans_tm=dat['trans_tm'],
    )
    return values


@jsonrpc_method(method='register', endpoint='api-merchant')
def register(request, data, **kwargs):
    user = auth_from_rpc(request)
    i = 0
    if not data:
        raise JsonRpcParameterNotFound

    is_list = type(data) == list
    data = is_list and data or [data]
    customer = Partner.query_user(user).first()
    if not customer:
        raise JsonRpcCustomerNotFoundError

    r_data = []
    log.info("%s Payment Request: %s" % (customer.kode, data))
    for dat in data:
        if "invoice_no" not in dat or \
                'amount' not in dat or not dat['amount']:
            dat["status"] = "FAILED"
            dat["message"] = "Parameter tidak lengkap"
            dat['code'] = -1
        else:
            inv_no = dat["invoice_no"]
            row = PartnerPay.query().filter_by(cust_inv_no=inv_no).first()
            if row and row.status > 0:
                raise JsonRpcInvoiceFoundError()

            vendor_kd = "vendor_kd" in dat and dat["vendor_kd"] or None
            produk_kd = 'denom' in dat and dat['denom'] or None
            print(produk_kd, vendor_kd)
            vendor_produk = get_vendor_produk(produk_kd, vendor_kd=vendor_kd)
            if not vendor_produk:
                raise JsonRpcProdukNotFoundError

            values = set_register_values(dat, customer)
            credit_card = "credit_card" in dat and dat["credit_card"] or {}
            if credit_card:
                values.update(dict(
                    instmnt_mon='instmnt_mon' in credit_card and credit_card['instmnt_mon'] or '',
                    instmnt_type='instmnt_type' in credit_card and credit_card['instmnt_type'] or '',
                    recurr_opt='recurr_opt' in credit_card and credit_card['recurr_opt'] or 0,
                ))
                ccard = None
            else:
                ccard = None

            va = "va" in dat and dat["va"] or {}
            if va:
                values.update(dict(
                    inv_valid_date='valid_date' in va and va['valid_date'] or '',
                    inv_valid_time='valid_time' in va and va['valid_time'] or '',
                    inv_cust_va='fix_acct_id' in va and va['fix_acct_id'] or '',
                ))

            ar_invoice = save_partner_pay(values, vendor_produk, row)
            build_register(vendor_produk, ar_invoice, ccard=ccard)
            dat.update(ar_invoice.inquiry["result"])
            # if "form" in result:
            #     dat.update(dict(form=result["form"]))
            #     # request.environ["application"]="text/html"
            #     # request.response()
            #     # return request.response

        r_data.append(dat)

    data = is_list and r_data or r_data[0]
    log.info("%s Payment Response: %s " % (customer.kode, data))
    return data


class ResultSchema(colander.Schema):
    code = colander.SchemaNode(
        colander.String(),
        widget=widget.TextInputWidget(readonly=True)
    )
    message = colander.SchemaNode(
        colander.String(),
        widget=widget.TextInputWidget(readonly=True)
    )


def form_result(request, values):
    schema = ResultSchema()
    schema.request = request
    buttons = ('ok',)
    form = Form(schema, buttons=buttons)
    form.render(values)
    return dict(form=form, params=dict(scripts=""))


class ViewData(BaseView):
    @view_config(route_name='api-merchant-payment',
                 renderer='templates/form-clean.pt')
    def view_api_merchant_payment(self):
        request = self.req
        data = request.POST and dict(request.POST.items()) or dict(request.GET.items())
        log.info("Merchant payment request: {}".format(data))
        tx_id = data["tx_id"]
        cust_inv_no = data["invoice_no"]
        invoice_det = PartnerPay.query_txid(tx_id) \
            .filter_by(cust_inv_no=cust_inv_no).first()
        if not invoice_det:
            code = 55
            values = dict(code=code,
                          message="Payment Not Found")
            return form_result(request, values)

        vendor_produk = PartnerProduk.get_produk(invoice_det.vendor_id,
                                                 invoice_det.produk_id).first()
        pckgs = 'agratek.api.merchant.views'
        moduls = vendor_produk.modules.split('.')
        if len(moduls) > 1:
            pckg = ".".join(moduls[:-1])
            pckgs = ".".join([pckgs, pckg])
            moduls = moduls[-1:]
        modul = moduls[0]

        log.info("Payment Module: %s Pckgs: %s" % (modul, pckgs))
        modul = '.' + modul
        modules = import_module(modul, pckgs)
        cls_module = modules.Vendor(vendor_produk, invoice_det)
        typ = "payment"
        cls = hasattr(cls_module, typ) and getattr(cls_module, typ) or None
        if cls:
            result = cls(data)
            # headers = {"Content-type": "application/x-www-form-urlencoded"}
            if result:
                return dict(form=result["form"])
                # qs = get_qs(result['_query'])
                # url = "{}{}".format(result['url'], qs)
                # headers = result["headers"]
                # # return form_result(request, result)
                # return HTTPFound(url, headers=headers)
        else:
            code = 55
            values = dict(code=code,
                          message="Payment Not Found")
            return form_result(request, values)

        code = 99
        values = dict(code=code,
                      message="Parameter Expected")
        return form_result(request, values)


@view_config(route_name='api-vendor-callback', renderer="templates/form-clean.pt")
def api_vendor_callback(request):
    data = request.POST and dict(request.POST.items()) or dict(request.GET.items())
    # print(data)
    vendor_nm = request.matchdict['name']
    modul = '.callback'
    pckgs = 'agratek.api.merchant.views.{}'.format(vendor_nm)
    moduls = import_module(modul, pckgs)
    typ = 'proses'
    log.info("Pckgs: {} Modul:{} typ {}".format(pckgs, modul, typ))
    cls = hasattr(moduls, typ) and getattr(moduls, typ) or None
    # print(dir(cls))
    if cls:
        result = cls(data)
        if result:
            return dict(form=result["form"])
    qs = get_qs(data)
    return HTTPFound(location=request.route_url("api-merchant-register-callback", _query=qs))
    # return dict(form="<h1>ERROR</h1>")