Subversion Repositories SmartDukaan

Rev

Rev 6449 | Rev 6486 | 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
 
6482 rajveer 274
 
275
	public synchronized boolean refundPayment(long merchantTxnId, double amount) throws PaymentException, TException {
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
 
281
        in.shop2020.payment.domain.Payment payment = payments.get(0);
282
        switch(PaymentStatus.findByValue(payment.getStatus())){
283
        case PENDING:
284
            logger.error("Attempt to refund a non-authorized payment");
285
            return false;
286
        case INIT:
287
            logger.warn("Attempt to refund a non-authorized payment");
288
            return false;
289
        case AUTHORIZED:
290
        	logger.warn("Attempt to refund a non-captured payment");
291
            return false;
292
        case CAPTURE_IN_PROCESS:
293
        	logger.warn("Attempt to refund a non-captured payment");
294
            return false;
295
        case PROVISIONALLY_CAPTURED:
296
        	logger.warn("Attempt to refund a non-captured payment");
297
            return false;
298
        case SUCCESS:
299
            break;
300
        case FAILED:
301
            logger.error("Attempting to capture a failed payment");
302
            return false;
303
        }
304
 
305
        long gatewayId = payment.getGatewayId();
306
 
307
        if(gatewayId == HDFC_GATEWAY_ID){
308
            //Capture and update the HDFC payment
309
            return refundHdfcPayment(payment, amount);
310
        } 
311
 
312
//        else if (gatewayId == EBS_GATEWAY_ID){
313
//            //Capture and update the EBS payment
314
//            return refundEbsPayment(payment);
315
//        } else if (HDFC_EMI_GATEWAY_IDS.contains(gatewayId)){
316
//            //Capture and update the HDFC EMI payment
317
//            return refundsHdfcEmiPayment(payment);
318
//        }
319
 
320
        logger.error("We have an captured payment from unknown gateway: " + gatewayId);
321
        return false;
322
    }
323
 
324
 
3616 chandransh 325
	@Override
2689 chandransh 326
    public long createRefund(long orderId, long merchantTxnId, double amount) throws PaymentException, TException{
6482 rajveer 327
		logger.info("Attempting to create a refund for order: " + orderId);
328
		if(!refundPayment(merchantTxnId, amount)){
329
			throw new PaymentException(104, "Not able to refund corresponding to the merchant txn " + merchantTxnId);
330
		}
2689 chandransh 331
		List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
332
		if(payments ==null || payments.isEmpty())
333
			throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
334
 
3010 chandransh 335
		in.shop2020.payment.domain.Payment payment = payments.get(0);
2689 chandransh 336
		if(payment.getStatus() != PaymentStatus.SUCCESS.getValue())
337
			throw new PaymentException(104, "No successful payments found corresponding to the merchant txn " + merchantTxnId);
338
 
2747 chandransh 339
		Refund refund = new Refund();
340
		refund.setOrderId(orderId);
341
		refund.setPaymentId(payment.getId());
342
		refund.setGatewayId(payment.getGatewayId());
343
		refund.setAmount(amount);
344
		refund.setAttempts(0);
345
		return refundHandler.createRefund(refund);
2689 chandransh 346
    }
347
 
3010 chandransh 348
    @Override
