Subversion Repositories SmartDukaan

Rev

Rev 6488 | Rev 6503 | 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
 
6050 anupam.sin 3
import in.shop2020.model.v1.order.RechargeOrder;
3578 mandeep.dh 4
import in.shop2020.payment.domain.Refund;
5
import in.shop2020.payment.handler.PaymentGatewayHandler;
6
import in.shop2020.payment.handler.PaymentHandler;
4008 mandeep.dh 7
import in.shop2020.payment.handler.PaymentRequiringExtraProcessingHandler;
3578 mandeep.dh 8
import in.shop2020.payment.handler.RefundHandler;
9
import in.shop2020.payments.Attribute;
4008 mandeep.dh 10
import in.shop2020.payments.ExtraPaymentProcessingType;
3578 mandeep.dh 11
import in.shop2020.payments.Payment;
12
import in.shop2020.payments.PaymentException;
13
import in.shop2020.payments.PaymentGateway;
14
import in.shop2020.payments.PaymentService.Iface;
15
import in.shop2020.payments.PaymentStatus;
6050 anupam.sin 16
import in.shop2020.thrift.clients.TransactionClient;
3578 mandeep.dh 17
 
3010 chandransh 18
import java.text.SimpleDateFormat;
1946 chandransh 19
import java.util.ArrayList;
6448 rajveer 20
import java.util.Arrays;
1946 chandransh 21
import java.util.Date;
22
import java.util.HashMap;
23
import java.util.List;
24
import java.util.Map;
25
 
26
import org.apache.thrift.TException;
3010 chandransh 27
import org.slf4j.Logger;
28
import org.slf4j.LoggerFactory;
1946 chandransh 29
import org.springframework.context.ApplicationContext;
30
import org.springframework.context.support.ClassPathXmlApplicationContext;
31
 
