Subversion Repositories SmartDukaan

Rev

Rev 6486 | Rev 6491 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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