Subversion Repositories SmartDukaan

Rev

Rev 6091 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package in.shop2020.serving.controllers;

import in.shop2020.config.ConfigException;
import in.shop2020.datalogger.EventType;
import in.shop2020.model.v1.order.RechargeOrder;
import in.shop2020.model.v1.order.RechargeOrderStatus;
import in.shop2020.model.v1.order.TransactionServiceException;
import in.shop2020.payments.Attribute;
import in.shop2020.payments.Payment;
import in.shop2020.payments.PaymentException;
import in.shop2020.payments.PaymentStatus;
import in.shop2020.serving.services.CommonPaymentService;
import in.shop2020.serving.utils.ebs.Base64;
import in.shop2020.serving.utils.ebs.RC4;
import in.shop2020.thrift.clients.PaymentClient;
import in.shop2020.thrift.clients.TransactionClient;
import in.shop2020.thrift.clients.UserClient;
import in.shop2020.thrift.clients.config.ConfigClient;
import in.shop2020.utils.DataLogger;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.apache.thrift.TException;

@SuppressWarnings("serial")
public class EbsPayResponseController extends BaseController{

        private static Logger log = Logger.getLogger(Class.class);

        private static final String FLAG_KEY = "IsFlagged";
        private static final String TXN_KEY = "TransactionID";
        private static final String AUTH_TXN_ID = "AuthTxnId";

        private static String successUrl;
        private static String errorUrl;
        private static String rechargeResultUri;

        /**
         * The secret key used to decode RC4 encoded data.
         */
        private static String accountKey;

        private String redirectUrl;

        static{
                try {
                        successUrl = ConfigClient.getClient().get("ebs_success_url");
                        errorUrl = ConfigClient.getClient().get("ebs_error_url");
                        setRechargeResultUri(ConfigClient.getClient().get("recharge_success_url"));
                        accountKey = ConfigClient.getClient().get("ebs_secret_key");
                } catch (ConfigException e) {
                        log.error("Unable to get success and error usr info from config server.");
                }
        }

        private Map<String, String> paymentParams = new TreeMap<String, String>();