32
public class PaymentServiceHandler implements Iface {
3010 chandransh 33
 
34
    private static Logger logger = LoggerFactory.getLogger(PaymentServiceHandler.class);
35
 
36
    /**
37
     * Enum of all statuses that can be returned by the HDFC gateway
38
     * 
39
     * @author Chandranshu
40
     * 
41
     */
42
    private enum HdfcPaymentReturnStatus{
43
        APPROVED("APPROVED"),
44
        NOT_APPROVED("NOT APPROVED"),
45
        CAPTURED("CAPTURED"),
46
        NOT_CAPTURED ("NOT CAPTURED"),
47
        CANCELLED ("CANCELLED"),
48
        DENIED_BY_RISK("DENIED BY RISK"),
49
        HOST_TIMEOUT("HOST TIMEOUT");
50
        private String value;
51
        HdfcPaymentReturnStatus(String value) {
52
            this.value = value;
53
        }
54
        public String value(){
55
            return this.value;
56
        }
57
    }
58
 
2391 chandransh 59
	public static final long PAYMENT_NOT_CREATED = -1;
60
 
3010 chandransh 61
	private static final long HDFC_GATEWAY_ID = 1;
62
	private static final long EBS_GATEWAY_ID = 2;
6449 rajveer 63
	private static final List<Long> HDFC_EMI_GATEWAY_IDS = Arrays.asList(5L,10L,11L,12L);
3010 chandransh 64
 
4651 rajveer 65
	ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
1946 chandransh 66
	PaymentHandler paymentHandler = (PaymentHandler) context.getBean("paymentHandler");
4008 mandeep.dh 67
    PaymentRequiringExtraProcessingHandler paymentRequiringExtraProcessingHandler =
68
        (PaymentRequiringExtraProcessingHandler) context.getBean("paymentRequiringExtraProcessingHandler");
69
 
70
    PaymentGatewayHandler paymentGatewayHandler = (PaymentGatewayHandler) context.getBean("paymentGatewayHandler");
2747 chandransh 71
	RefundHandler refundHandler = (RefundHandler) context.getBean("refundHandler");
1946 chandransh 72
 
4651 rajveer 73
	public void setDataSourceUrl(String dbHost){
74
		org.apache.commons.dbcp.BasicDataSource ds = (org.apache.commons.dbcp.BasicDataSource)context.getBean("dataSource");
75
		ds.setUrl(dbHost);
76
	}
77
 
78
	public String getDataSourceUrl(){
79
		org.apache.commons.dbcp.BasicDataSource ds = (org.apache.commons.dbcp.BasicDataSource)context.getBean("dataSource");
80
		return ds.getUrl();
81
	}
82
 
1946 chandransh 83
	@Override
6050 anupam.sin 84
	public long createPayment(long userId, double amount, long gatewayId, long txnId, boolean isDigital) throws PaymentException, TException {
3010 chandransh 85
	    logger.info("Creating payment corresponding to our txn id:" + txnId);
1946 chandransh 86
		in.shop2020.payment.domain.Payment payment = new in.shop2020.payment.domain.Payment();
87
		payment.setUserId(userId);
88
		payment.setAmount(amount);
89
		payment.setGatewayId(gatewayId);
90
		payment.setMerchantTxnId(txnId);
91
		payment.setStatus(PaymentStatus.INIT.getValue());
6050 anupam.sin 92
		payment.setDigital(isDigital);
1946 chandransh 93
 
94
		return paymentHandler.insertPayment(payment);
95
	}
96
 
97
	@Override
98
	public List<Payment> getPaymentsForUser(long userId, long fromTime, long toTime, PaymentStatus status, long gatewayId) throws PaymentException, TException {
3010 chandransh 99
	    logger.info("Getting payments from " + fromTime + " to " + toTime + " for user: " + userId);
2291 chandransh 100
		int statusValue = -1;
101
		if(status != null)
102
			statusValue = status.getValue();
103
		else
104
			statusValue = -1;
105
		return getThriftPayments(paymentHandler.getPaymentsForUser(userId, fromTime, toTime, statusValue, gatewayId));
1946 chandransh 106
	}
107
 
108
	@Override
109
	public List<Payment> getPayments(long fromTime, long toTime, PaymentStatus status, long gatewayId) throws PaymentException,	TException {
3010 chandransh 110
	    logger.info("Getting payments from " + fromTime + " to " + toTime);
2291 chandransh 111
		int statusValue = -1;
112
		if(status != null)
113
			statusValue = status.getValue();
114
		else
115
			statusValue = -1;
116
		return getThriftPayments(paymentHandler.getPayments(fromTime, toTime, statusValue, gatewayId));
1946 chandransh 117
	}
4141 chandransh 118
 
119
	@Override
120
	public List<Payment> getPaymentsByCapturedDate(long fromTime, long toTime, long gatewayId) throws PaymentException, TException {
121
		logger.info("Getting payments from " + fromTime + " to " + toTime + " for " + gatewayId);
122
		return getThriftPayments(paymentHandler.getPaymentsByCapturedDate(fromTime, toTime, gatewayId));
123
	}
1946 chandransh 124
 
125
	@Override
126
	public PaymentGateway getPaymentGateway(long id) throws PaymentException, TException {
3010 chandransh 127
	    logger.info("Getting payment gateway with id:" + id);
2291 chandransh 128
		return paymentGatewayHandler.getPaymentGateway(id).getThriftPaymentGateway();
1946 chandransh 129
	}
4600 varun.gupt 130
 
1946 chandransh 131
	@Override
4600 varun.gupt 132
	public List<PaymentGateway> getActivePaymentGateways() throws PaymentException, TException {
133
	    logger.info("Getting all active payment gateways");
134
	    return getThriftPaymentGateways(paymentGatewayHandler.getActivePaymentGateways());
135
	}
136
 
137
	@Override
1946 chandransh 138
	public Payment getPayment(long id) throws PaymentException, TException {
3010 chandransh 139
	    logger.info("Getting payment with id: " + id);
1946 chandransh 140
		return paymentHandler.getPayment(id).getThriftPayment();
141
	}
142
 
143
	@Override
144
	public List<Payment> getPaymentForTxnId(long txnId) throws PaymentException, TException {
3010 chandransh 145
	    logger.info("Getting payment for the txn id: " + txnId);
1946 chandransh 146
		return getThriftPayments(paymentHandler.getPaymentForTxn(txnId));
147
	}
4600 varun.gupt 148
 
149
	@Override
150
	public Payment getSuccessfulPaymentForTxnId(long txnId) throws PaymentException, TException {
151
 
152
		for (Payment payment: getPaymentForTxnId(txnId))	{
153
			if (payment.getStatus() == PaymentStatus.SUCCESS || payment.getStatus() == PaymentStatus.PARTIALLY_CAPTURED)	{
154
				return payment;
155
			}
156
		}
157
		return null;
158
	}
1946 chandransh 159
 
160
	@Override
161
	public boolean updatePaymentDetails(long id, String gatewayPaymentId,
162
			String sessionId, String gatewayTxnStatus, String description,
163
			String gatewayTxnId, String authCode, String referenceCode,
164
			String errorCode, PaymentStatus status, String gatewayTxnDate,
165
			List<Attribute> attributes) throws PaymentException, TException {
3010 chandransh 166
	    logger.info("Updating details of payment id: " + id);
1946 chandransh 167
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(id);
168
		payment.setGatewayPaymentId(gatewayPaymentId);
169
		payment.setSessionId(sessionId);
170
		payment.setGatewayTxnStatus(gatewayTxnStatus);
171
		payment.setDescription(description);
172
		payment.setGatewayTxnId(gatewayTxnId);
173
		payment.setAuthCode(authCode);
174
		payment.setReferenceCode(referenceCode);
175
		payment.setErrorCode(errorCode);
176
		if(status!=null){
177
			payment.setStatus(status.getValue());
178
			if(status.equals(PaymentStatus.SUCCESS))
179
				payment.setSuccessTimestamp(new Date());
3578 mandeep.dh 180
			else if(status.equals(PaymentStatus.FAILED)) {
181
			    payment.setErrorTimestamp(new Date());
4421 mandeep.dh 182
			    persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
3578 mandeep.dh 183
			}
4421 mandeep.dh 184
			else if (status.equals(PaymentStatus.PROVISIONALLY_CAPTURED)) {
185
			    // FIXME different column to note provisional capture timestamp
186
			    // FIXME Requires extra processing at Crm end for actual manual capture
187
			    payment.setProvisionalCaptureTimestamp(new Date());
188
			    persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.PENDING_CAPTURE);
189
			}
1946 chandransh 190
		}
191
 
192
		payment.setGatewayTxnDate(gatewayTxnDate);
193
 
194
		Map<String, String> attrMap = new HashMap<String, String>();
2272 rajveer 195
		if(attributes != null){
196
			for(Attribute attribute : attributes){
197
				attrMap.put(attribute.getName(), attribute.getValue());
198
			}
1946 chandransh 199
		}
200
 
201
		paymentHandler.updatePayment(payment, attrMap);
202
		return true;
203
	}
