Subversion Repositories SmartDukaan

Rev

Rev 3583 | Rev 3649 | 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
 
3578 mandeep.dh 3
import in.shop2020.crm.CRMService.Client;
4
import in.shop2020.payment.domain.Refund;
5
import in.shop2020.payment.handler.PaymentGatewayHandler;
6
import in.shop2020.payment.handler.PaymentHandler;
7
import in.shop2020.payment.handler.RefundHandler;
8
import in.shop2020.payments.Attribute;
9
import in.shop2020.payments.Payment;
10
import in.shop2020.payments.PaymentException;
11
import in.shop2020.payments.PaymentGateway;
12
import in.shop2020.payments.PaymentService.Iface;
13
import in.shop2020.payments.PaymentStatus;
14
import in.shop2020.thrift.clients.CRMClient;
15
 
3010 chandransh 16
import java.text.SimpleDateFormat;
1946 chandransh 17
import java.util.ArrayList;
18
import java.util.Date;
19
import java.util.HashMap;
20
import java.util.List;
21
import java.util.Map;
22
 
23
import org.apache.thrift.TException;
3578 mandeep.dh 24
import org.apache.thrift.transport.TTransportException;
3010 chandransh 25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
1946 chandransh 27
import org.springframework.context.ApplicationContext;
28
import org.springframework.context.support.ClassPathXmlApplicationContext;
29
 
