Subversion Repositories SmartDukaan

Rev

Rev 3282 | Rev 3578 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1946 chandransh 1
package in.shop2020.payment.service.handler;
2
 
3010 chandransh 3
import java.text.SimpleDateFormat;
1946 chandransh 4
import java.util.ArrayList;
5
import java.util.Date;
6
import java.util.HashMap;
7
import java.util.List;
8
import java.util.Map;
9
 
10
import org.apache.thrift.TException;
3010 chandransh 11
import org.slf4j.Logger;
12
import org.slf4j.LoggerFactory;
1946 chandransh 13
import org.springframework.context.ApplicationContext;
14
import org.springframework.context.support.ClassPathXmlApplicationContext;
15
 
2747 chandransh 16
import in.shop2020.payment.domain.Refund;
1946 chandransh 17
import in.shop2020.payment.handler.PaymentGatewayHandler;
18
import in.shop2020.payment.handler.PaymentHandler;
2747 chandransh 19
import in.shop2020.payment.handler.RefundHandler;
1946 chandransh 20
import in.shop2020.payments.Attribute;
21
import in.shop2020.payments.Payment;
22
import in.shop2020.payments.PaymentException;
23
import in.shop2020.payments.PaymentGateway;
24
import in.shop2020.payments.PaymentService.Iface;
25
import in.shop2020.payments.PaymentStatus;
26
 