        public String index() {
                StringBuffer data1 = new StringBuffer(request.getParameter("DR"));
                log.info("Received data string: " + data1.toString());
                byte[] result = decodeRecvdData(data1);

                String recvString = parseRecvdData(result);
                updatePaymentParams(recvString);

                PaymentClient paymentServiceClient = null;
                TransactionClient transactionServiceClient = null;
                UserClient userServiceClient = null;
                try {
                        paymentServiceClient = new PaymentClient();
                        transactionServiceClient = new TransactionClient();
                        userServiceClient = new UserClient();
                } catch (Exception e) {
                        log.error("Unable to initialize one of the clients", e);
                }


                long merchantPaymentId = Long.parseLong(paymentParams.get("MerchantRefNo"));
                String gatewayPaymentId = paymentParams.get("PaymentID");
                double amount = Double.parseDouble(paymentParams.get("Amount"));
                String isFlagged = paymentParams.get(FLAG_KEY);
                String gatewayTxnStatus = paymentParams.get("ResponseCode");
                String description = paymentParams.get("ResponseMessage");
                String authTxnId = paymentParams.get(TXN_KEY);


                List<Attribute> attributes = new ArrayList<Attribute>();
                attributes.add(new Attribute(FLAG_KEY, isFlagged));
                attributes.add(new Attribute(AUTH_TXN_ID, authTxnId));

                Payment payment = null;
                Long txnId = null;
                try {
                        payment = paymentServiceClient.getClient().getPayment(merchantPaymentId);
                        txnId = payment.getMerchantTxnId();
                } catch (PaymentException e1) {
                        log.error("Payment exception. It is serious, check merchant payment id + " + merchantPaymentId, e1);
                } catch (TException e1) {
                        log.error("Thrift exception. Check payment id "+ merchantPaymentId, e1);
                }

                if(payment.getStatus() != PaymentStatus.INIT){
                        // We have already processed a response for this payment. Processing
                        // it again may fail his orders. So, let's ask him to check his
                        // account.
                        return "maybe";
                }

                if(!validatePaymentParams(amount, payment)){
                        this.redirectUrl = errorUrl + "?paymentId=" + merchantPaymentId;
                        return "index";
                }

                if(gatewayTxnStatus.equals("0")){
                        //Update payment status as authorized if payment is authorized.
                        try {
                                paymentServiceClient.getClient().updatePaymentDetails(merchantPaymentId, gatewayPaymentId,
                                                "", gatewayTxnStatus, description, "", "", "", "", PaymentStatus.AUTHORIZED, "", attributes);
                        } catch (PaymentException e) {
                                log.error("Unable to mark the payment as authorized", e);
                        } catch (TException e) {
                            log.error("Unable to mark the payment as authorized", e);
                        }
                        
                        if(payment.isIsDigital()) {
                            RechargeOrder rechargeOrder = null;
                try {
                    rechargeOrder = transactionServiceClient.getClient().getRechargeOrdersForTransaction(txnId);
                } catch (Exception e1) {
                    log.error("Problem with txn client while getting recharge object", e1);
                }
                            if(!isFlagged.equals("YES")) {
                                //Recharge only when payment is digital and is captured and is not flagged 
                                try {
                                    PaymentClient pcl = new PaymentClient();
                                    boolean isCaptured = pcl.getClient().capturePayment(txnId, true);
                                    
                                    //Retry in case we are not able to capture first time
                                    if(!isCaptured){
                                        Thread.sleep(2000);
                                        isCaptured = pcl.getClient().capturePayment(txnId, true);
                                    }
                                    if(!isCaptured){
                                        Thread.sleep(2000);
                                        isCaptured = pcl.getClient().capturePayment(txnId, true);
                                    }
                                    
                                    if(isCaptured) {
                                        transactionServiceClient.getClient().updateRechargeOrderStatus(rechargeOrder.getId(), RechargeOrderStatus.PAYMENT_SUCCESSFUL);
                                    } else {
                                transactionServiceClient.getClient().updateRechargeOrderStatus(rechargeOrder.getId(), RechargeOrderStatus.PAYMENT_FAILED);
                                    }
                                } catch (Exception e) {
                                    log.error("Problem with txn client while trying to recharge", e);
                                }
                            } else {
                                try {
                                    transactionServiceClient.getClient().updateRechargeOrderStatus(rechargeOrder.getId(), RechargeOrderStatus.PAYMENT_FAILED);
                    } catch (Exception e) {
                        log.error("Problem with txn client while trying to mark payment failed in recharge order", e);
                    }
                            }
                            this.redirectUrl = rechargeResultUri + "?paymentId=" + merchantPaymentId;
                        } else {
                            //For physical orders
                            if(isFlagged.equals("YES")){
                                CommonPaymentService.processSuccessfulTxn(txnId, userServiceClient, transactionServiceClient, true);
                                this.redirectUrl = successUrl + "?paymentId=" + merchantPaymentId;
                            }else{
                                CommonPaymentService.processSuccessfulTxn(txnId, userServiceClient, transactionServiceClient, false);
                                this.redirectUrl = successUrl + "?paymentId=" + merchantPaymentId;      
                            }
                        }
                        
                        
//                      Map<String, String> captureResult = EbsPaymentService.capturePayment(payment, gatewayPaymentId);
//                      String captureStatus = captureResult.get(IPaymentService.STATUS);
//
//                      if("".equals(captureStatus)){
//                              //Failure
//                              description = captureResult.get(EbsPaymentService.ERROR);
//                              String errorCode = captureResult.get(EbsPaymentService.ERR_CODE);
//                              try {
//                                      paymentServiceClient.getClient().updatePaymentDetails(merchantPaymentId, gatewayPaymentId,
//                                                      "", gatewayTxnStatus, description, "", "", "", errorCode, PaymentStatus.FAILED, "", attributes);
//                              } catch (PaymentException e) {
//                                      log.error("Error while updating failed capture payment attempt: ", e);
//                              } catch (TException e) {
//                                      log.error("Error while updating failed capture payment attempt: ", e);
//                              }
//                              DataLogger.logData(EventType.PAYMENT_FAILURE, getSessionId(), userinfo.getUserId(), userinfo.getEmail(), Long.toString(merchantPaymentId), gatewayPaymentId,
//                        gatewayTxnStatus, description, errorCode);
//                              this.redirectUrl = errorUrl + "?paymentId=" + merchantPaymentId;
//                      }else{
//                              //Success
//                              try {
//                                      attributes.add(new Attribute(IPaymentService.CAPTURE_TXN_ID, captureResult.get(IPaymentService.CAPTURE_TXN_ID)));
//                                      attributes.add(new Attribute(IPaymentService.CAPTURE_TIME, captureResult.get(IPaymentService.CAPTURE_TIME)));
//
//                                      paymentServiceClient.getClient().updatePaymentDetails(merchantPaymentId, gatewayPaymentId,
//                                                      "", captureStatus, description, "", "", "", "", PaymentStatus.SUCCESS, "", attributes);
//                              } catch (PaymentException e) {
//                                      log.error("Error while updating successful capture payment attempt: ", e);
//                              } catch (TException e) {
//                                      log.error("Error while updating successful capture payment attempt: ", e);
//                              }
//
//                              CommonPaymentService.processSuccessfulTxn(txnId, userServiceClient, transactionServiceClient);
//
//                              this.redirectUrl = successUrl + "?paymentId=" + merchantPaymentId;
//                      }
                }else{
                        try {
                                paymentServiceClient.getClient().updatePaymentDetails(merchantPaymentId, gatewayPaymentId,
                                                "", gatewayTxnStatus, description, "", "", "", "", PaymentStatus.FAILED, "", attributes);
                        } catch (PaymentException e) {
                            log.error("Unable to mark the payment as failed", e);
                        } catch (TException e) {
                            log.error("Unable to mark the payment as failed", e);
                        }
                        if(!payment.isIsDigital()) {
                        CommonPaymentService.processFailedTxn(txnId, transactionServiceClient);
                        DataLogger.logData(EventType.PAYMENT_FAILURE, getSessionId(), userinfo.getUserId(), userinfo.getEmail(), Long.toString(merchantPaymentId), gatewayPaymentId,
                    gatewayTxnStatus, description);

                        this.redirectUrl = errorUrl + "?paymentId=" + merchantPaymentId;
                        } else {
                            this.redirectUrl = rechargeResultUri + "?paymentId=" + merchantPaymentId;
                        }
                }

                log.info("User will be redirected to: " + this.redirectUrl);
                return "index";
        }