204
 
3649 mandeep.dh 205
	/**
4008 mandeep.dh 206
	 * Persists a given payment Id in another table for future processing by CRM etc.
207
	 * Failed payments generally require a follow-up to help customers through our
208
	 * CRM-Outbound team.
3649 mandeep.dh 209
	 *
210
	 * @param payment  the payment object that failed.
4421 mandeep.dh 211
	 * @param type TODO
3649 mandeep.dh 212
	 */
4421 mandeep.dh 213
	private void persistPaymentRequiringExtraProcessing(in.shop2020.payment.domain.Payment payment, ExtraPaymentProcessingType type) {
4008 mandeep.dh 214
	    try {
4421 mandeep.dh 215
            paymentRequiringExtraProcessingHandler.insert(payment.getId(), type);
4008 mandeep.dh 216
        } catch (Exception e) {
217
            logger.error("Could not persist payment: " + payment.getId(), e);
3578 mandeep.dh 218
        }
219
    }
220
 
221
    @Override
1946 chandransh 222
	public List<Double> getSuccessfulPaymentsAmountRange() throws TException {
3010 chandransh 223
	    logger.info("Getting the range of successful payments.");
1946 chandransh 224
		List<Double> minMaxAmounts = new ArrayList<Double>();
225
		Map<String, Float> minMax = paymentHandler.getMinMaxPaymentAmount();
226
		minMaxAmounts.add(Double.parseDouble(Float.toString(minMax.get("MIN"))));
227
		minMaxAmounts.add(Double.parseDouble(Float.toString(minMax.get("MAX"))));
228
		return minMaxAmounts;
229
	}
230
 
6050 anupam.sin 231
    @Override
232
    public String initializeHdfcPayment(long merchantPaymentId) throws PaymentException, TException {
233
        logger.info("Initializing HDFC payment with id: " + merchantPaymentId);
234
        in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
235
        String redirectURL;
236
        try {
237
            redirectURL = HdfcPaymentHandler.initializeHdfcPayment(payment, this);
238
        } catch (Exception e) {
239
            throw new PaymentException(102, "Error while initiliazing payment. Check service log for more details.");
240
        }
241
        return redirectURL;
242
    }
243
 
244
    @Override
6228 anupam.sin 245
	public String doHdfcPaymentForDigitalOrder(long merchantPaymentId, long rechargeOrderId, String phone) throws PaymentException, TException {
6050 anupam.sin 246
        logger.info("Initializing HDFC payment with id: " + merchantPaymentId);
247
        in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
248
        TransactionClient tc = new TransactionClient();
249
        String redirectURL;
250
        RechargeOrder rechargeOrder;
251
        try {
252
            rechargeOrder = tc.getClient().getRechargeOrder(rechargeOrderId);
6228 anupam.sin 253
            redirectURL = HdfcPaymentHandler.initializeHdfcPayment(payment, rechargeOrder, phone, this);
6050 anupam.sin 254
        } catch (Exception e) {
255
            throw new PaymentException(102, "Error while initiliazing payment. Check service log for more details.");
256
        }
257
 
258
        return redirectURL;
259
    }
2391 chandransh 260
 
261
	@Override
3616 chandransh 262
    public String initializeHdfcEmiPayment(long merchantPaymentId) throws PaymentException, TException {
263
        logger.info("Initializing HDFC payment with id: " + merchantPaymentId);
264
        in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
265
        String redirectURL;
266
        try {
267
            redirectURL = HdfcEmiPaymentHandler.initializeHdfcPayment(payment, this);
268
        } catch (Exception e) {
269
            throw new PaymentException(102, "Error while initiliazing payment. Check service log for more details.");
270
        }
271
        return redirectURL;
272
    }
273
 
6486 rajveer 274
	@Override
275
	public synchronized boolean refundPayment(long merchantTxnId, double amount, boolean isDigital) throws PaymentException, TException {
6482 rajveer 276
        logger.info("Attempting to refund payment of amount " + amount + " corresponding to our transaction " + merchantTxnId);
277
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
278
        if(payments ==null || payments.isEmpty())
279
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
280
 
6486 rajveer 281
        if(payments ==null || payments.isEmpty())
282
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
283
 
6482 rajveer 284
        in.shop2020.payment.domain.Payment payment = payments.get(0);
6486 rajveer 285
 
286
        if(payment.getAmount() < amount){
287
        	logger.warn("Refund amount is more than payment amount.");
288
            return false;
289
        }
290
 
6482 rajveer 291
        switch(PaymentStatus.findByValue(payment.getStatus())){
292
        case PENDING:
293
            logger.error("Attempt to refund a non-authorized payment");
294
            return false;
295
        case INIT:
296
            logger.warn("Attempt to refund a non-authorized payment");
297
            return false;
298
        case AUTHORIZED:
299
        	logger.warn("Attempt to refund a non-captured payment");
300
            return false;
301
        case CAPTURE_IN_PROCESS:
302
        	logger.warn("Attempt to refund a non-captured payment");
303
            return false;
304
        case PROVISIONALLY_CAPTURED:
305
        	logger.warn("Attempt to refund a non-captured payment");
306
            return false;
6486 rajveer 307
        case REFUNDED:
308
        	logger.warn("Attempt to refund a refunded payment");
309
            return false;
6482 rajveer 310
        case SUCCESS:
311
            break;
312
        case FAILED:
313
            logger.error("Attempting to capture a failed payment");
314
            return false;
315
        }
316
 
317
        long gatewayId = payment.getGatewayId();
318
 
319
        if(gatewayId == HDFC_GATEWAY_ID){
6491 rajveer 320
            //Refund the HDFC payment
6482 rajveer 321
            return refundHdfcPayment(payment, amount);
6491 rajveer 322
        }else if (gatewayId == EBS_GATEWAY_ID){
323
            //Refund the EBS payment
324
            return refundEbsPayment(payment, amount);
6482 rajveer 325
        } 
6491 rajveer 326
        else if (HDFC_EMI_GATEWAY_IDS.contains(gatewayId)){
327
             //Capture and update the HDFC EMI payment
328
            return refundHdfcEmiPayment(payment, amount);
329
        }
6482 rajveer 330
 
331
        logger.error("We have an captured payment from unknown gateway: " + gatewayId);
332
        return false;
333
    }