4253 mandeep.dh 349
    public synchronized boolean capturePayment(long merchantTxnId) throws PaymentException, TException {
3010 chandransh 350
        logger.info("Attempting to capture payment corresponding to our transaction " + merchantTxnId);
351
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
352
        if(payments ==null || payments.isEmpty())
353
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
354
 
355
        in.shop2020.payment.domain.Payment payment = payments.get(0);
356
        switch(PaymentStatus.findByValue(payment.getStatus())){
357
        case PENDING:
358
            logger.error("Attempt to capture a non-authorized payment");
359
            return false;
360
        case INIT:
361
            logger.warn("Attempt to capture a non-authorized payment");
362
            return false;
363
        case AUTHORIZED:
4421 mandeep.dh 364
        case CAPTURE_IN_PROCESS:
3010 chandransh 365
            //Actual work to be done in this case. Let the call proceed.
366
            break;
4421 mandeep.dh 367
        case PROVISIONALLY_CAPTURED:
368
            logger.info("Attempting to capture a payment that is provisonally captured but we can let the client proceed.");
369
            return true;
3010 chandransh 370
        case SUCCESS:
371
            logger.warn("Attempting to capture an already captured payment but we can let the client proceed.");
372
            return true;
373
        case FAILED:
374
            logger.error("Attempting to capture a failed payment");
375
            return false;
376
        }
377
 
378
        long gatewayId = payment.getGatewayId();
379
 
380
        if(gatewayId == HDFC_GATEWAY_ID){
381
            //Capture and update the HDFC payment
382
            return captureAndUpdateHdfcPayment(payment);
383
        } else if (gatewayId == EBS_GATEWAY_ID){
384
            //Capture and update the EBS payment
385
            return captureAndUpdateEbsPayment(payment);
6449 rajveer 386
        } else if (HDFC_EMI_GATEWAY_IDS.contains(gatewayId)){
3583 chandransh 387
            //Capture and update the HDFC EMI payment
388
            return captureAndUpdateHdfcEmiPayment(payment);
3010 chandransh 389
        }
390
 
391
        logger.error("We have an authorized payment from unknown gateway: " + gatewayId);
392
        return false;
393
    }
394
 
3956 chandransh 395
    @Override
396
    public boolean partiallyCapturePayment(long merchantTxnId, double amount, String xferBy, String xferTxnId, long xferDate) throws PaymentException, TException {
397
        logger.info("Attempting to partially capture payment corresponding to our transaction " + merchantTxnId);
398
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
399
        if(payments ==null || payments.isEmpty())
400
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
401
 
402
        in.shop2020.payment.domain.Payment payment = payments.get(0);
403
        switch(PaymentStatus.findByValue(payment.getStatus())){
404
        case PENDING:
405
            // COD payments lie in this state before settlement.
406
        case INIT:
407
        case PARTIALLY_CAPTURED:
408
        case AUTHORIZED:
409
            // COD payments would not be in this state but we are processing
410
            // payments in this state as well for forward compatibility since
411
            // someday we'd want to be able to capture authorized CC payments
412
            // partially.
413
            break;
414
        case SUCCESS:
415
            logger.warn("Attempting to capture an already captured payment but we can let the client proceed.");
416
            return true;
417
        case FAILED:
418
            logger.error("Attempting to capture a failed payment");
419
            return false;
420
        }
421
        SimpleDateFormat mysqlDateFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
422
        String xferDateStr = mysqlDateFormatter.format(new Date(xferDate));
423
 
424
        return settleAndUpdateCodPayment(payment, amount, xferBy, xferTxnId, xferDateStr);
425
    }
426
 
3010 chandransh 427
    /**
428
     * Capture the HDFC payment represented by the given payment object. If the
429
     * capture attempt is not successful, we mark this payment as failed. We
430
     * don't retry or anything. We'll add the support of multiple attempts later
431
     * on.
432
     * 
433
     * @param payment The payment which has to be captured.
434
     * @return True if the payment attempt is successful, false if not.
4421 mandeep.dh 435
     * @throws PaymentException 
3010 chandransh 436
     */
4421 mandeep.dh 437
    private boolean captureAndUpdateHdfcPayment(in.shop2020.payment.domain.Payment payment) throws PaymentException {
3010 chandransh 438
        long merchantPaymentId = payment.getId();
439
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
440
        Map<String, String> captureResult = HdfcPaymentHandler.capturePayment(payment);
441
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
442
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
443
 
444
        Map<String, String> attrMap = new HashMap<String, String>();
445
        if (!captureStatus.trim().equals("0") 
446
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
447
            // Failure
3616 chandransh 448
            logger.error("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
3010 chandransh 449
            String description = captureResult.get(IPaymentHandler.ERROR);
450
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
451
 
452
            payment.setDescription(description);
453
            payment.setErrorCode(errorCode);
454
            payment.setErrorTimestamp(new Date());
4421 mandeep.dh 455
 
456
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
457
                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());
458
                paymentHandler.updatePayment(payment, attrMap);
459
                throw new PaymentException(106, "Could not capture due to connection issue");
460
            }
461
            else {
462
                payment.setStatus(PaymentStatus.FAILED.getValue());
463
                paymentHandler.updatePayment(payment, attrMap);
464
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
465
            }
466
 
3010 chandransh 467
            return false;
468
        } else {
469
            // Success
3616 chandransh 470
            logger.info("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
3010 chandransh 471
            payment.setDescription("Payment Captured");
472
            payment.setGatewayTxnStatus(gatewayStatus);
473
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
474
            payment.setSuccessTimestamp(new Date());           
475
 
476
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
477
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
478
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
479
 
480
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
481
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
482
 
483
            paymentHandler.updatePayment(payment, attrMap);
484
            return true;
485
          }
486
    }