        private boolean validatePaymentParams(double returnedAmount, Payment payment){
                if(!(payment != null && Math.abs(payment.getAmount() - returnedAmount) <= 0.50)){
                        // We did not request this payment or the authorised amount is different.
                        log.error("Checks and balance failed on returned data");
                        return false;
                }
                return true;
        }

        private byte[] decodeRecvdData(StringBuffer data1) {
                for (int i = 0; i < data1.length(); i++) {
                        if (data1.charAt(i) == ' ')
                                data1.setCharAt(i, '+');
                }

                Base64 base64 = new Base64();
                byte[] data = base64.decode(data1.toString());
                RC4 rc4 = new RC4(accountKey);
                byte[] result = rc4.rc4(data);
                return result;
        }

        private String parseRecvdData(byte[] result) {
                ByteArrayInputStream byteIn = new ByteArrayInputStream(result, 0, result.length);
                BufferedReader reader = new BufferedReader(new InputStreamReader(byteIn));
                String recvString1 = "";
                String recvString = "";
                try {
                        recvString1 = reader.readLine();
                        int lineCount = 0;
                        while (recvString1 != null) {
                                lineCount++;
                                if (lineCount > 705)
                                        break;
                                recvString += recvString1 + "\n";
                                recvString1 = reader.readLine();
                        }
                } catch (IOException e) {
                        log.error("Unable to read from Ebs response", e);
                }
                recvString = recvString.replace("=&", "=--&");
                return recvString;
        }

        private void updatePaymentParams(String str){
                StringTokenizer st = new StringTokenizer(str, "=&");
                String key, value;
                while(st.hasMoreTokens()) {
                        key = st.nextToken();
                        value = st.nextToken();
                        log.info("Key: " + key + ", Value: " + value);
                        paymentParams.put(key, value);
                }
        }

        public String getRedirectUrl(){
                return this.redirectUrl;
        }

        @Override
        public void setServletRequest(HttpServletRequest request) {
                this.request = request;
        }

        public Map<String, String> getPaymentParams() {
                return paymentParams;
        }

    public static void setRechargeResultUri(String rechargeResultUri) {
        EbsPayResponseController.rechargeResultUri = rechargeResultUri;
    }

    public static String getRechargeResultUri() {
        return rechargeResultUri;
    }
}