334
 
335
 
3616 chandransh 336
	@Override
2689 chandransh 337
    public long createRefund(long orderId, long merchantTxnId, double amount) throws PaymentException, TException{
6482 rajveer 338
		logger.info("Attempting to create a refund for order: " + orderId);
6488 rajveer 339
//		if(!refundPayment(merchantTxnId, amount, false)){
340
//			logger.warn("Not able to refund corresponding to the merchant txn " + merchantTxnId);
341
//		}
2689 chandransh 342
		List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
343
		if(payments ==null || payments.isEmpty())
344
			throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
345
 
3010 chandransh 346
		in.shop2020.payment.domain.Payment payment = payments.get(0);
2689 chandransh 347
		if(payment.getStatus() != PaymentStatus.SUCCESS.getValue())
348
			throw new PaymentException(104, "No successful payments found corresponding to the merchant txn " + merchantTxnId);
349
 
2747 chandransh 350
		Refund refund = new Refund();
351
		refund.setOrderId(orderId);
352
		refund.setPaymentId(payment.getId());
353
		refund.setGatewayId(payment.getGatewayId());
354
		refund.setAmount(amount);
355
		refund.setAttempts(0);
356
		return refundHandler.createRefund(refund);
2689 chandransh 357
    }
358
 
3010 chandransh 359
    @Override
4253 mandeep.dh 360
    public synchronized boolean capturePayment(long merchantTxnId) throws PaymentException, TException {
3010 chandransh 361
        logger.info("Attempting to capture payment corresponding to our transaction " + merchantTxnId);
362
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
363
        if(payments ==null || payments.isEmpty())
364
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
365
 
366
        in.shop2020.payment.domain.Payment payment = payments.get(0);
367
        switch(PaymentStatus.findByValue(payment.getStatus())){
368
        case PENDING:
369
            logger.error("Attempt to capture a non-authorized payment");
370
            return false;
371
        case INIT:
372
            logger.warn("Attempt to capture a non-authorized payment");
373
            return false;
374
        case AUTHORIZED:
4421 mandeep.dh 375
        case CAPTURE_IN_PROCESS:
3010 chandransh 376
            //Actual work to be done in this case. Let the call proceed.
377
            break;
4421 mandeep.dh 378
        case PROVISIONALLY_CAPTURED:
379
            logger.info("Attempting to capture a payment that is provisonally captured but we can let the client proceed.");
380
            return true;
3010 chandransh 381
        case SUCCESS:
382
            logger.warn("Attempting to capture an already captured payment but we can let the client proceed.");
383
            return true;
384
        case FAILED:
385
            logger.error("Attempting to capture a failed payment");
386
            return false;
387
        }
388
 
389
        long gatewayId = payment.getGatewayId();
390
 
391
        if(gatewayId == HDFC_GATEWAY_ID){
392
            //Capture and update the HDFC payment
393
            return captureAndUpdateHdfcPayment(payment);
394
        } else if (gatewayId == EBS_GATEWAY_ID){
395
            //Capture and update the EBS payment
396
            return captureAndUpdateEbsPayment(payment);
6449 rajveer 397
        } else if (HDFC_EMI_GATEWAY_IDS.contains(gatewayId)){
3583 chandransh 398
            //Capture and update the HDFC EMI payment
399
            return captureAndUpdateHdfcEmiPayment(payment);
3010 chandransh 400
        }
401
 
402
        logger.error("We have an authorized payment from unknown gateway: " + gatewayId);
403
        return false;
404
    }
405
 
3956 chandransh 406
    @Override
407
    public boolean partiallyCapturePayment(long merchantTxnId, double amount, String xferBy, String xferTxnId, long xferDate) throws PaymentException, TException {
408
        logger.info("Attempting to partially capture payment corresponding to our transaction " + merchantTxnId);
409
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
410
        if(payments ==null || payments.isEmpty())
411
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
412
 
413
        in.shop2020.payment.domain.Payment payment = payments.get(0);
414
        switch(PaymentStatus.findByValue(payment.getStatus())){
415
        case PENDING:
416
            // COD payments lie in this state before settlement.
417
        case INIT:
418
        case PARTIALLY_CAPTURED:
419
        case AUTHORIZED:
420
            // COD payments would not be in this state but we are processing
421
            // payments in this state as well for forward compatibility since
422
            // someday we'd want to be able to capture authorized CC payments
423
            // partially.
424
            break;
425
        case SUCCESS:
426
            logger.warn("Attempting to capture an already captured payment but we can let the client proceed.");
427
            return true;
428
        case FAILED:
429
            logger.error("Attempting to capture a failed payment");
430
            return false;
431
        }
432
        SimpleDateFormat mysqlDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
433
        String xferDateStr = mysqlDateFormatter.format(new Date(xferDate));
434
 
435
        return settleAndUpdateCodPayment(payment, amount, xferBy, xferTxnId, xferDateStr);
436
    }
