Subversion Repositories SmartDukaan

Rev

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