487
 
488
    /**
3583 chandransh 489
     * Capture the HDFC EMI payment represented by the given payment object. If
490
     * the capture attempt is not successful, we mark this payment as failed. We
491
     * don't retry or anything. We'll add the support of multiple attempts later
492
     * on.
493
     * 
494
     * @param payment
495
     *            The payment which has to be captured.
496
     * @return True if the payment attempt is successful, false if not.
4421 mandeep.dh 497
     * @throws PaymentException 
3583 chandransh 498
     */
4421 mandeep.dh 499
    private boolean captureAndUpdateHdfcEmiPayment(in.shop2020.payment.domain.Payment payment) throws PaymentException{
3583 chandransh 500
        long merchantPaymentId = payment.getId();
501
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
502
        Map<String, String> captureResult = HdfcEmiPaymentHandler.capturePayment(payment);
503
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
504
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
505
 
506
        Map<String, String> attrMap = new HashMap<String, String>();
507
        if (!captureStatus.trim().equals("0") 
508
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
509
            // Failure
3616 chandransh 510
            logger.error("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
3583 chandransh 511
            String description = captureResult.get(IPaymentHandler.ERROR);
512
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
513
 
514
            payment.setDescription(description);
515
            payment.setErrorCode(errorCode);
4421 mandeep.dh 516
            payment.setErrorTimestamp(new Date());                
517
 
518
            // Not marking payments as failed in case of connection issues
519
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
520
                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());
521
                paymentHandler.updatePayment(payment, attrMap);
522
                throw new PaymentException(106, "Could not capture due to connection issue");
523
            }
524
            else {
525
                payment.setStatus(PaymentStatus.FAILED.getValue());
526
                paymentHandler.updatePayment(payment, attrMap);
527
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
528
            }
529
 
3583 chandransh 530
            return false;
531
        } else {
532
            // Success
3616 chandransh 533
            logger.info("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
3583 chandransh 534
            payment.setDescription("Payment Captured");
535
            payment.setGatewayTxnStatus(gatewayStatus);
536
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
4421 mandeep.dh 537
            payment.setSuccessTimestamp(new Date());
3583 chandransh 538
 
539
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
540
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
541
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
542
 
543
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
544
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
545
 
546
            paymentHandler.updatePayment(payment, attrMap);
547
            return true;
548
          }
549
    }
550
 
551
    /**
3010 chandransh 552
     * Capture the EBS payment represented by the given payment object. If the
553
     * capture attempt is not successful, we mark this payment as failed. We
554
     * don't retry or anything. We'll add the support of multiple attempts later
555
     * on.
556
     * 
557
     * @param payment The payment which has to be captured.
558
     * @return True if the payment attempt is successful, false if not.
4421 mandeep.dh 559
     * @throws PaymentException 
3010 chandransh 560
     */
