Subversion Repositories SmartDukaan

Rev

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

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