Subversion Repositories SmartDukaan

Rev

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