Subversion Repositories SmartDukaan

Rev

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