com.eywa.impl.app.mongo.services.PaymentService.java Source code

Java tutorial

Introduction

Here is the source code for com.eywa.impl.app.mongo.services.PaymentService.java

Source

/*
 * EYWA.COM (Eywa Commerce)
 * This program is an integrated platform with E-Commerce and Configurator system.
 * Support: Please, contact the Author on http://www.smartfeeling.org.
 * Copyright (C) 2014  Gian Angelo Geminiani
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * 
 */
package com.eywa.impl.app.mongo.services;

import com.eywa.AppEywa;
import com.eywa.impl.app.controllers.paypal.PayPalManager;
import com.eywa.impl.app.controllers.paypal.wrappers.PayPalResponse;
import com.eywa.impl.app.controllers.scheduled.IJobConstants;
import com.eywa.impl.app.controllers.scheduled.impl.typepayment.drivers.PaymentPostProcessor;
import com.eywa.impl.app.controllers.session.SessionManager;
import com.eywa.impl.app.mongo.entities.Payment;
import com.eywa.impl.app.mongo.entities.ScheduledJob;
import com.eywa.impl.app.mongo.entities.User;
import com.eywa.impl.app.mongo.entities.items.ItemBillingUser;
import com.eywa.impl.app.mongo.entities.items.jobs.ItemJobMessage;
import com.eywa.impl.app.mongo.entities.items.jobs.payments.ItemJobPayment;
import com.eywa.impl.app.mongo.entities.items.payment.ItemPayTransaction;
import com.eywa.impl.app.mongo.entities.items.session.cart.ItemSessionDataCart;
import com.eywa.impl.app.mongo.entities.items.session.cart.ItemSessionDataCartItem;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.paypal.svcs.types.ap.Receiver;
import org.ly.Smartly;
import org.ly.commons.logging.Level;
import org.ly.commons.logging.util.LoggingUtils;
import org.ly.commons.util.DateUtils;
import org.ly.commons.util.FormatUtils;
import org.ly.commons.util.MathUtils;
import org.ly.commons.util.StringUtils;
import org.ly.packages.mongo.impl.AbstractMongoService;
import org.ly.packages.mongo.impl.StandardCodedException;
import org.ly.packages.mongo.impl.util.MongoUtils;
import org.ly.proxies.DBProxy;

import java.util.*;

/**
 * @author angelo.geminiani
 */
public class PaymentService extends AbstractMongoService {

    // --------------------------------------------------------------------
    //               c o n s t r u c t o r
    // --------------------------------------------------------------------

    public PaymentService() throws Exception {
        super((DB) DBProxy.get().getDBMain(), Payment.COLLECTION, Smartly.getLanguages());
    }

    // --------------------------------------------------------------------
    //               p u b l i c
    // --------------------------------------------------------------------

    @Override
    public int upsert(final DBObject item) throws StandardCodedException {
        return super.upsert(item);
    }

    // --------------------------------------------------------------------
    //               p r i v a t e
    // --------------------------------------------------------------------

    // --------------------------------------------------------------------
    //               S T A T I C   p r i v a t e
    // --------------------------------------------------------------------

    private static org.ly.commons.logging.Logger getStaticLogger() {
        return LoggingUtils.getLogger(PaymentService.class);
    }