437
 
3010 chandransh 438
    /**
439
     * Capture the HDFC payment represented by the given payment object. If the
440
     * capture attempt is not successful, we mark this payment as failed. We
441
     * don't retry or anything. We'll add the support of multiple attempts later
442
     * on.
443
     * 
444
     * @param payment The payment which has to be captured.
445
     * @return True if the payment attempt is successful, false if not.
4421 mandeep.dh 446
     * @throws PaymentException 
3010 chandransh 447
     */
4421 mandeep.dh 448
    private boolean captureAndUpdateHdfcPayment(in.shop2020.payment.domain.Payment payment) throws PaymentException {
3010 chandransh 449
        long merchantPaymentId = payment.getId();
450
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
451
        Map<String, String> captureResult = HdfcPaymentHandler.capturePayment(payment);
452
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
453
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
454
 
455
        Map<String, String> attrMap = new HashMap<String, String>();
456
        if (!captureStatus.trim().equals("0") 
457
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
458
            // Failure
3616 chandransh 459
            logger.error("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
3010 chandransh 460
            String description = captureResult.get(IPaymentHandler.ERROR);
461
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
462
 
463
            payment.setDescription(description);
464
            payment.setErrorCode(errorCode);
465
            payment.setErrorTimestamp(new Date());
4421 mandeep.dh 466
 
467
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
468
                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());
469
                paymentHandler.updatePayment(payment, attrMap);
470
                throw new PaymentException(106, "Could not capture due to connection issue");
471
            }
472
            else {
473
                payment.setStatus(PaymentStatus.FAILED.getValue());
474
                paymentHandler.updatePayment(payment, attrMap);
475
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
476
            }
477
 
3010 chandransh 478
            return false;
479
        } else {
480
            // Success
3616 chandransh 481
            logger.info("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
3010 chandransh 482
            payment.setDescription("Payment Captured");
483
            payment.setGatewayTxnStatus(gatewayStatus);
484
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
485
            payment.setSuccessTimestamp(new Date());           
486
 
487
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
488
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
489
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
490
 
491
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
492
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
493
 
494
            paymentHandler.updatePayment(payment, attrMap);
495
            return true;
496
          }
497
    }
498
 
499
    /**
3583 chandransh 500
     * Capture the HDFC EMI payment represented by the given payment object. If
501
     * the capture attempt is not successful, we mark this payment as failed. We
502
     * don't retry or anything. We'll add the support of multiple attempts later
503
     * on.
504
     * 
505
     * @param payment
506
     *            The payment which has to be captured.
507
     * @return True if the payment attempt is successful, false if not.
4421 mandeep.dh 508
     * @throws PaymentException 
3583 chandransh 509
     */
4421 mandeep.dh 510
    private boolean captureAndUpdateHdfcEmiPayment(in.shop2020.payment.domain.Payment payment) throws PaymentException{
3583 chandransh 511
        long merchantPaymentId = payment.getId();
512
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
513
        Map<String, String> captureResult = HdfcEmiPaymentHandler.capturePayment(payment);
514
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
515
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
516
 
517
        Map<String, String> attrMap = new HashMap<String, String>();
518
        if (!captureStatus.trim().equals("0") 
519
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
520
            // Failure
3616 chandransh 521
            logger.error("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
3583 chandransh 522
            String description = captureResult.get(IPaymentHandler.ERROR);
523
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
524
 
525
            payment.setDescription(description);
526
            payment.setErrorCode(errorCode);
4421 mandeep.dh 527
            payment.setErrorTimestamp(new Date());                
528
 
529
            // Not marking payments as failed in case of connection issues
530
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
531
                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());
532
                paymentHandler.updatePayment(payment, attrMap);
533
                throw new PaymentException(106, "Could not capture due to connection issue");
534
            }
535
            else {
536
                payment.setStatus(PaymentStatus.FAILED.getValue());
537
                paymentHandler.updatePayment(payment, attrMap);
538
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
539
            }
540
 
3583 chandransh 541
            return false;
542
        } else {
543
            // Success
3616 chandransh 544
            logger.info("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
3583 chandransh 545
            payment.setDescription("Payment Captured");
546
            payment.setGatewayTxnStatus(gatewayStatus);
547
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
4421 mandeep.dh 548
            payment.setSuccessTimestamp(new Date());
3583 chandransh 549
 
550
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
551
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
552
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
553
 
554
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
555
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
556
 
557
            paymentHandler.updatePayment(payment, attrMap);
558
            return true;
559
          }
560
    }
561
 
562
    /**
3010 chandransh 563
     * Capture the EBS payment represented by the given payment object. If the
564
     * capture attempt is not successful, we mark this payment as failed. We
565
     * don't retry or anything. We'll add the support of multiple attempts later
566
     * on.
567
     * 
568
     * @param payment The payment which has to be captured.
569
     * @return True if the payment attempt is successful, false if not.
4421 mandeep.dh 570
     * @throws PaymentException 
3010 chandransh 571
     */