30
public class PaymentServiceHandler implements Iface {
3010 chandransh 31
 
32
    private static Logger logger = LoggerFactory.getLogger(PaymentServiceHandler.class);
33
 
34
    /**
35
     * Enum of all statuses that can be returned by the HDFC gateway
36
     * 
37
     * @author Chandranshu
38
     * 
39
     */
40
    private enum HdfcPaymentReturnStatus{
41
        APPROVED("APPROVED"),
42
        NOT_APPROVED("NOT APPROVED"),
43
        CAPTURED("CAPTURED"),
44
        NOT_CAPTURED ("NOT CAPTURED"),
45
        CANCELLED ("CANCELLED"),
46
        DENIED_BY_RISK("DENIED BY RISK"),
47
        HOST_TIMEOUT("HOST TIMEOUT");
48
        private String value;
49
        HdfcPaymentReturnStatus(String value) {
50
            this.value = value;
51
        }
52
        public String value(){
53
            return this.value;
54
        }
55
    }
56
 
2391 chandransh 57
	public static final long PAYMENT_NOT_CREATED = -1;
58
 
3010 chandransh 59
	private static final long HDFC_GATEWAY_ID = 1;
60
	private static final long EBS_GATEWAY_ID = 2;
3583 chandransh 61
	private static final long HDFC_EMI_GATEWAY_ID = 5;
3010 chandransh 62
 
1946 chandransh 63
	ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");
64
	PaymentHandler paymentHandler = (PaymentHandler) context.getBean("paymentHandler");
65
	PaymentGatewayHandler paymentGatewayHandler = (PaymentGatewayHandler) context.getBean("paymentGatewayHandler");
2747 chandransh 66
	RefundHandler refundHandler = (RefundHandler) context.getBean("refundHandler");
1946 chandransh 67
 
68
	@Override
69
	public void closeSession() throws TException {
70
		// TODO Auto-generated method stub		
71
	}
72
 
73
	@Override
74
	public long createPayment(long userId, double amount, long gatewayId, long txnId) throws PaymentException, TException {
3010 chandransh 75
	    logger.info("Creating payment corresponding to our txn id:" + txnId);
1946 chandransh 76
		in.shop2020.payment.domain.Payment payment = new in.shop2020.payment.domain.Payment();
77
		payment.setUserId(userId);
78
		payment.setAmount(amount);
79
		payment.setGatewayId(gatewayId);
80
		payment.setMerchantTxnId(txnId);
81
		payment.setStatus(PaymentStatus.INIT.getValue());
82
 
83
		return paymentHandler.insertPayment(payment);
84
	}
85
 
86
	@Override
87
	public List<Payment> getPaymentsForUser(long userId, long fromTime, long toTime, PaymentStatus status, long gatewayId) throws PaymentException, TException {
3010 chandransh 88
	    logger.info("Getting payments from " + fromTime + " to " + toTime + " for user: " + userId);
2291 chandransh 89
		int statusValue = -1;
90
		if(status != null)
91
			statusValue = status.getValue();
92
		else
93
			statusValue = -1;
94
		return getThriftPayments(paymentHandler.getPaymentsForUser(userId, fromTime, toTime, statusValue, gatewayId));
1946 chandransh 95
	}
96
 
97
	@Override
98
	public List<Payment> getPayments(long fromTime, long toTime, PaymentStatus status, long gatewayId) throws PaymentException,	TException {
3010 chandransh 99
	    logger.info("Getting payments from " + fromTime + " to " + toTime);
2291 chandransh 100
		int statusValue = -1;
101
		if(status != null)
102
			statusValue = status.getValue();
103
		else
104
			statusValue = -1;
105
		return getThriftPayments(paymentHandler.getPayments(fromTime, toTime, statusValue, gatewayId));
1946 chandransh 106
	}
107
 
108
	@Override
109
	public PaymentGateway getPaymentGateway(long id) throws PaymentException, TException {
3010 chandransh 110
	    logger.info("Getting payment gateway with id:" + id);
2291 chandransh 111
		return paymentGatewayHandler.getPaymentGateway(id).getThriftPaymentGateway();
1946 chandransh 112
	}
113
 
114
	@Override
115
	public Payment getPayment(long id) throws PaymentException, TException {
3010 chandransh 116
	    logger.info("Getting payment with id: " + id);
1946 chandransh 117
		return paymentHandler.getPayment(id).getThriftPayment();
118
	}
119
 
120
	@Override
121
	public List<Payment> getPaymentForTxnId(long txnId) throws PaymentException, TException {
3010 chandransh 122
	    logger.info("Getting payment for the txn id: " + txnId);
1946 chandransh 123
		return getThriftPayments(paymentHandler.getPaymentForTxn(txnId));
124
	}
125
 
126
	@Override
127
	public boolean updatePaymentDetails(long id, String gatewayPaymentId,
128
			String sessionId, String gatewayTxnStatus, String description,
129
			String gatewayTxnId, String authCode, String referenceCode,
130
			String errorCode, PaymentStatus status, String gatewayTxnDate,
131
			List<Attribute> attributes) throws PaymentException, TException {
3010 chandransh 132
	    logger.info("Updating details of payment id: " + id);
1946 chandransh 133
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(id);
134
		payment.setGatewayPaymentId(gatewayPaymentId);
135
		payment.setSessionId(sessionId);
136
		payment.setGatewayTxnStatus(gatewayTxnStatus);
137
		payment.setDescription(description);
138
		payment.setGatewayTxnId(gatewayTxnId);
139
		payment.setAuthCode(authCode);
140
		payment.setReferenceCode(referenceCode);
141
		payment.setErrorCode(errorCode);
142
		if(status!=null){
143
			payment.setStatus(status.getValue());
144
			if(status.equals(PaymentStatus.SUCCESS))
145
				payment.setSuccessTimestamp(new Date());
3578 mandeep.dh 146
			else if(status.equals(PaymentStatus.FAILED)) {
147
			    payment.setErrorTimestamp(new Date());
148
			    createTicketForFailedPayment(payment);
149
			}
1946 chandransh 150
		}
151
 
152
		payment.setGatewayTxnDate(gatewayTxnDate);
153
 
154
		Map<String, String> attrMap = new HashMap<String, String>();
2272 rajveer 155
		if(attributes != null){
156
			for(Attribute attribute : attributes){
157
				attrMap.put(attribute.getName(), attribute.getValue());
158
			}
1946 chandransh 159
		}
160
 
161
		paymentHandler.updatePayment(payment, attrMap);
162
		return true;
163
	}
164
 
3578 mandeep.dh 165
	// Creates tickets for payment failures in CRM
166
	private void createTicketForFailedPayment(in.shop2020.payment.domain.Payment payment) {
167
        try {
168
            Client crmClient = new CRMClient().getClient();
169
            crmClient.processPaymentFailure(payment.getUserId());
170
        } catch (TTransportException e) {
171
            logger.error("Could not create CRM client", e);
172
        } catch (TException e) {
173
            logger.error("Could not process paymentId: " + payment.getId(), e);
174
        }
175
    }
176
 
177
    @Override
1946 chandransh 178
	public List<Double> getSuccessfulPaymentsAmountRange() throws TException {
3010 chandransh 179
	    logger.info("Getting the range of successful payments.");
1946 chandransh 180
		List<Double> minMaxAmounts = new ArrayList<Double>();
181
		Map<String, Float> minMax = paymentHandler.getMinMaxPaymentAmount();
182
		minMaxAmounts.add(Double.parseDouble(Float.toString(minMax.get("MIN"))));
183
		minMaxAmounts.add(Double.parseDouble(Float.toString(minMax.get("MAX"))));
184
		return minMaxAmounts;
185
	}
186
 
2391 chandransh 187
	@Override
188
	public String initializeHdfcPayment(long merchantPaymentId) throws PaymentException, TException {
3010 chandransh 189
	    logger.info("Initializing HDFC payment with id: " + merchantPaymentId);
2391 chandransh 190
		in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
191
		String redirectURL;
192
		try {
193
			redirectURL = HdfcPaymentHandler.initializeHdfcPayment(payment, this);
194
		} catch (Exception e) {
195
			throw new PaymentException(102, "Error while initiliazing payment. Check service log for more details.");
196
		}
197
		return redirectURL;
198
	}
199
 
200
	@Override
3616 chandransh 201
    public String initializeHdfcEmiPayment(long merchantPaymentId) throws PaymentException, TException {
202
        logger.info("Initializing HDFC payment with id: " + merchantPaymentId);
203
        in.shop2020.payment.domain.Payment payment = paymentHandler.getPayment(merchantPaymentId);
204
        String redirectURL;
205
        try {
206
            redirectURL = HdfcEmiPaymentHandler.initializeHdfcPayment(payment, this);
207
        } catch (Exception e) {
208
            throw new PaymentException(102, "Error while initiliazing payment. Check service log for more details.");
209
        }
210
        return redirectURL;
211
    }
212
 
213
	@Override
2689 chandransh 214
    public long createRefund(long orderId, long merchantTxnId, double amount) throws PaymentException, TException{
3010 chandransh 215
	    logger.info("Attempting to create a refund for order: " + orderId);
2689 chandransh 216
		List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
217
		if(payments ==null || payments.isEmpty())
218
			throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
219
 
3010 chandransh 220
		in.shop2020.payment.domain.Payment payment = payments.get(0);
2689 chandransh 221
		if(payment.getStatus() != PaymentStatus.SUCCESS.getValue())
222
			throw new PaymentException(104, "No successful payments found corresponding to the merchant txn " + merchantTxnId);
223
 
2747 chandransh 224
		Refund refund = new Refund();
225
		refund.setOrderId(orderId);
226
		refund.setPaymentId(payment.getId());
227
		refund.setGatewayId(payment.getGatewayId());
228
		refund.setAmount(amount);
229
		refund.setAttempts(0);
230
		return refundHandler.createRefund(refund);
2689 chandransh 231
    }
232
 
3010 chandransh 233
    @Override
234
    public boolean capturePayment(long merchantTxnId) throws PaymentException, TException {
235
        logger.info("Attempting to capture payment corresponding to our transaction " + merchantTxnId);
236
        List<in.shop2020.payment.domain.Payment> payments = paymentHandler.getPaymentForTxn(merchantTxnId);
237
        if(payments ==null || payments.isEmpty())
238
            throw new PaymentException(104, "No payments found corresponding to the merchant txn " + merchantTxnId);
239
 
240
        in.shop2020.payment.domain.Payment payment = payments.get(0);
241
        switch(PaymentStatus.findByValue(payment.getStatus())){
242
        case PENDING:
243
            logger.error("Attempt to capture a non-authorized payment");
244
            return false;
245
        case INIT:
246
            logger.warn("Attempt to capture a non-authorized payment");
247
            return false;
248
        case AUTHORIZED:
249
            //Actual work to be done in this case. Let the call proceed.
250
            break;
251
        case SUCCESS:
252
            logger.warn("Attempting to capture an already captured payment but we can let the client proceed.");
253
            return true;
254
        case FAILED:
255
            logger.error("Attempting to capture a failed payment");
256
            return false;
257
        }
258
 
259
        long gatewayId = payment.getGatewayId();
260
 
261
        if(gatewayId == HDFC_GATEWAY_ID){
262
            //Capture and update the HDFC payment
263
            return captureAndUpdateHdfcPayment(payment);
264
        } else if (gatewayId == EBS_GATEWAY_ID){
265
            //Capture and update the EBS payment
266
            return captureAndUpdateEbsPayment(payment);
3583 chandransh 267
        } else if (gatewayId == HDFC_EMI_GATEWAY_ID){
268
            //Capture and update the HDFC EMI payment
269
            return captureAndUpdateHdfcEmiPayment(payment);
3010 chandransh 270
        }
271
 
272
        logger.error("We have an authorized payment from unknown gateway: " + gatewayId);
273
        return false;
274
    }
275
 
276
    /**
277
     * Capture the HDFC payment represented by the given payment object. If the
278
     * capture attempt is not successful, we mark this payment as failed. We
279
     * don't retry or anything. We'll add the support of multiple attempts later
280
     * on.
281
     * 
282
     * @param payment The payment which has to be captured.
283
     * @return True if the payment attempt is successful, false if not.
284
     */
285
    private boolean captureAndUpdateHdfcPayment(in.shop2020.payment.domain.Payment payment){
286
        long merchantPaymentId = payment.getId();
287
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
288
        Map<String, String> captureResult = HdfcPaymentHandler.capturePayment(payment);
289
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
290
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
291
 
292
        Map<String, String> attrMap = new HashMap<String, String>();
293
        if (!captureStatus.trim().equals("0") 
294
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
295
            // Failure
3616 chandransh 296
            logger.error("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
3010 chandransh 297
            String description = captureResult.get(IPaymentHandler.ERROR);
298
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
299
 
300
            payment.setDescription(description);
301
            payment.setErrorCode(errorCode);
302
            payment.setStatus(PaymentStatus.FAILED.getValue());
303
            payment.setErrorTimestamp(new Date());
304
            paymentHandler.updatePayment(payment, attrMap);
3578 mandeep.dh 305
            createTicketForFailedPayment(payment);
3010 chandransh 306
            return false;
307
        } else {
308
            // Success
3616 chandransh 309
            logger.info("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
3010 chandransh 310
            payment.setDescription("Payment Captured");
311
            payment.setGatewayTxnStatus(gatewayStatus);
312
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
313
            payment.setSuccessTimestamp(new Date());           
314
 
315
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
316
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
317
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
318
 
319
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
320
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
321
 
322
            paymentHandler.updatePayment(payment, attrMap);
323
            return true;
324
          }
325
    }
326
 
327
    /**
3583 chandransh 328
     * Capture the HDFC EMI payment represented by the given payment object. If
329
     * the capture attempt is not successful, we mark this payment as failed. We
330
     * don't retry or anything. We'll add the support of multiple attempts later
331
     * on.
332
     * 
333
     * @param payment
334
     *            The payment which has to be captured.
335
     * @return True if the payment attempt is successful, false if not.
336
     */
337
    private boolean captureAndUpdateHdfcEmiPayment(in.shop2020.payment.domain.Payment payment){
338
        long merchantPaymentId = payment.getId();
339
        logger.info("Capturing HDFC payment with id: " + merchantPaymentId);
340
        Map<String, String> captureResult = HdfcEmiPaymentHandler.capturePayment(payment);
341
        String captureStatus = captureResult.get(IPaymentHandler.STATUS);
342
        String gatewayStatus = captureResult.get(IPaymentHandler.GATEWAY_STATUS);
343
 
344
        Map<String, String> attrMap = new HashMap<String, String>();
345
        if (!captureStatus.trim().equals("0") 
346
                || !HdfcPaymentReturnStatus.CAPTURED.value().equals(gatewayStatus)) {
347
            // Failure
3616 chandransh 348
            logger.error("Capture attempt failed for HDFC payment with id: " + merchantPaymentId);
3583 chandransh 349
            String description = captureResult.get(IPaymentHandler.ERROR);
350
            String errorCode = captureResult.get(IPaymentHandler.ERR_CODE);
351
 
352
            payment.setDescription(description);
353
            payment.setErrorCode(errorCode);
354
            payment.setStatus(PaymentStatus.FAILED.getValue());
355
            payment.setErrorTimestamp(new Date());
356
            paymentHandler.updatePayment(payment, attrMap);
357
            createTicketForFailedPayment(payment);
358
            return false;
359
        } else {
360
            // Success
3616 chandransh 361
            logger.info("Capture attempt successful for HDFC payment with id: " + merchantPaymentId);
3583 chandransh 362
            payment.setDescription("Payment Captured");
363
            payment.setGatewayTxnStatus(gatewayStatus);
364
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
365
            payment.setSuccessTimestamp(new Date());           
366
 
367
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
368
            attrMap.put(IPaymentHandler.CAPTURE_REF_ID, captureResult.get(IPaymentHandler.CAPTURE_REF_ID));
369
            attrMap.put(IPaymentHandler.CAPTURE_AUTH_ID, captureResult.get(IPaymentHandler.CAPTURE_AUTH_ID));
370
 
371
            SimpleDateFormat captureTimeDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
372
            attrMap.put(HdfcPaymentHandler.CAPTURE_TIME, captureTimeDateFormatter.format(new Date()));
373
 
374
            paymentHandler.updatePayment(payment, attrMap);
375
            return true;
376
          }
377
    }
378
 
379
    /**
3010 chandransh 380
     * Capture the EBS payment represented by the given payment object. If the
381
     * capture attempt is not successful, we mark this payment as failed. We
382
     * don't retry or anything. We'll add the support of multiple attempts later
383
     * on.
384
     * 
385
     * @param payment The payment which has to be captured.
386
     * @return True if the payment attempt is successful, false if not.
387
     */
388
    private boolean captureAndUpdateEbsPayment(in.shop2020.payment.domain.Payment payment){
389
        Map<String, String> captureResult = EbsPaymentHandler.capturePayment(payment);
390
        String captureStatus = captureResult.get(EbsPaymentHandler.STATUS);
391
 
392
        Map<String, String> attrMap = new HashMap<String, String>();
393
        if("".equals(captureStatus)){
394
            //Failure
3616 chandransh 395
            logger.error("Capture attempt failed for EBS payment with id: " + payment.getId());
3010 chandransh 396
            String description = captureResult.get(EbsPaymentHandler.ERROR);
397
            String errorCode = captureResult.get(EbsPaymentHandler.ERR_CODE);
398
 
399
            payment.setDescription(description);
400
            payment.setErrorCode(errorCode);
401
            payment.setStatus(PaymentStatus.FAILED.getValue());
402
            payment.setErrorTimestamp(new Date());
403
            paymentHandler.updatePayment(payment, attrMap);
3578 mandeep.dh 404
            createTicketForFailedPayment(payment);
3010 chandransh 405
            return false;
406
        }else{
407
            //Success
3616 chandransh 408
            logger.info("Capture attempt successful for EBS payment with id: " + payment.getId());
3010 chandransh 409
            payment.setGatewayTxnStatus(captureStatus);
410
            payment.setStatus(PaymentStatus.SUCCESS.getValue());
411
            payment.setSuccessTimestamp(new Date());
412
 
413
            attrMap.put(IPaymentHandler.CAPTURE_TXN_ID, captureResult.get(IPaymentHandler.CAPTURE_TXN_ID));
414
            attrMap.put(IPaymentHandler.CAPTURE_TIME, captureResult.get(IPaymentHandler.CAPTURE_TIME));
415
            paymentHandler.updatePayment(payment, attrMap);
416
            return true;
417
        }
418
    }
419
 
420
 
421
    /**
422
     * Creates a list of thrift payment objects corresponding to a list of
423
     * payment data objects.
424
     * 
425
     * @param daoPayments
426
     *            A list of payment DAO.
427
     * @return A list of Thrift payment objects.
428
     */
429
    private List<Payment> getThriftPayments(List<in.shop2020.payment.domain.Payment> daoPayments){
430
 
431
        List<Payment> payments = new ArrayList<Payment>();
432
        for(in.shop2020.payment.domain.Payment payment : daoPayments){
433
            payments.add(payment.getThriftPayment());
434
        }
435
        return payments;
436
    }
3375 rajveer 437
 
438
	@Override
439
	public boolean isAlive() throws TException {
440
		// TODO Auto-generated method stub
441
		return true;
442
	}
1946 chandransh 443
}