com.artivisi.biller.simulator.gateway.pln.PlnGateway.java Source code

Java tutorial

Introduction

Here is the source code for com.artivisi.biller.simulator.gateway.pln.PlnGateway.java

Source

/**
 * Copyright (C) 2011 ArtiVisi Intermedia <info@artivisi.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.artivisi.biller.simulator.gateway.pln;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.commons.lang.StringUtils;
import org.joda.time.format.DateTimeFormat;
import org.jpos.iso.BaseChannel;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOFilter.VetoException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.ISORequestListener;
import org.jpos.iso.ISOServer;
import org.jpos.iso.ISOSource;
import org.jpos.util.Log4JListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.artivisi.biller.simulator.entity.Pelanggan;
import com.artivisi.biller.simulator.entity.PembayaranPascabayar;
import com.artivisi.biller.simulator.entity.TagihanPascabayar;
import com.artivisi.biller.simulator.gateway.pln.constants.MTIConstants;
import com.artivisi.biller.simulator.gateway.pln.constants.ResponseCode;
import com.artivisi.biller.simulator.gateway.pln.entity.InquiryPostpaidResponse;
import com.artivisi.biller.simulator.gateway.pln.entity.InquiryPostpaidResponseDetail;
import com.artivisi.biller.simulator.gateway.pln.jpos.PlnChannel;
import com.artivisi.biller.simulator.gateway.pln.jpos.PlnPackager;
import com.artivisi.biller.simulator.gateway.pln.service.PlnService;
import com.artivisi.biller.simulator.service.BillerSimulatorService;
import com.artivisi.biller.simulator.service.PlnSimulatorService;

public class PlnGateway implements ISORequestListener {

    private static final Logger logger = LoggerFactory.getLogger(PlnGateway.class);

    @Autowired
    private PlnSimulatorService plnSimulatorService;
    @Autowired
    private BillerSimulatorService billerSimulatorService;
    @Autowired
    private PlnService plnService;

    private Integer port = 11111;
    private ISOServer server;

    public PlnGateway(Integer port) {
        this.port = port;
    }

    @PostConstruct
    public void init() {
        try {
            PlnChannel channel = new PlnChannel(new PlnPackager());
            server = new ISOServer(port, channel, null);
            server.addISORequestListener(this);

            org.jpos.util.Logger jposLogger = new org.jpos.util.Logger();
            Log4JListener log4JListener = new Log4JListener();
            log4JListener.setLevel("info");
            jposLogger.addListener(log4JListener);
            server.setLogger(jposLogger, "pln-server");
            channel.setLogger(jposLogger, "pln-channel");

            new Thread(server).start();
            logger.info("Pln Gateway started at port [{}]", port);
        } catch (Exception err) {
            logger.error(err.getMessage(), err);
        }
    }

    @PreDestroy
    public void shutdown() {
        try {
            server.shutdown();
        } catch (Exception err) {
            logger.error(err.getMessage(), err);
        }
    }

    @Override
    public boolean process(ISOSource src, ISOMsg msg) {
        try {
            logger.info("Incoming message from [{}]",
                    ((BaseChannel) src).getSocket().getInetAddress().getHostAddress());
            logger.info("Message Stream [{}]", new String(msg.pack()));

            if (MTIConstants.NETWORK_MANAGEMENT_REQUEST.equals(msg.getMTI())) {
                return handleNetworkManagementRequest(src, msg);
            }

            if (MTIConstants.INQUIRY_REQUEST.equals(msg.getMTI())) {
                return handleInquiryRequest(src, msg);
            }

            if (MTIConstants.PAYMENT_REQUEST.equals(msg.getMTI())) {
                return handlePaymentRequest(src, msg);
            }

        } catch (Exception err) {
            logger.error(err.getMessage(), err);
        }
        return false;
    }

    private boolean handlePaymentRequest(ISOSource src, ISOMsg msg) throws Exception {
        ISOMsg response = (ISOMsg) msg.clone();
        response.setMTI(MTIConstants.PAYMENT_RESPONSE);

        String bank = msg.getString(32);
        if (billerSimulatorService.findBankByKode(bank) == null) {
            logger.debug("[POSTPAID] - [PAY-REQ] - Bit 32 [{}]", bank);
            logger.error("[POSTPAID] - [PAY-REQ] - Invalid bit 32 [{}]", bank);
            response.set(39, ResponseCode.ERROR_UNREGISTERED_BANK_CODE);
            src.send(response);
            return true;
        }

        String pan = msg.getString(2);
        if (pan.length() != 5) {
            logger.error("[POSTPAID] - [PAY-REQ] - Invalid bit 2 [{}]", pan);
            response.set(39, ResponseCode.ERROR_INVALID_MESSAGE);
            src.send(response);
            return true;
        }

        String produk = pan.substring(2);
        if ("501".equals(produk)) {
            return handlePaymentPostpaid(src, msg, response);
        } else {
            logger.error("[POSTPAID] - [PAY-REQ] - Invalid produk [{}]", produk);
            response.set(39, ResponseCode.ERROR_UNREGISTERED_PRODUCT);
            src.send(response);
            return true;
        }
    }

    private boolean handleInquiryRequest(ISOSource src, ISOMsg msg) throws Exception {
        ISOMsg response = (ISOMsg) msg.clone();
        response.setMTI(MTIConstants.INQUIRY_RESPONSE);

        String bank = msg.getString(32);
        if (billerSimulatorService.findBankByKode(bank) == null) {
            logger.debug("[POSTPAID] - [INQ-REQ] - Bit 32 [{}]", bank);
            logger.error("[POSTPAID] - [INQ-REQ] - Invalid bit 32 [{}]", bank);
            response.set(39, ResponseCode.ERROR_UNREGISTERED_BANK_CODE);
            src.send(response);
            return true;
        }

        String pan = msg.getString(2);
        if (pan.length() != 5) {
            logger.error("[POSTPAID] - [INQ-REQ] - Invalid bit 2 [{}]", pan);
            response.set(39, ResponseCode.ERROR_INVALID_MESSAGE);
            src.send(response);
            return true;
        }

        String produk = pan.substring(2);
        if ("501".equals(produk)) {
            return handleInquiryPostpaid(src, msg, response);
        } else {
            logger.error("[POSTPAID] - [INQ-REQ] - Invalid produk [{}]", produk);
            response.set(39, ResponseCode.ERROR_UNREGISTERED_PRODUCT);
            src.send(response);
            return true;
        }

    }

    private boolean handlePaymentPostpaid(ISOSource src, ISOMsg msg, ISOMsg response) throws Exception {
        String bit48Request = msg.getString(48);
        if (bit48Request.length() < 55) {
            logger.error("[POSTPAID] - [PAY-REQ] - Invalid bit 48 [{}]", bit48Request);
            response.set(39, ResponseCode.ERROR_INVALID_MESSAGE);
            src.send(response);
            return true;
        }

        String plnRef = bit48Request.substring(23, 55).toLowerCase();
        InquiryPostpaidResponse daftarTagihan = plnService.findInquiryPostpaidResponse(plnRef);

        if (daftarTagihan == null) {
            logger.error("[POSTPAID] - [PAY-REQ] - Invalid PLN REF [{}]", plnRef);
            response.set(39, ResponseCode.ERROR_PLN_REFNUM_NOT_VALID);
            src.send(response);
            return true;
        }

        String switcher = bit48Request.substring(0, 7);
        Integer hold = 0;

        for (InquiryPostpaidResponseDetail detail : daftarTagihan.getDetails()) {
            PembayaranPascabayar payment = new PembayaranPascabayar();
            payment.setBank(msg.getString(32));
            payment.setLoket("");
            payment.setMerchantCategory(msg.getString(26));
            payment.setOperator("");
            payment.setSwitcher(switcher);
            payment.setTagihanPascabayar(detail.getTagihanPascabayar());
            plnSimulatorService.save(payment);

            hold = detail.getTagihanPascabayar().getPelanggan().getHoldResponse();
        }

        response.set(39, ResponseCode.SUCCESSFUL);

        try {
            logger.info("[POSTPAID] - [PAY-REQ] - Pelanggan diset untuk hold [{}]", hold);
            Thread.sleep(hold);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        src.send(response);
        return true;
    }

    private boolean handleInquiryPostpaid(ISOSource src, ISOMsg msg, ISOMsg response)
            throws ISOException, IOException, VetoException {
        String bit48Request = msg.getString(48);
        if (bit48Request.length() != 19) {
            logger.error("[POSTPAID] - [INQ-REQ] - Invalid bit 48 [{}]", bit48Request);
            response.set(39, ResponseCode.ERROR_INVALID_MESSAGE);
            src.send(response);
            return true;
        }

        String mitra = bit48Request.substring(0, 7);
        if (billerSimulatorService.findMitraByKode(mitra.trim()) == null) {
            logger.debug("[POSTPAID] - [INQ-REQ] - Mitra [{}]", mitra);
            logger.error("[POSTPAID] - [INQ-REQ] - Kode mitra tidak ditemukan [{}]", mitra);
            response.set(39, ResponseCode.ERROR_UNREGISTERED_SWITCHING);
            src.send(response);
            return true;
        }

        String idpel = bit48Request.substring(7);
        Pelanggan p = plnSimulatorService.findPelangganByIdpel(idpel);
        if (p == null) {
            logger.error("[POSTPAID] - [INQ-REQ] - IDPEL tidak ditemukan [{}]", idpel);
            response.set(39, ResponseCode.ERROR_UNKNOWN_SUBSCRIBER);
            src.send(response);
            return true;
        }

        if (!ResponseCode.SUCCESSFUL.equals(p.getResponseCode())) {
            logger.error("[POSTPAID] - [INQ-REQ] - Pelanggan diset untuk RC [{}]", p.getResponseCode());
            response.set(39, p.getResponseCode());
            src.send(response);
            return true;
        }

        List<TagihanPascabayar> daftarTagihan = plnSimulatorService.findTagihan(p);
        if (daftarTagihan.size() < 1) {
            logger.error("[POSTPAID] - [INQ-REQ] - Tagihan untuk idpel [{}] tidak ada", idpel);
            response.set(39, ResponseCode.ERROR_CURRENT_BILL_IS_NOT_AVAILABLE);
            src.send(response);
            return true;
        }

        List<TagihanPascabayar> tagihanDikirim;
        if (daftarTagihan.size() > 4) {
            tagihanDikirim = daftarTagihan.subList(0, 4);
        } else {
            tagihanDikirim = daftarTagihan;
        }

        BigDecimal amount = BigDecimal.ZERO;
        for (TagihanPascabayar tagihanPascabayar : tagihanDikirim) {
            amount = amount.add(tagihanPascabayar.getBill());
            amount = amount.add(tagihanPascabayar.getDenda());
        }

        response.set(4,
                "360" + "0" + StringUtils.leftPad(amount.setScale(0, RoundingMode.HALF_EVEN).toString(), 12, "0"));

        InquiryPostpaidResponse ipr = new InquiryPostpaidResponse();
        ipr.setBank(msg.getString(32));
        ipr.setSwitcher(mitra);
        ipr.setStan(msg.getString(11));

        for (TagihanPascabayar tagihanPascabayar : tagihanDikirim) {
            InquiryPostpaidResponseDetail detail = new InquiryPostpaidResponseDetail();
            detail.setTagihanPascabayar(tagihanPascabayar);
            detail.setInquiryPostpaidResponse(ipr);
            ipr.getDetails().add(detail);
        }

        plnService.save(ipr);

        StringBuffer bit48Response = createBit48InquiryPostpaidResponse(bit48Request, p, daftarTagihan,
                tagihanDikirim, ipr);

        response.set(39, ResponseCode.SUCCESSFUL);
        response.set(48, bit48Response.toString());

        try {
            logger.info("[POSTPAID] - [INQ-REQ] - Pelanggan diset untuk hold [{}]", p.getHoldResponse());
            Thread.sleep(p.getHoldResponse());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        src.send(response);
        return true;
    }

    private StringBuffer createBit48InquiryPostpaidResponse(String bit48Request, Pelanggan p,
            List<TagihanPascabayar> daftarTagihan, List<TagihanPascabayar> tagihanDikirim,
            InquiryPostpaidResponse ipr) {
        StringBuffer bit48Response = new StringBuffer();
        bit48Response.append(bit48Request);
        bit48Response.append(tagihanDikirim.size());
        bit48Response.append(StringUtils.leftPad(String.valueOf(daftarTagihan.size()), 2, "0"));
        bit48Response.append(ipr.getId().toUpperCase());
        bit48Response.append(StringUtils.rightPad(p.getNama(), 25, " "));
        bit48Response.append(StringUtils.rightPad(p.getServiceUnit(), 5, " "));
        bit48Response.append(StringUtils.rightPad(p.getServiceUnitPhone(), 15, " "));
        bit48Response.append(StringUtils.rightPad(p.getSubscriberSegmentation(), 4, " "));
        bit48Response.append(StringUtils.leftPad(p.getPowerConsumingCategory(), 9, "0"));
        bit48Response.append(StringUtils.leftPad("", 9, "0")); // total admin charges

        for (TagihanPascabayar t : tagihanDikirim) {
            bit48Response.append(DateTimeFormat.forPattern("yyyyMM").print(t.getBillPeriod().getTime()));
            bit48Response.append(DateTimeFormat.forPattern("ddMMyyyy").print(t.getDueDate().getTime()));
            bit48Response.append(DateTimeFormat.forPattern("ddMMyyyy").print(t.getMeterReadDate().getTime()));
            bit48Response.append(
                    StringUtils.leftPad(t.getBill().setScale(0, RoundingMode.HALF_EVEN).toString(), 11, "0"));
            if (BigDecimal.ZERO.compareTo(t.getInsentif()) > 0) {
                bit48Response.append("D");
            } else {
                bit48Response.append("C");
            }
            bit48Response.append(StringUtils
                    .leftPad(t.getInsentif().abs().setScale(0, RoundingMode.HALF_EVEN).toString(), 10, "0"));
            bit48Response.append(
                    StringUtils.leftPad(t.getVat().setScale(0, RoundingMode.HALF_EVEN).toString(), 10, "0"));
            bit48Response.append(
                    StringUtils.leftPad(t.getDenda().setScale(0, RoundingMode.HALF_EVEN).toString(), 10, "0"));
            bit48Response.append(StringUtils.leftPad(t.getPreviousMeterRead1(), 8, "0"));
            bit48Response.append(StringUtils.leftPad(t.getCurrentMeterRead1(), 8, "0"));
            bit48Response.append(StringUtils.leftPad(t.getPreviousMeterRead2(), 8, "0"));
            bit48Response.append(StringUtils.leftPad(t.getCurrentMeterRead2(), 8, "0"));
            bit48Response.append(StringUtils.leftPad(t.getPreviousMeterRead3(), 8, "0"));
            bit48Response.append(StringUtils.leftPad(t.getCurrentMeterRead3(), 8, "0"));
        }
        return bit48Response;
    }

    private boolean handleNetworkManagementRequest(ISOSource src, ISOMsg msg) throws Exception {
        ISOMsg response = (ISOMsg) msg.clone();
        response.setMTI(MTIConstants.NETWORK_MANAGEMENT_RESPONSE);
        response.set(39, ResponseCode.SUCCESSFUL);
        src.send(response);
        return true;
    }
}