Rev 1981 | Rev 2141 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
package in.shop2020.serving.services;import in.shop2020.model.v1.order.LineItem;import in.shop2020.model.v1.order.Order;import in.shop2020.model.v1.order.Transaction;import in.shop2020.model.v1.order.TransactionServiceException;import in.shop2020.model.v1.order.TransactionStatus;import in.shop2020.model.v1.user.Cart;import in.shop2020.model.v1.user.Line;import in.shop2020.model.v1.user.PromotionException;import in.shop2020.model.v1.user.ShoppingCartException;import in.shop2020.model.v1.user.UserContextService;import in.shop2020.payments.PaymentException;import in.shop2020.payments.PaymentService.Client;import in.shop2020.serving.utils.Utils;import in.shop2020.thrift.clients.PaymentServiceClient;import in.shop2020.thrift.clients.PromotionServiceClient;import in.shop2020.thrift.clients.TransactionServiceClient;import in.shop2020.thrift.clients.UserContextServiceClient;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.log4j.Logger;import org.apache.thrift.TException;/*** This class has methods to be used to process non-gateway-specific aspects of* payments and transactions.** @author Chandranshu**/public class CommonPaymentService {private static final boolean PAYMENT_NOT_CREATED = false;private static Logger log = Logger.getLogger(Class.class);private long paymentId;private double amount;public long getPaymentId() {return paymentId;}public double getAmount() {return amount;}/*** Creates a payment for the given cart of the given user for the given* transaction. Stores the id of the newly created payment and the amount* for which this payment was created. They can be retrieved later on using* {@link #getPaymentId()}getPaymentId() and {@link #getAmount()}getAmount()* methods respectively later on.** @param currentCartId* The cart for which the payment object has to be created.* @param userId* The user for whom the payment has to be created.* @param txnId* The transaction against which the payment has to be created.* @param gatewayId* @return True if the payment object is successfully created, False* otherwise.*/public boolean createPayment(long currentCartId, long userId, long txnId, int gatewayId){PaymentServiceClient paymentServiceClient = null;try {paymentServiceClient = new PaymentServiceClient();} catch (Exception e) {log.error("Error while getting payment client");e.printStackTrace();return PAYMENT_NOT_CREATED;}try {amount = calculatePaymentAmount(currentCartId);} catch (ShoppingCartException e1) {log.error("Not able to fetch payment amount from cart id." + e1.getId() + e1.getMessage());e1.printStackTrace();return PAYMENT_NOT_CREATED;} catch (TException e1) {log.error("Not able to fetch payment amount." + e1.getMessage());e1.printStackTrace();return PAYMENT_NOT_CREATED;}Client paymentClient = paymentServiceClient.getClient();try {paymentId = paymentClient.createPayment(userId, amount, gatewayId, txnId);} catch (PaymentException e1) {log.error("Not able to create payment object." + e1.getError_code() + e1.getMessage());e1.printStackTrace();return PAYMENT_NOT_CREATED;} catch (TException e) {log.error("Not able to create payment object." + e.getMessage());e.printStackTrace();return PAYMENT_NOT_CREATED;}return true;}/*** Marks the given transaction as in process. Once the transaction is marked* as successful, the items in the cart for which this transaction was* processed are removed from the cart.<br>* Please note that it's possible that a user has added items to the cart* and so it's not possible to simply wipe out their cart.<br>* Again, it's important to ensure that we remove only as much quantity of* items as for which the order was processed.** @param txnId The transaction which should be marked as successful.* @param userServiceClient A user context service client to use.* @param transactionServiceClient A transaction service client to use.*/public static void processSuccessfulTxn(long txnId, UserContextServiceClient userServiceClient, TransactionServiceClient transactionServiceClient) {Transaction transaction = null;Map<Long,Double> items = new HashMap<Long, Double>();try {in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();transactionClient.changeTransactionStatus(txnId, TransactionStatus.IN_PROCESS, "Payment received for the order");transaction = transactionClient.getTransaction(txnId);for(Order order: transaction.getOrders()){for(LineItem lineitem: order.getLineitems()){Long itemId = lineitem.getItem_id();Double quantity = items.get(itemId);if(quantity==null){quantity = lineitem.getQuantity();}else{quantity= quantity + lineitem.getQuantity();}items.put(itemId, quantity);}}} catch (TException e1) {log.error("Unable to update status of transaction. Thrift Exception" + e1.getMessage());e1.printStackTrace();} catch (TransactionServiceException e) {log.error("Unable to update status of transaction. Thrift Exception" + e.getErrorCode() + e.getMessage());e.printStackTrace();}try {// Tracking Coupon UsageUserContextService.Client userClient = userServiceClient.getClient();Cart cart = userClient.getCart(transaction.getShoppingCartid());PromotionServiceClient promotionServiceClient = new PromotionServiceClient();String couponCode = cart.getCouponCode();if (couponCode != null && !couponCode.isEmpty()) {promotionServiceClient.getClient().trackCouponUsage(couponCode, txnId, transaction.getCustomer_id());}} catch (ShoppingCartException e) {log.error("Error occurred in reading CardId for transaction");e.printStackTrace();} catch (PromotionException e) {log.error("Promotion Exception: " + e.getMessage());e.printStackTrace();} catch (TException e) {log.error("Transport from Promotion Service failed");e.printStackTrace();} catch (Exception e) {e.printStackTrace();}try {//TODO Optimize the function to send less amount of data over networklog.info("Transaction shopping cart id is: " + transaction.getShoppingCartid());log.info("Items to restr in cart are: " + items );userServiceClient.getClient().resetCart(transaction.getShoppingCartid(), items);}catch (TException e) {log.error("Error while updating information in payment database.");e.printStackTrace();//FIXME Even we get exception we should sent url back to payment gateway. And some thing back channel should be done} catch (ShoppingCartException e) {log.error("Error while reseting the cart in cart database.");e.printStackTrace();}catch (Exception e) {// TODO: handle exception}}/*** Enqueues the transaction successful email, containing transaction info,* to be sent later by batch job.** @param transactionClient*/public static void sendTxnEmail(long txnId, TransactionServiceClient transactionServiceClient) {in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();try {transactionClient.enqueueTransactionInfoEmail(txnId);} catch (Exception e) {log.error("Error while adding email to dispatch queue.");e.printStackTrace();}}/*** Marks a transaction as well as all its orders as failed.** @param txnId* The id of the transaction which has to be marked as failed.* @param transactionServiceClient*/public static void processFailedTxn(long txnId, TransactionServiceClient transactionServiceClient) {try {in.shop2020.model.v1.order.TransactionService.Client transactionClient = transactionServiceClient.getClient();transactionClient.changeTransactionStatus(txnId, TransactionStatus.FAILED, "Payment failed for the transaction.");} catch(TException e){log.error("Thrift exception while getting information from transaction service.");e.printStackTrace();} catch (TransactionServiceException e) {log.error("Error while updating status information in transaction database.");e.printStackTrace();}}/*** Calculates the amount for the payment required for the given cart.** @param cartId* Id of the cart for which this payment amount has to be* calculated.* @return The total amount for which a payment should be created.* @throws ShoppingCartException* If no cart can be found for the given id.* @throws TException*/private double calculatePaymentAmount(long cartId) throws ShoppingCartException, TException{double totalAmount = 0;Cart cart;UserContextServiceClient userContextServiceClient = null;try {userContextServiceClient = new UserContextServiceClient();} catch (Exception e) {e.printStackTrace();}in.shop2020.model.v1.user.UserContextService.Client userClient = userContextServiceClient.getClient();cart = userClient.getCart(cartId);if(cart.getCouponCode() == null || cart.getDiscountedPrice() == 0.0) {List<Line> lineItems = cart.getLines();for (Line line : lineItems) {long productId = line.getItemId();// FIXME: It's expensive to get the price of each item from the// catalog service. We maintain the pricing info in the line items// themselves now.totalAmount = totalAmount + line.getQuantity() * Utils.getItemPrice(productId);}} else {totalAmount = cart.getDiscountedPrice();}return totalAmount;}// TODO: The service client parameters are unnecessary but initializing them// again when the caller has the necessary references has a performance// overhead. Need to think more about this.}