4421 mandeep.dh 572
    private boolean captureAndUpdateEbsPayment(in.shop2020.payment.domain.Payment payment) throws PaymentException{
3010 chandransh 573
        Map<String, String> captureResult = EbsPaymentHandler.capturePayment(payment);
574
        String captureStatus = captureResult.get(EbsPaymentHandler.STATUS);
575
 
576
        Map<String, String> attrMap = new HashMap<String, String>();
577
        if("".equals(captureStatus)){
578
            //Failure
3616 chandransh 579
            logger.error("Capture attempt failed for EBS payment with id: " + payment.getId());
3010 chandransh 580
            String description = captureResult.get(EbsPaymentHandler.ERROR);
581
            String errorCode = captureResult.get(EbsPaymentHandler.ERR_CODE);
4421 mandeep.dh 582
 
3010 chandransh 583
            payment.setDescription(description);
584
            payment.setErrorCode(errorCode);
585
            payment.setErrorTimestamp(new Date());
4421 mandeep.dh 586
 
587
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
588
                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());            
589
                paymentHandler.updatePayment(payment, attrMap);
590
                throw new PaymentException(106, "Could not capture due to connection issue");
591
            }
592
            else {
593
                payment.setStatus(PaymentStatus.FAILED.getValue());            
594
                paymentHandler.updatePayment(payment, attrMap);
595
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
596
            }
597
 
3010 chandransh 598
            return false;
599
        }else{
600
            //Success
3616 chandransh 601
            logger.info("Capture attempt successful for EBS payment with id: " + payment.getId());
3010 chandransh 602
            payment.setGatewayTxnStatus(captureStatus);
603
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
604
            payment.setSuccessTimestamp(new Date());
605
 
606
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
607
            attrMap.put(IPaymentHandler.CAPTURE_TIME, captureResult.get(IPaymentHandler.CAPTURE_TIME));
608
            paymentHandler.updatePayment(payment, attrMap);
609
            return true;
610
        }
611
    }
612
 
6482 rajveer 613
 
3010 chandransh 614
    /**
6482 rajveer 615
     * Refund the HDFC payment represented by the given payment object. If the
616
     * refund attempt is not successful, will not any action.
617
     * 
618
     * @param payment The payment which has to be captured.
619
     * @amount amount to be refunded
620
     * @return True if the payment attempt is successful, false if not.
621
     * @throws PaymentException 
622
     */
623
    private boolean refundHdfcPayment(in.shop2020.payment.domain.Payment payment, double amount) throws PaymentException {
624
        long merchantPaymentId = payment.getId();
625
        logger.info("Refunding HDFC payment with id: " + merchantPaymentId);
626
        Map<String, String> refundResult = HdfcPaymentHandler.refundPayment(payment, amount);
6486 rajveer 627
        String refundStatus = refundResult.get(IPaymentHandler.STATUS);
6482 rajveer 628
        String gatewayStatus = refundResult.get(IPaymentHandler.GATEWAY_STATUS);
629
 
630
        Map<String, String> attrMap = new HashMap<String, String>();
6486 rajveer 631
        if (!refundStatus.trim().equals("0") 
6482 rajveer 632
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
6486 rajveer 633
 
634
        	logger.error("Refund attempt failed for HDFC payment with id: " + merchantPaymentId);
635
            String description = refundResult.get(IPaymentHandler.ERROR);
636
            String errorCode = refundResult.get(IPaymentHandler.ERR_CODE);
637
 
638
            payment.setDescription(description);
639
            payment.setErrorCode(errorCode);
640
            payment.setErrorTimestamp(new Date());
641
 
642
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
643
                //payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());
644
                //paymentHandler.updatePayment(payment, attrMap);
645
                throw new PaymentException(106, "Could not capture due to connection issue. Try Later");
646
            }
647
            else {
6491 rajveer 648
//                payment.setStatus(PaymentStatus.FAILED.getValue());
649
//                paymentHandler.updatePayment(payment, attrMap);
6486 rajveer 650
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
651
            }
652
 
6482 rajveer 653
            return false;
654
        } else {
655
            // Success
656
            logger.info("Refund attempt successful for HDFC payment with id: " + merchantPaymentId);
657
            payment.setDescription("Payment Refunded");
658
            payment.setGatewayTxnStatus(gatewayStatus);
6486 rajveer 659
            payment.setStatus(PaymentStatus.REFUNDED.getValue());           
6482 rajveer 660
 
6486 rajveer 661
            attrMap.put(IPaymentHandler.REFUND_TXN_ID, refundResult.get(IPaymentHandler.REFUND_TXN_ID));
662
            attrMap.put(IPaymentHandler.REFUND_REF_ID, refundResult.get(IPaymentHandler.REFUND_REF_ID));
663
            attrMap.put(IPaymentHandler.REFUND_AUTH_ID, refundResult.get(IPaymentHandler.REFUND_AUTH_ID));
6482 rajveer 664
 
665
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
6486 rajveer 666
            attrMap.put(HdfcPaymentHandler.REFUND_TIME, captureTimeDateFormatter.format(new Date()));
6482 rajveer 667
 
668
            paymentHandler.updatePayment(payment, attrMap);
669
            return true;
670
          }