4421 mandeep.dh 561
    private boolean captureAndUpdateEbsPayment(in.shop2020.payment.domain.Payment payment) throws PaymentException{
3010 chandransh 562
        Map<String, String> captureResult = EbsPaymentHandler.capturePayment(payment);
563
        String captureStatus = captureResult.get(EbsPaymentHandler.STATUS);
564
 
565
        Map<String, String> attrMap = new HashMap<String, String>();
566
        if("".equals(captureStatus)){
567
            //Failure
3616 chandransh 568
            logger.error("Capture attempt failed for EBS payment with id: " + payment.getId());
3010 chandransh 569
            String description = captureResult.get(EbsPaymentHandler.ERROR);
570
            String errorCode = captureResult.get(EbsPaymentHandler.ERR_CODE);
4421 mandeep.dh 571
 
3010 chandransh 572
            payment.setDescription(description);
573
            payment.setErrorCode(errorCode);
574
            payment.setErrorTimestamp(new Date());
4421 mandeep.dh 575
 
576
            if (IPaymentHandler.Errors.CONN_FAILURE.code.equals(errorCode)) {
577
                payment.setStatus(PaymentStatus.CAPTURE_IN_PROCESS.getValue());            
578
                paymentHandler.updatePayment(payment, attrMap);
579
                throw new PaymentException(106, "Could not capture due to connection issue");
580
            }
581
            else {
582
                payment.setStatus(PaymentStatus.FAILED.getValue());            
583
                paymentHandler.updatePayment(payment, attrMap);
584
                persistPaymentRequiringExtraProcessing(payment, ExtraPaymentProcessingType.FAILED_PAYMENTS);
585
            }
586
 
3010 chandransh 587
            return false;
588
        }else{
589
            //Success
3616 chandransh 590
            logger.info("Capture attempt successful for EBS payment with id: " + payment.getId());
3010 chandransh 591
            payment.setGatewayTxnStatus(captureStatus);
592
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
593
            payment.setSuccessTimestamp(new Date());
594
 
595
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
596
            attrMap.put(IPaymentHandler.CAPTURE_TIME, captureResult.get(IPaymentHandler.CAPTURE_TIME));
597
            paymentHandler.updatePayment(payment, attrMap);
598
            return true;
599
        }
600
    }
601
 
6482 rajveer 602
 
3010 chandransh 603
    /**
6482 rajveer 604
     * Refund the HDFC payment represented by the given payment object. If the
605
     * refund attempt is not successful, will not any action.
606
     * 
607
     * @param payment The payment which has to be captured.
608
     * @amount amount to be refunded
609
     * @return True if the payment attempt is successful, false if not.
610
     * @throws PaymentException 
611
     */
612
    private boolean refundHdfcPayment(in.shop2020.payment.domain.Payment payment, double amount) throws PaymentException {
613
        long merchantPaymentId = payment.getId();
614
        logger.info("Refunding HDFC payment with id: " + merchantPaymentId);
615
        Map<String, String> refundResult = HdfcPaymentHandler.refundPayment(payment, amount);
616
        String captureStatus = refundResult.get(IPaymentHandler.STATUS);
617
        String gatewayStatus = refundResult.get(IPaymentHandler.GATEWAY_STATUS);
618
 
619
        Map<String, String> attrMap = new HashMap<String, String>();
620
        if (!captureStatus.trim().equals("0") 
621
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
622
            return false;
623
        } else {
624
            // Success
625
            logger.info("Refund attempt successful for HDFC payment with id: " + merchantPaymentId);
626
            payment.setDescription("Payment Refunded");
627
            payment.setGatewayTxnStatus(gatewayStatus);
628
            payment.setStatus(PaymentStatus.SUCCESS.getValue());           
629
 
630
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, refundResult.get(IPaymentHandler.CAPTURE_TXN_ID));
631
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, refundResult.get(IPaymentHandler.CAPTURE_REF_ID));
632
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, refundResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
633
 
634
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
635
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
636
 
637
            paymentHandler.updatePayment(payment, attrMap);
638
            return true;
639
          }
640
    }
641
 
642
 
643
 
644
    /**
3956 chandransh 645
     * Updates the settlement details of COD payments. Sets payment status as
646
     * either PARTIALLY CAPTURED or SUCCESS depending on whether the complete
647
     * amount has been captured. Other parameters are set as attributes.
648
     * 
649
     * @param payment
650
     *            The payment which needs to be updated.
651
     * @param amount
652
     *            Amount that has been captured.
653
     * @param xferBy
654
     *            Entity which transferred the money.
655
     * @param xferTxnId
656
     *            Transaction Id of the transfer.
657
     * @param xferDateStr
658
     *            Date on which the transfer took place.
659
     * @return true if the payment details were updated successfully.
660
     * @throws PaymentException
661
     *             if the captured amount will become more than the actual
662
     *             amount after this update.
663
     */
