Subversion Repositories SmartDukaan

Rev

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