Subversion Repositories SmartDukaan

Rev

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