    /**
     * Process payments
     *
     * @param transactions List of payments to process
     */
    private static void processPayments(final List<DBObject> transactions) {
        for (final DBObject transaction : transactions) {
            final DBObject callbackParams = ItemPayTransaction.getCallbackParams(transaction);
            final Map<String, String> mapParams = null != callbackParams ? callbackParams.toMap() : new HashMap<>();
            try {
                // process only payments with no errors
                if (!StringUtils.hasText(ItemPayTransaction.getError(transaction))) {
                    final String sellerType = ItemPayTransaction.getSellerType(transaction); // payment methods are saved into users billing data
                    if (ItemBillingUser.isFree(sellerType) || ItemBillingUser.isPro(sellerType)
                            || ItemBillingUser.isAdmin(sellerType)) {
                        // pay with pay-pal
                        final String id = ItemPayTransaction.getPaymentId(transaction);
                        final DBObject cart = ItemPayTransaction.getCart(transaction);
                        final double price = ItemSessionDataCart.getItemsPrice(cart);
                        final String currency = ItemSessionDataCart.getCurrencyCode(cart);
                        final List<Receiver> receivers = new LinkedList<>();
                        if (ItemBillingUser.isPro(sellerType)) {
                            // PRO SELLER
                            final Receiver rec_seller = new Receiver(price);
                            rec_seller.setPrimary(true);
                            rec_seller.setEmail(ItemPayTransaction.getSellerEmail(transaction));

                            receivers.add(rec_seller);
                        } else if (ItemBillingUser.isFree(sellerType)) {
                            // FREE SELLER
                            final double eywa_price = MathUtils.round(price * AppEywa.getTransactionFee(), 2);
                            final double seller_price = price;
                            final Receiver rec_seller = new Receiver(seller_price);
                            rec_seller.setPrimary(true);
                            rec_seller.setEmail(ItemPayTransaction.getSellerEmail(transaction));
                            final Receiver rec_eywa = new Receiver(eywa_price);
                            rec_eywa.setPrimary(false);
                            rec_eywa.setEmail(AppEywa.getTransactionEmail());

                            receivers.add(rec_seller);
                            receivers.add(rec_eywa);
                        } else {
                            // admin (test only)
                            final double eywa_price = price * AppEywa.getTransactionFee();
                            final double seller_price = price;
                            final Receiver rec_seller = new Receiver(seller_price);
                            rec_seller.setPrimary(true);
                            rec_seller.setEmail(ItemPayTransaction.getSellerEmail(transaction));
                            final Receiver rec_eywa = new Receiver(eywa_price);
                            rec_eywa.setPrimary(false);
                            rec_eywa.setEmail(AppEywa.getTransactionEmail());

                            receivers.add(rec_seller);
                            receivers.add(rec_eywa);
                        }
                        // transaction
                        final PayPalResponse response = PayPalManager.getInstance().pay(currency, receivers, "", // ItemPayTransaction.getCustomerEmail(transaction),  // customer
                                "", // ipn
                                id, // tracking id
                                mapParams, // some useful url parameters
                                "", // cancel url
                                ""); // return url
                        ItemPayTransaction.setPayResponse(transaction, MongoUtils.parseObject(response.toString()));
                        ItemPayTransaction.setPayKey(transaction, response.getPayKey());
                        ItemPayTransaction.setPayExecStatus(transaction, response.getPayExecStatus());
                        ItemPayTransaction.setPayUrl(transaction, response.getPayUrl());
                        if (response.hasError()) {
                            ItemPayTransaction.setError(transaction, response.getFirstErrorMessage());
                        }
                    } else {
                        // unmanaged seller type
                        ItemPayTransaction.setError(transaction, "Unmanaged Seller Account Type: " + sellerType);
                        // TODO: Add here more payments types
                    }
                }
            } catch (Throwable t) {
                ItemPayTransaction.setError(transaction, "Transaction error: " + t.toString());
            }
        } // end for
    }

    // --------------------------------------------------------------------
    //               S T A T I C
    // --------------------------------------------------------------------

    public static DBObject get(final String id) {
        try {
            final PaymentService srvc = new PaymentService();
            return srvc.findById(id);
        } catch (Throwable ignored) {
        }
        return null;
    }

    public List<DBObject> getClosedOrPartial() {
        try {
            final PaymentService srvc = new PaymentService();
            final DBObject query = MongoUtils.queryNotEquals(Payment.TYPE, Payment.TYPE_OPEN);
            return srvc.find(query);
        } catch (Throwable ignored) {
        }
        return new ArrayList<>();
    }

    public static Map<String, ItemSessionDataCart> splitToSellersCart(final DBObject rawCart) {
        //-- split carts for each seller --//
        final Map<String, ItemSessionDataCart> sellerCarts = new HashMap<>();
        if (ItemSessionDataCart.getItemsCount(rawCart) > 0) {
            final List<DBObject> items = ItemSessionDataCart.getItems(rawCart);
            for (final DBObject item : items) {
                final String sellerId = ItemSessionDataCartItem.getSellerId(item);
                // get or creates cart for seller
                if (!sellerCarts.containsKey(sellerId)) {
                    sellerCarts.put(sellerId, new ItemSessionDataCart());
                }
                final ItemSessionDataCart sellerCart = sellerCarts.get(sellerId);
                // add item to seller cart
                sellerCart.addItem(item);
            }
        }
        return sellerCarts;
    }