671
    }
672
 
673
 
6491 rajveer 674
    /**
675
     * Refund the HDFC EMI payment represented by the given payment object. If
676
     * the capture attempt is not successful, we will not do anything.
677
     * 
678
     * @param payment
679
     *            The payment which has to be captured.
680
     * @return True if the payment attempt is successful, false if not.
681
     * @throws PaymentException 
682
     */
683
    private boolean refundHdfcEmiPayment(in.shop2020.payment.domain.Payment payment, double amount) throws PaymentException{
684
        long merchantPaymentId = payment.getId();
685
        logger.info("Refunding HDFC payment with id: " + merchantPaymentId);
686
        Map<String, String> refundResult = HdfcEmiPaymentHandler.refundPayment(payment, amount);
687
        String refundStatus = refundResult.get(IPaymentHandler.STATUS);
688
        String gatewayStatus = refundResult.get(IPaymentHandler.GATEWAY_STATUS);
689
 
690
        Map<String, String> attrMap = new HashMap<String, String>();
691
        if (!refundStatus.trim().equals("0") 
692
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
693
            // Failure
694
            logger.error("Refund attempt failed for HDFC payment with id: " + merchantPaymentId);
695
            String description = refundResult.get(IPaymentHandler.ERROR);
696
            String errorCode = refundResult.get(IPaymentHandler.ERR_CODE);
697
 
698
            payment.setDescription(description);
699
            payment.setErrorCode(errorCode);
700
            payment.setErrorTimestamp(new Date());                
701
 
702
            // Not marking payments as failed in case of connection issues
703
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
704
             //   payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());
705
             //   paymentHandler.updatePayment(payment, attrMap);
706
                throw new PaymentException(106, "Could not capture due to connection issue");
707
            }
708
            else {
709
              //  payment.setStatus(PaymentStatus.FAILED.getValue());
710
              //  paymentHandler.updatePayment(payment, attrMap);
711
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
712
            }
713
 
714
            return false;
715
        } else {
716
            // Success
717
            logger.info("Refund attempt successful for HDFC payment with id: " + merchantPaymentId);
718
            payment.setDescription("Payment Refunded");
719
            payment.setGatewayTxnStatus(gatewayStatus);
720
            payment.setStatus(PaymentStatus.REFUNDED.getValue());           
721
 
722
            attrMap.put(IPaymentHandler.REFUND_TXN_ID, refundResult.get(IPaymentHandler.REFUND_TXN_ID));
723
            attrMap.put(IPaymentHandler.REFUND_REF_ID, refundResult.get(IPaymentHandler.REFUND_REF_ID));
724
            attrMap.put(IPaymentHandler.REFUND_AUTH_ID, refundResult.get(IPaymentHandler.REFUND_AUTH_ID));
725
 
726
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
727
            attrMap.put(HdfcPaymentHandler.REFUND_TIME, captureTimeDateFormatter.format(new Date()));
728
 
729
            paymentHandler.updatePayment(payment, attrMap);
730
            return true;
731
          }
732
    }
6482 rajveer 733
 
734
    /**
6491 rajveer 735
     * Refund the EBS payment represented by the given payment object. If the
736
     * capture attempt is not successful, we will ignore. We don't retry or anything. 
737
     * We'll add the support of multiple attempts later on.
738
     * 
739
     * @param payment The payment which has to be captured.
740
     * @amount Amount to be refunded
741
     * @return True if the payment attempt is successful, false if not.
742
     * @throws PaymentException 
743
     */
744
    private boolean refundEbsPayment(in.shop2020.payment.domain.Payment payment, double amount) throws PaymentException{
745
        Map<String, String> refundResult = EbsPaymentHandler.refundPayment(payment, amount);
746
        String refundStatus = refundResult.get(EbsPaymentHandler.STATUS);
747
 
748
        Map<String, String> attrMap = new HashMap<String, String>();
749
        if("".equals(refundStatus)){
750
            //Failure
751
            logger.error("Refund attempt failed for EBS payment with id: " + payment.getId());
752
            String description = refundResult.get(EbsPaymentHandler.ERROR);
753
            String errorCode = refundResult.get(EbsPaymentHandler.ERR_CODE);
754
 
755
            payment.setDescription(description);
756
            payment.setErrorCode(errorCode);
757
            payment.setErrorTimestamp(new Date());
758
 
759
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
760
//                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());            
761
//                paymentHandler.updatePayment(payment, attrMap);
762
                throw new PaymentException(106, "Could not capture due to connection issue");
763
            }
764
            else {
765
//                payment.setStatus(PaymentStatus.FAILED.getValue());            
766
//                paymentHandler.updatePayment(payment, attrMap);
767
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
768
            }
769
 
770
            return false;
771
        }else{
772
            //Success
773
            logger.info("Refund attempt successful for EBS payment with id: " + payment.getId());
774
            payment.setGatewayTxnStatus(refundStatus);
775
            payment.setStatus(PaymentStatus.REFUNDED.getValue());
776
 
777
            attrMap.put(IPaymentHandler.REFUND_TXN_ID, refundResult.get(IPaymentHandler.REFUND_TXN_ID));
778
            attrMap.put(IPaymentHandler.REFUND_TIME, refundResult.get(IPaymentHandler.REFUND_TIME));
779
            paymentHandler.updatePayment(payment, attrMap);
780
            return true;
781
        }