27
public class PaymentServiceHandler implements Iface {
3010 chandransh 28
 
29
    private static Logger logger = LoggerFactory.getLogger(PaymentServiceHandler.class);
30
 
31
    /**
32
     * Enum of all statuses that can be returned by the HDFC gateway
33
     * 
34
     * @author Chandranshu
35
     * 
36
     */
37
    private enum HdfcPaymentReturnStatus{
38
        APPROVED("APPROVED"),
39
        NOT_APPROVED("NOT APPROVED"),
40
        CAPTURED("CAPTURED"),
41
        NOT_CAPTURED ("NOT CAPTURED"),
42
        CANCELLED ("CANCELLED"),
43
        DENIED_BY_RISK("DENIED BY RISK"),
44
        HOST_TIMEOUT("HOST TIMEOUT");
45
        private String value;
46
        HdfcPaymentReturnStatus(String value) {
47
            this.value = value;
48
        }
49
        public String value(){
50
            return this.value;
51
        }
52
    }
53
 
2391 chandransh 54
	public static final long PAYMENT_NOT_CREATED = -1;
55
 
3010 chandransh 56
	private static final long HDFC_GATEWAY_ID = 1;
57
	private static final long EBS_GATEWAY_ID = 2;
58
 
1946 chandransh 59
	ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
60
	PaymentHandler paymentHandler = (PaymentHandler) context.getBean("paymentHandler");
61
	PaymentGatewayHandler paymentGatewayHandler = (PaymentGatewayHandler) context.getBean("paymentGatewayHandler");
2747 chandransh 62
	RefundHandler refundHandler = (RefundHandler) context.getBean("refundHandler");
1946 chandransh 63
 
64
	@Override
65
	public void closeSession() throws TException {
66
		// TODO Auto-generated method stub		
67
	}
68
 
69
	@Override
70
	public long createPayment(long userId, double amount, long gatewayId, long txnId) throws PaymentException, TException {
3010 chandransh 71
	    logger.info("Creating payment corresponding to our txn id:" + txnId);
1946 chandransh 72
		in.shop2020.payment.domain.Payment payment = new in.shop2020.payment.domain.Payment();
73
		payment.setUserId(userId);
74
		payment.setAmount(amount);
75
		payment.setGatewayId(gatewayId);
76
		payment.setMerchantTxnId(txnId);
77
		payment.setStatus(PaymentStatus.INIT.getValue());
78
 
79
		return paymentHandler.insertPayment(payment);
80
	}
81
 
82
	@Override
83
	public List<Payment> getPaymentsForUser(long userId, long fromTime, long toTime, PaymentStatus status, long gatewayId) throws PaymentException, TException {
3010 chandransh 84
	    logger.info("Getting payments from " + fromTime + " to " + toTime + " for user: " + userId);
2291 chandransh 85
		int statusValue = -1;
86
		if(status != null)
87
			statusValue = status.getValue();
88
		else
89
			statusValue = -1;
90
		return getThriftPayments(paymentHandler.getPaymentsForUser(userId, fromTime, toTime, statusValue, gatewayId));
1946 chandransh 91
	}
92
 
93
	@Override
94
	public List<Payment> getPayments(long fromTime, long toTime, PaymentStatus status, long gatewayId) throws PaymentException,	TException {
3010 chandransh 95
	    logger.info("Getting payments from " + fromTime + " to " + toTime);
2291 chandransh 96
		int statusValue = -1;
97
		if(status != null)
98
			statusValue = status.getValue();
99
		else
100
			statusValue = -1;
101
		return getThriftPayments(paymentHandler.getPayments(fromTime, toTime, statusValue, gatewayId));
1946 chandransh 102
	}
103
 
104
	@Override
105
	public PaymentGateway getPaymentGateway(long id) throws PaymentException, TException {
3010 chandransh 106
	    logger.info("Getting payment gateway with id:" + id);
2291 chandransh 107
		return paymentGatewayHandler.getPaymentGateway(id).getThriftPaymentGateway();
1946 chandransh 108
	}
109
 
110
	@Override
111
	public Payment getPayment(long id) throws PaymentException, TException {
3010 chandransh 112
	    logger.info("Getting payment with id: " + id);
1946 chandransh 113
		return paymentHandler.getPayment(id).getThriftPayment();
114
	}
115
 
116
	@Override
117
	public List<Payment> getPaymentForTxnId(long txnId) throws PaymentException, TException {
3010 chandransh 118
	    logger.info("Getting payment for the txn id: " + txnId);
1946 chandransh 119
		return getThriftPayments(paymentHandler.getPaymentForTxn(txnId));
120
	}
121
 
122
	@Override
123
	public boolean updatePaymentDetails(long id, String gatewayPaymentId,
124
			String sessionId, String gatewayTxnStatus, String description,
125
			String gatewayTxnId, String authCode, String referenceCode,
126
			String errorCode, PaymentStatus status, String gatewayTxnDate,
127
			List<Attribute> attributes) throws PaymentException, TException {
3010 chandransh 128
	    logger.info("Updating details of payment id: " + id);
1946 chandransh 129
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(id);
130
		payment.setGatewayPaymentId(gatewayPaymentId);
131
		payment.setSessionId(sessionId);
132
		payment.setGatewayTxnStatus(gatewayTxnStatus);
133
		payment.setDescription(description);
134
		payment.setGatewayTxnId(gatewayTxnId);
135
		payment.setAuthCode(authCode);
136
		payment.setReferenceCode(referenceCode);
137
		payment.setErrorCode(errorCode);
138
		if(status!=null){
139
			payment.setStatus(status.getValue());
140
			if(status.equals(PaymentStatus.SUCCESS))
141
				payment.setSuccessTimestamp(new Date());
142
			else if(status.equals(PaymentStatus.FAILED))
143
				payment.setErrorTimestamp(new Date());
144
		}
145
 
146
		payment.setGatewayTxnDate(gatewayTxnDate);
147
 
148
		Map<String, String> attrMap = new HashMap<String, String>();
2272 rajveer 149
		if(attributes != null){
150
			for(Attribute attribute : attributes){
151
				attrMap.put(attribute.getName(), attribute.getValue());
152
			}
1946 chandransh 153
		}
154
 
155
		paymentHandler.updatePayment(payment, attrMap);
156
		return true;
157
	}
158
 
159
	@Override
160
	public List<Double> getSuccessfulPaymentsAmountRange() throws TException {
3010 chandransh 161
	    logger.info("Getting the range of successful payments.");
1946 chandransh 162
		List<Double> minMaxAmounts = new ArrayList<Double>();
163
		Map<String, Float> minMax = paymentHandler.getMinMaxPaymentAmount();
164
		minMaxAmounts.add(Double.parseDouble(Float.toString(minMax.get("MIN"))));
165
		minMaxAmounts.add(Double.parseDouble(Float.toString(minMax.get("MAX"))));
166
		return minMaxAmounts;
167
	}
168
 
2391 chandransh 169
	@Override
170
	public String initializeHdfcPayment(long merchantPaymentId) throws PaymentException, TException {
3010 chandransh 171
	    logger.info("Initializing HDFC payment with id: " + merchantPaymentId);
2391 chandransh 172
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
173
		String redirectURL;
174
		try {
175
			redirectURL = HdfcPaymentHandler.initializeHdfcPayment(payment, this);
176
		} catch (Exception e) {
177
			throw new PaymentException(102, "Error while initiliazing payment. Check service log for more details.");
178
		}
179
		return redirectURL;
180
	}
181
 
182
	@Override
2708 chandransh 183
	public Map<String, String> captureHdfcPayment(long merchantPaymentId) throws PaymentException, TException {
3010 chandransh 184
	    logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
2391 chandransh 185
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
186
		return HdfcPaymentHandler.capturePayment(payment);
187
	}
188
 
2689 chandransh 189
	@Override
2708 chandransh 190
	public Map<String, String> captureEbsPayment(long merchantPaymentId) throws PaymentException, TException {
3010 chandransh 191
	    logger.info("Capturing EBS payment with id: " + merchantPaymentId);
2708 chandransh 192
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
3010 chandransh 193
		return EbsPaymentHandler.capturePayment(payment);
2708 chandransh 194
	}
195
 
196
	@Override
2689 chandransh 197
    public long createRefund(long orderId, long merchantTxnId, double amount) throws PaymentException, TException{
3010 chandransh 198
	    logger.info("Attempting to create a refund for order: " + orderId);
2689 chandransh 199
		List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
200
		if(payments ==null || payments.isEmpty())
201
			throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
202
 
3010 chandransh 203
		in.shop2020.payment.domain.Payment payment = payments.get(0);
2689 chandransh 204
		if(payment.getStatus() != PaymentStatus.SUCCESS.getValue())
205
			throw new PaymentException(104, "No successful payments found corresponding to the merchant txn " + merchantTxnId);
206
 
2747 chandransh 207
		Refund refund = new Refund();
208
		refund.setOrderId(orderId);
209
		refund.setPaymentId(payment.getId());
210
		refund.setGatewayId(payment.getGatewayId());
211
		refund.setAmount(amount);
212
		refund.setAttempts(0);
213
		return refundHandler.createRefund(refund);
2689 chandransh 214
    }
215
 
3010 chandransh 216
    @Override
217
    public boolean capturePayment(long merchantTxnId) throws PaymentException, TException {
218
        logger.info("Attempting to capture payment corresponding to our transaction " + merchantTxnId);
219
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
220
        if(payments ==null || payments.isEmpty())
221
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
222
 
223
        in.shop2020.payment.domain.Payment payment = payments.get(0);
224
        switch(PaymentStatus.findByValue(payment.getStatus())){
225
        case PENDING:
226
            logger.error("Attempt to capture a non-authorized payment");
227
            return false;
228
        case INIT:
229
            logger.warn("Attempt to capture a non-authorized payment");
230
            return false;
231
        case AUTHORIZED:
232
            //Actual work to be done in this case. Let the call proceed.
233
            break;
234
        case SUCCESS:
235
            logger.warn("Attempting to capture an already captured payment but we can let the client proceed.");
236
            return true;
237
        case FAILED:
238
            logger.error("Attempting to capture a failed payment");
239
            return false;
240
        }
241
 
242
        long gatewayId = payment.getGatewayId();
243
 
244
        if(gatewayId == HDFC_GATEWAY_ID){
245
            //Capture and update the HDFC payment
246
            return captureAndUpdateHdfcPayment(payment);
247
        } else if (gatewayId == EBS_GATEWAY_ID){
248
            //Capture and update the EBS payment
249
            return captureAndUpdateEbsPayment(payment);
250
        }
251
 
252
        logger.error("We have an authorized payment from unknown gateway: " + gatewayId);
253
        return false;
254
    }
255
 
256
    /**
257
     * Capture the HDFC payment represented by the given payment object. If the
258
     * capture attempt is not successful, we mark this payment as failed. We
259
     * don't retry or anything. We'll add the support of multiple attempts later
260
     * on.
261
     * 
262
     * @param payment The payment which has to be captured.
263
     * @return True if the payment attempt is successful, false if not.
264
     */
265
    private boolean captureAndUpdateHdfcPayment(in.shop2020.payment.domain.Payment payment){
266
        long merchantPaymentId = payment.getId();
267
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
268
        Map<String, String> captureResult = HdfcPaymentHandler.capturePayment(payment);
269
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
270
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
271
 
272
        Map<String, String> attrMap = new HashMap<String, String>();
273
        if (!captureStatus.trim().equals("0") 
274
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
275
            // Failure
276
            logger.info("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
277
            String description = captureResult.get(IPaymentHandler.ERROR);
278
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
279
 
280
            payment.setDescription(description);
281
            payment.setErrorCode(errorCode);
282
            payment.setStatus(PaymentStatus.FAILED.getValue());
283
            payment.setErrorTimestamp(new Date());
284
            paymentHandler.updatePayment(payment, attrMap);
285
            return false;
286
        } else {
287
            // Success
288
            logger.error("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
289
            payment.setDescription("Payment Captured");
290
            payment.setGatewayTxnStatus(gatewayStatus);
291
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
292
            payment.setSuccessTimestamp(new Date());           
293
 
294
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
295
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
296
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
297
 
298
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
299
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
300
 
301
            paymentHandler.updatePayment(payment, attrMap);
302
            return true;
303
          }
304
    }
305
 
306
    /**
307
     * Capture the EBS payment represented by the given payment object. If the
308
     * capture attempt is not successful, we mark this payment as failed. We
309
     * don't retry or anything. We'll add the support of multiple attempts later
310
     * on.
311
     * 
312
     * @param payment The payment which has to be captured.
313
     * @return True if the payment attempt is successful, false if not.
314
     */
315
    private boolean captureAndUpdateEbsPayment(in.shop2020.payment.domain.Payment payment){
316
        Map<String, String> captureResult = EbsPaymentHandler.capturePayment(payment);
317
        String captureStatus = captureResult.get(EbsPaymentHandler.STATUS);
318
 
319
        Map<String, String> attrMap = new HashMap<String, String>();
320
        if("".equals(captureStatus)){
321
            //Failure
322
            String description = captureResult.get(EbsPaymentHandler.ERROR);
323
            String errorCode = captureResult.get(EbsPaymentHandler.ERR_CODE);
324
 
325
            payment.setDescription(description);
326
            payment.setErrorCode(errorCode);
327
            payment.setStatus(PaymentStatus.FAILED.getValue());
328
            payment.setErrorTimestamp(new Date());
329
            paymentHandler.updatePayment(payment, attrMap);
330
            return false;
331
        }else{
332
            //Success
333
            payment.setGatewayTxnStatus(captureStatus);
334
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
335
            payment.setSuccessTimestamp(new Date());
336
 
337
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
338
            attrMap.put(IPaymentHandler.CAPTURE_TIME, captureResult.get(IPaymentHandler.CAPTURE_TIME));
339
            paymentHandler.updatePayment(payment, attrMap);
340
            return true;
341
        }
342
    }
343
 
344
 
345
    /**
346
     * Creates a list of thrift payment objects corresponding to a list of
347
     * payment data objects.
348
     * 
349
     * @param daoPayments
350
     *            A list of payment DAO.
351
     * @return A list of Thrift payment objects.
352
     */
353
    private List<Payment> getThriftPayments(List<in.shop2020.payment.domain.Payment> daoPayments){
354
 
355
        List<Payment> payments = new ArrayList<Payment>();
356
        for(in.shop2020.payment.domain.Payment payment : daoPayments){
357
            payments.add(payment.getThriftPayment());
358
        }
359
        return payments;
360
    }
3375 rajveer 361
 
362
	@Override
363
	public boolean isAlive() throws TException {
364
		// TODO Auto-generated method stub
365
		return true;
366
	}
1946 chandransh 367
}