    /**
     * Create payment from cart.
     * A Cart can host multiple store/seller,
     * so a list containing one transaction for each seller is created inside payment.
     *
     * @param customerId     ID of customer (must be registered)
     * @param rawCart        Cart instance (from checkout session)
     * @param callbackParams Callback parameters
     * @return Payment containing list of transaction
     */
    public static DBObject create(final String customerId, final DBObject rawCart, final DBObject callbackParams)
            throws Exception {
        final PaymentService srvc = new PaymentService();
        final DBObject payment = new Payment();
        final List<DBObject> transactions = new LinkedList<>();

        //-- split carts for each seller --//
        final Map<String, ItemSessionDataCart> sellerCarts = splitToSellersCart(rawCart);

        //-- loop on all carts and create a payment for each seller --//
        final Set<String> sellersIds = sellerCarts.keySet();
        for (final String sellerId : sellersIds) {
            final ItemSessionDataCart cart = sellerCarts.get(sellerId);
            final DBObject customer = UserService.get(customerId);
            final DBObject seller = UserService.get(sellerId);
            final ItemPayTransaction transaction = new ItemPayTransaction();
            ItemPayTransaction.setPaymentId(transaction, Payment.getId(payment));
            ItemPayTransaction.setCustomerId(transaction, customerId);
            ItemPayTransaction.setSellerId(transaction, sellerId);
            if (null != customer && null != seller) {
                ItemPayTransaction.setCallbackParams(transaction, callbackParams);
                ItemPayTransaction.setSellerEmail(transaction, User.getPayEmail(seller));
                ItemPayTransaction.setSellerType(transaction, ItemBillingUser.getType(User.getBilling(seller)));
                ItemPayTransaction.setCustomerEmail(transaction, User.getPayEmail(customer));
                ItemPayTransaction.setCart(transaction, cart);
            } else {
                if (null == seller) {
                    ItemPayTransaction.setError(transaction, "Seller not found: " + sellerId);
                } else {
                    ItemPayTransaction.setError(transaction, "Customer not found: " + customerId);
                }
            }
            // add to transaction list
            transactions.add(transaction);
        }
        Payment.setTransactions(payment, transactions);

        //-- process created payments calling seller payment system --//
        processPayments(transactions);

        //-- save payment and transactions --//
        srvc.upsert(payment);

        //-- empty session cart --//
        final String sessionId = ItemSessionDataCart.getSessionId(rawCart);
        try {
            final ItemSessionDataCart dataCart = new ItemSessionDataCart();
            ItemSessionDataCart.setSessionId(dataCart, sessionId);
            SessionManager.getInstance().setData(sessionId, dataCart.toString());
        } catch (Throwable t) {
            getStaticLogger().log(Level.WARNING,
                    FormatUtils.format("ERROR REGENERATING EMPTY CART DATA INTO SESSION: {0} - {1}", sessionId, t));
        }
        return payment;
    }

    /**
     * Return first url of payment to process.
     * Returns empty string if there are no more payments to process.
     *
     * @param id Payment ID
     * @return Payment redirect url (usually PayPal transaction url)
     */
    public static String getFirstUnprocessedTransactionUrl(final String id) {
        String result = null;
        try {
            final PaymentService srvc = new PaymentService();
            final DBObject payment = srvc.findById(id);
            if (null != payment) {
                boolean need_save = false;
                final List<DBObject> transactions = Payment.getTransactions(payment);
                for (final DBObject transaction : transactions) {
                    if (ItemPayTransaction.isCreated(transaction)) {
                        // verify is not processed
                        final PayPalResponse resp = PayPalManager.getInstance()
                                .paymentDetails(ItemPayTransaction.getPayKey(transaction));
                        if (!resp.isPayCompleted()) {
                            result = ItemPayTransaction.getPayUrl(transaction);
                            break;
                        } else {
                            // update existing transaction
                            final DBObject db_resp = MongoUtils.parseObject(resp);
                            ItemPayTransaction.setPayResponse(transaction, db_resp);
                            need_save = true;
                        }
                    }
                }
                if (need_save) {
                    srvc.upsert(payment);
                }
            }
        } catch (Throwable ignored) {

        }
        return result;
    }

    /**
     * Parse transactions and change payment type (status) to "close" or "partial".
     * "close" and "partial" payments will be asynchronously processed to generate selling orders.
     *
     * @param id Payment ID
     */
    public static void closePayment(final String id) {
        try {
            final PaymentService srvc = new PaymentService();
            final DBObject payment = srvc.findById(id);
            if (null != payment) {
                if (!Payment.isClose(payment)) {
                    int count_complete = 0;
                    final List<DBObject> transactions = Payment.getTransactions(payment);
                    for (final DBObject transaction : transactions) {
                        if (ItemPayTransaction.isCompleted(transaction)) {
                            count_complete++;
                        }
                    }
                    if (count_complete == transactions.size()) {
                        Payment.setClose(payment);
                    } else {
                        Payment.setPartial(payment);
                    }
                    srvc.upsert(payment);

                    //-- add scheduled job to generate order --//
                    PaymentPostProcessor.schedule(payment);
                }
            }
        } catch (Throwable ignored) {

        }
    }
}