Java tutorial
/* * 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) { } } }