Subversion Repositories SmartDukaan

Rev

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