664
    private boolean settleAndUpdateCodPayment(in.shop2020.payment.domain.Payment payment, double amount, String xferBy, String xferTxnId, String xferDateStr) throws PaymentException{
665
        Map<String, String> attrMap = payment.getAttributeMap();
666
 
667
        double captureAmount = 0;
668
        String captureAmntStr = attrMap.get(IPaymentHandler.CAPTURE_AMNT);
669
        if(captureAmntStr != null)
670
            captureAmount = Double.parseDouble(captureAmntStr);
671
        captureAmount += amount;
5051 rajveer 672
        // If capture amount higher than payment amount by more than 50 paisa,
673
        // there is some issue and we should raise exception.
674
        if(captureAmount - payment.getAmount() > 0.5){
675
        	throw new PaymentException(105, "We've got a settlement request for an amount which is more than the transaction value.");
676
        }
3956 chandransh 677
 
5051 rajveer 678
        // If capture amount differs from payment amount by less than 50 paisa, lets mark the payment as successful. 
679
        // Else we can safely assume there will be some more orders for the payment, leading to make the payment as partially captured.
680
        if(Math.abs(captureAmount - payment.getAmount()) < 0.5){
681
        	payment.setStatus(PaymentStatus.SUCCESS.getValue());
682
        }else {
683
        	payment.setStatus(PaymentStatus.PARTIALLY_CAPTURED.getValue());   
3956 chandransh 684
        }
685
        payment.setSuccessTimestamp(new Date());
686
        attrMap.put(IPaymentHandler.CAPTURE_AMNT, captureAmount + "");
687
        attrMap.put(IPaymentHandler.XFER_TXN_ID, xferTxnId);
688
        attrMap.put(IPaymentHandler.XFER_TXN_DATE, xferDateStr);
689
        attrMap.put(IPaymentHandler.XFER_BY, xferBy);
690
        paymentHandler.updatePayment(payment, attrMap);
691
        return true;
692
    }
693
 
694
    /**
3010 chandransh 695
     * Creates a list of thrift payment objects corresponding to a list of
696
     * payment data objects.
697
     * 
698
     * @param daoPayments
699
     *            A list of payment DAO.
700
     * @return A list of Thrift payment objects.
701
     */
702
    private List<Payment> getThriftPayments(List<in.shop2020.payment.domain.Payment> daoPayments){
703
 
704
        List<Payment> payments = new ArrayList<Payment>();
705
        for(in.shop2020.payment.domain.Payment payment : daoPayments){
706
            payments.add(payment.getThriftPayment());
707
        }
708
        return payments;
709
    }
3375 rajveer 710
 
4600 varun.gupt 711
    /**
712
     * Creates a list of thrift payment gateway objects corresponding to a list of
713
     * payment gateway data objects.
714
     * 
715
     * @param daoPaymentGateways
716
     *            A list of payment gateway DAO.
717
     * @return A list of Thrift payment gateway objects.
718
     */
719
    private List<PaymentGateway> getThriftPaymentGateways(List<in.shop2020.payment.domain.PaymentGateway> daoPaymentGateways){
720
 
721
        List<PaymentGateway> paymentGateways = new ArrayList<PaymentGateway>();
722
        for(in.shop2020.payment.domain.PaymentGateway paymentGateway : daoPaymentGateways){
723
            paymentGateways.add(paymentGateway.getThriftPaymentGateway());
724
        }
725
        return paymentGateways;
726
    }
4619 mandeep.dh 727
 
3375 rajveer 728
	@Override
4619 mandeep.dh 729
	public boolean isAlive() {
730
	    try {
731
            return !paymentGatewayHandler.getActivePaymentGateways().isEmpty();
732
        } catch (Exception e) {
733
            logger.error("Could not fetch payment gateways", e);
734
        }
735
 
736
        return false;
3375 rajveer 737
	}
3956 chandransh 738
 
739
 
740
    @Override
741
    public void closeSession() throws TException {
742
        // TODO Auto-generated method stub      
743
    }
4008 mandeep.dh 744
 
745
    @Override
746
    public List<Long> getPaymentsRequiringExtraProcessing (
747
            ExtraPaymentProcessingType category) throws TException {
748
        return paymentRequiringExtraProcessingHandler.getPaymentIds(category);
749
    }
750
 
751
    @Override
752
    public void markPaymentAsProcessed(long paymentId,
753
            ExtraPaymentProcessingType category) throws TException {
754
        paymentRequiringExtraProcessingHandler.delete(paymentId, category);
755
    }
4141 chandransh 756
 
1946 chandransh 757
}