782
    }
783
 
784
 
785
    /**
3956 chandransh 786
     * Updates the settlement details of COD payments. Sets payment status as
787
     * either PARTIALLY CAPTURED or SUCCESS depending on whether the complete
788
     * amount has been captured. Other parameters are set as attributes.
789
     * 
790
     * @param payment
791
     *            The payment which needs to be updated.
792
     * @param amount
793
     *            Amount that has been captured.
794
     * @param xferBy
795
     *            Entity which transferred the money.
796
     * @param xferTxnId
797
     *            Transaction Id of the transfer.
798
     * @param xferDateStr
799
     *            Date on which the transfer took place.
800
     * @return true if the payment details were updated successfully.
801
     * @throws PaymentException
802
     *             if the captured amount will become more than the actual
803
     *             amount after this update.
804
     */
805
    private boolean settleAndUpdateCodPayment(in.shop2020.payment.domain.Payment payment, double amount, String xferBy, String xferTxnId, String xferDateStr) throws PaymentException{
806
        Map<String, String> attrMap = payment.getAttributeMap();
807
 
808
        double captureAmount = 0;
809
        String captureAmntStr = attrMap.get(IPaymentHandler.CAPTURE_AMNT);
810
        if(captureAmntStr != null)
811
            captureAmount = Double.parseDouble(captureAmntStr);
812
        captureAmount += amount;
5051 rajveer 813
        // If capture amount higher than payment amount by more than 50 paisa,
814
        // there is some issue and we should raise exception.
815
        if(captureAmount - payment.getAmount() > 0.5){
816
        	throw new PaymentException(105, "We've got a settlement request for an amount which is more than the transaction value.");
817
        }
3956 chandransh 818
 
5051 rajveer 819
        // If capture amount differs from payment amount by less than 50 paisa, lets mark the payment as successful. 
820
        // Else we can safely assume there will be some more orders for the payment, leading to make the payment as partially captured.
821
        if(Math.abs(captureAmount - payment.getAmount()) < 0.5){
822
        	payment.setStatus(PaymentStatus.SUCCESS.getValue());
823
        }else {
824
        	payment.setStatus(PaymentStatus.PARTIALLY_CAPTURED.getValue());   
3956 chandransh 825
        }
826
        payment.setSuccessTimestamp(new Date());
827
        attrMap.put(IPaymentHandler.CAPTURE_AMNT, captureAmount + "");
828
        attrMap.put(IPaymentHandler.XFER_TXN_ID, xferTxnId);
829
        attrMap.put(IPaymentHandler.XFER_TXN_DATE, xferDateStr);
830
        attrMap.put(IPaymentHandler.XFER_BY, xferBy);
831
        paymentHandler.updatePayment(payment, attrMap);
832
        return true;
833
    }
834
 
835
    /**
3010 chandransh 836
     * Creates a list of thrift payment objects corresponding to a list of
837
     * payment data objects.
838
     * 
839
     * @param daoPayments
840
     *            A list of payment DAO.
841
     * @return A list of Thrift payment objects.
842
     */
843
    private List<Payment> getThriftPayments(List<in.shop2020.payment.domain.Payment> daoPayments){
844
 
845
        List<Payment> payments = new ArrayList<Payment>();
846
        for(in.shop2020.payment.domain.Payment payment : daoPayments){
847
            payments.add(payment.getThriftPayment());
848
        }
849
        return payments;
850
    }
3375 rajveer 851
 
4600 varun.gupt 852
    /**
853
     * Creates a list of thrift payment gateway objects corresponding to a list of
854
     * payment gateway data objects.
855
     * 
856
     * @param daoPaymentGateways
857
     *            A list of payment gateway DAO.
858
     * @return A list of Thrift payment gateway objects.
859
     */
860
    private List<PaymentGateway> getThriftPaymentGateways(List<in.shop2020.payment.domain.PaymentGateway> daoPaymentGateways){
861
 
862
        List<PaymentGateway> paymentGateways = new ArrayList<PaymentGateway>();
863
        for(in.shop2020.payment.domain.PaymentGateway paymentGateway : daoPaymentGateways){
864
            paymentGateways.add(paymentGateway.getThriftPaymentGateway());
865
        }
866
        return paymentGateways;
867
    }
4619 mandeep.dh 868
 
3375 rajveer 869
	@Override
4619 mandeep.dh 870
	public boolean isAlive() {
871
	    try {
872
            return !paymentGatewayHandler.getActivePaymentGateways().isEmpty();
873
        } catch (Exception e) {
874
            logger.error("Could not fetch payment gateways", e);
875
        }
876
 
877
        return false;
3375 rajveer 878
	}
3956 chandransh 879
 
880
 
881
    @Override
882
    public void closeSession() throws TException {
883
        // TODO Auto-generated method stub      
884
    }
4008 mandeep.dh 885
 
886
    @Override
887
    public List<Long> getPaymentsRequiringExtraProcessing (
888
            ExtraPaymentProcessingType category) throws TException {
889
        return paymentRequiringExtraProcessingHandler.getPaymentIds(category);
890
    }
891
 
892
    @Override
893
    public void markPaymentAsProcessed(long paymentId,
894
            ExtraPaymentProcessingType category) throws TException {
895
        paymentRequiringExtraProcessingHandler.delete(paymentId, category);
896
    }
4141 chandransh 897
 
1946 chandransh 898
}