bjb_qris.py 7.17 KB
from sqlalchemy import (
    Column,
    Integer,
    Text,
    DateTime,
    ForeignKey,
    UniqueConstraint,
    String,
    SmallInteger,
    BigInteger,
    Float,
    Date,
    )
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm import (
    relationship,
    backref
    )
from ..models import (NamaModel, Base, DBSession, CommonModel, KodeModel, TABLE_ARGS, User)
import requests
import json
import sys
from .rpc import json_rpc_header, get_jsonrpc
from ..tools import date_from_str, ymd, ymdhms
import logging
log = logging.getLogger('BJBQRIS LOG')
from datetime import datetime, date, timedelta,time
        
def datetime_from_str(values):
    separator = None
    values = values.split()
    value = values[0]  # dd-mm-yyyy HH:MM:SS
        
    tgl = date_from_str(value)
    t = [0,0,0]
    if len(values) > 1:
        t = values[1].split(':')

    return datetime(tgl.year, tgl.month, tgl.day, int(t[0]), int(t[1]), int(t[2]))

def cek_parameter(parameter):
    if not parameter['bjbqris_url']:
        log.error('bjbqris_url parameter belum ada')
        return
    if not parameter['bjbqris_user']:
        log.error('bjbqris_user parameter belum ada')
        return
    if not parameter['bjbqris_key']:
        log.error('bjbqris_key parameter belum ada')
        return
    return True
        
class BJBQRIS(KodeModel, Base):
    __tablename__   = 'bjb_qris'
    id              = Column(Integer, primary_key=True)
    client_type     = Column(SmallInteger)
    ## 0: VA Offline
    ## 1: Ecommerce
    ## 2: Edupay
    ## 3: Pajak
    ## 4: Rumah Sakit
    invoice_no      = Column(String(16))
    product_code    = Column(String(2))
    ## 01 = BPHTB
    ## 02 = PBB
    ## 05 = SAMSAT
    ## 10 = PDL
    ## 30 = WEBR
    ## 90 = PERIZINAN
    description        = Column(String(128))
    customer_name      = Column(String(64))
    customer_email     = Column(String(128))
    customer_phone     = Column(String(32))
    client_refnum      = Column(String(128))
    expired_date       = Column(DateTime)
    amount             = Column(BigInteger)
                       
    billing_type       = Column(String(1))
    ## o = open payment
    ## f = fixed payment
    va_type            = Column(String(1))
    va_number          = Column(String(32))
    currency           = Column(String(3))
    customer_id        = Column(String(32))
    status             = Column(String(1), server_default='0') 
    ## 0 = belum dibayar
    ## 1 = dibayar sebagian
    ## 2 = dibayar penuh
    ## 3 = kadaluarsa
    ## 4 = disabled
    cin                = Column(String(4))
    response_code      = Column(String(4))
    response_message   = Column(String(128))
    qrcode             = Column(Text)
    
    type                 = Column(String(64))
    merchantName         = Column(String(128))
    transactionDate      = Column(DateTime)
    transactionStatus    = Column(String(64))
    transactionAmount    = Column(BigInteger)
    transactionReference = Column(String(128))
    paymentReference     = Column(String(64))
    merchantBalance      = Column(String(255))
    merchantMsisdn       = Column(String(128))
    merchantEmail        = Column(String(64))
    merchantMpan         = Column(String(64))
    rrn                  = Column(String(64))
    customerName         = Column(String(128))
    invoiceNumber        = Column(String(128))
    
    created  = Column(DateTime, nullable=False, default=datetime.now,server_default='now()')
    updated  = Column(DateTime)
    create_uid  = Column(Integer, nullable=False, default=1,server_default='1')
    update_uid  = Column(Integer),

    __table_args__ = TABLE_ARGS

    @classmethod
    def save(cls, values, row=None, **kwargs):
        if not row:
            row = cls()
        row.from_dict(values)
        if 'transaction_date' in values and not isinstance(values['transaction_date'], datetime):
                values['transaction_date'] = datetime_from_str(values['transaction_date'])
        DBSession.add(row)
        DBSession.flush()
        return row
        
    @classmethod
    def create_va(cls, values, parameter):
        cek = cek_parameter(parameter)
        if not cek:
            return False
        expdate = datetime_from_str(values['expired_date'])
        if expdate > datetime.combine(date.today(),time(20,59,59)):
            expdate = ymdhms(datetime.combine(date.today(),time(20,59,59)))
        data = dict(
            client_type     = values['client_type'],
            invoice_no      = str(values['invoice_no']),
            product_code    = str(values['product_code']),
            description     = str(values['description']),
            customer_name   = str(values['customer_name']),
            customer_email  = str(values['customer_email']),
            customer_phone  = str(values['customer_phone']),
            expired_date    = str(values['expired_date']),
            amount          = str(values['amount'])
        )

        datava = send_rpc(parameter, 'create', data)
        if not datava:
            return False
        try:
            if 'error' in datava:
                return datava
        except:
            pass
        saved = cls.save(datava)
        return saved
        
    @classmethod
    def cancel_qris(cls, values, parameter):
        cek = cek_parameter(parameter)
        if not cek:
            return False
            
        row = cls.query().filter(cls.invoice_no==values['invoice_no'],cls.status=='0').all()
        qrisnum = [r.va_number for r in row]
        data = dict(
            va_number       = values['va_number'],
            client_type     = values['client_type'],
            invoice_no      = values['invoice_no'],
            product_code    = values['product_code'],
            description     = values['description'],
            customer_name   = values['customer_name'],
            customer_email  = values['customer_email'],
            customer_phone  = values['customer_phone'],
            amount          = str(values['amount']),
            va_type         = 'q'
        )
        datava = send_rpc(parameter, 'cancel', data)
        if not datava:
            return False
        datava['status'] = '4'
        saved = DBSession.query(cls).filter(cls.va_number.in_(qrisnum)).\
             update({cls.status: '4'}, synchronize_session='fetch')
        return saved
            
def send_rpc(parameter, method, data):
    headers = json_rpc_header(parameter['bjbqris_user'],parameter['bjbqris_key'])
    params = get_jsonrpc(method, dict(data=data))
    log.error("REQ TO QRIS")
    log.error(json.dumps(params))
    try:
        resp = requests.post(url=parameter['bjbqris_url'], 
                    data=json.dumps(params), 
                    headers=headers)
        try:
            datava = json.loads(resp.content)
            log.error("RESPONSE FROM QRIS")
            log.error(resp.text)
            if 'error' in datava:
                log.error(resp.content)
            return datava['result']['data']
        except:
            log.error('Response Error')
            log.error(resp.content)
            return False
        
        return False
        
    except requests.exceptions.RequestException as err:
        log.error('Gagal membuat koneksi, silakan coba lagi beberapa saat')
        return False