KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ofbiz > accounting > thirdparty > paypal > PayPalEvents


1 /*
2  * $Id: PayPalEvents.java 6642 2006-02-01 02:29:51Z sichen $
3  *
4  * Copyright (c) 2001-2005 The Open For Business Project - www.ofbiz.org
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
21  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */

25 package org.ofbiz.accounting.thirdparty.paypal;
26
27 import java.io.BufferedReader JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStreamReader JavaDoc;
30 import java.io.PrintWriter JavaDoc;
31 import java.net.URL JavaDoc;
32 import java.net.URLConnection JavaDoc;
33 import java.text.ParseException JavaDoc;
34 import java.text.SimpleDateFormat JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.LinkedList JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40 import javax.servlet.ServletContext JavaDoc;
41 import javax.servlet.ServletRequest JavaDoc;
42 import javax.servlet.http.HttpServletRequest JavaDoc;
43 import javax.servlet.http.HttpServletResponse JavaDoc;
44
45 import org.ofbiz.base.util.Debug;
46 import org.ofbiz.base.util.UtilDateTime;
47 import org.ofbiz.base.util.UtilFormatOut;
48 import org.ofbiz.base.util.UtilHttp;
49 import org.ofbiz.base.util.UtilMisc;
50 import org.ofbiz.base.util.UtilProperties;
51 import org.ofbiz.base.util.UtilValidate;
52 import org.ofbiz.entity.GenericDelegator;
53 import org.ofbiz.entity.GenericEntityException;
54 import org.ofbiz.entity.GenericValue;
55 import org.ofbiz.entity.transaction.GenericTransactionException;
56 import org.ofbiz.entity.transaction.TransactionUtil;
57 import org.ofbiz.order.order.OrderChangeHelper;
58 import org.ofbiz.product.catalog.CatalogWorker;
59 import org.ofbiz.product.store.ProductStoreWorker;
60 import org.ofbiz.service.GenericServiceException;
61 import org.ofbiz.service.ModelService;
62 import org.ofbiz.service.LocalDispatcher;
63
64 import org.apache.commons.collections.map.LinkedMap;
65
66 /**
67  * PayPal Events
68  *
69  * @author <a HREF="mailto:jaz@ofbiz.org">Andy Zeneski</a>
70  * @version $Rev: 6642 $
71  * @since 2.0
72  */

73 public class PayPalEvents {
74     
75     public static final String JavaDoc module = PayPalEvents.class.getName();
76     
77     /** Initiate PayPal Request */
78     public static String JavaDoc callPayPal(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
79         ServletContext JavaDoc application = ((ServletContext JavaDoc) request.getAttribute("servletContext"));
80         GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
81         LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
82         GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
83                 
84         // get the orderId
85
String JavaDoc orderId = (String JavaDoc) request.getAttribute("orderId");
86         
87         // get the order header
88
GenericValue orderHeader = null;
89         try {
90             orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
91         } catch (GenericEntityException e) {
92             Debug.logError(e, "Cannot get the order header for order: " + orderId, module);
93             request.setAttribute("_ERROR_MESSAGE_", "Problems getting order header.");
94             return "error";
95         }
96         
97         // get the order total
98
String JavaDoc orderTotal = UtilFormatOut.formatPrice(orderHeader.getDouble("grandTotal"));
99             
100         // get the webSiteId
101
String JavaDoc webSiteId = CatalogWorker.getWebSiteId(request);
102         
103         // get the product store
104
GenericValue productStore = ProductStoreWorker.getProductStore(request);
105
106         if (productStore == null) {
107             Debug.logError("ProductStore is null", module);
108             request.setAttribute("_ERROR_MESSAGE_", "Problems getting merchant configuration, please contact customer service.");
109             return "error";
110         }
111         
112         // get the payment properties file
113
GenericValue paymentConfig = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStore.getString("productStoreId"), "EXT_PAYPAL", null, true);
114         String JavaDoc configString = null;
115         if (paymentConfig != null) {
116             configString = paymentConfig.getString("paymentPropertiesPath");
117         }
118                 
119         if (configString == null) {
120             configString = "payment.properties";
121         }
122                         
123         // get the company name
124
String JavaDoc company = UtilFormatOut.checkEmpty(productStore.getString("companyName"), "");
125         
126         // create the item name
127
String JavaDoc itemName = "Order #" + orderId + (company != null ? " from " + company : "");
128         String JavaDoc itemNumber = "0";
129         
130         // get the redirect url
131
String JavaDoc redirectUrl = UtilProperties.getPropertyValue(configString, "payment.paypal.redirect");
132         
133         // get the notify url
134
String JavaDoc notifyUrl = UtilProperties.getPropertyValue(configString, "payment.paypal.notify");
135         
136         // get the return urls
137
String JavaDoc returnUrl = UtilProperties.getPropertyValue(configString, "payment.paypal.return");
138         String JavaDoc cancelReturnUrl = UtilProperties.getPropertyValue(configString, "payment.paypal.cancelReturn");
139         
140         // get the image url
141
String JavaDoc imageUrl = UtilProperties.getPropertyValue(configString, "payment.paypal.image");
142         
143         // get the paypal account
144
String JavaDoc payPalAccount = UtilProperties.getPropertyValue(configString, "payment.paypal.business");
145                 
146         // create the redirect string
147
Map JavaDoc parameters = new LinkedMap();
148         parameters.put("cmd", "_xclick");
149         parameters.put("business", payPalAccount);
150         parameters.put("item_name", itemName);
151         parameters.put("item_number", itemNumber);
152         parameters.put("invoice", orderId);
153         parameters.put("custom", userLogin.getString("userLoginId"));
154         parameters.put("amount", orderTotal);
155         parameters.put("return", returnUrl);
156         parameters.put("cancel_return", cancelReturnUrl);
157         parameters.put("notify_url", notifyUrl);
158         parameters.put("image_url", imageUrl);
159         parameters.put("no_note", "1"); // no notes allowed in paypal (not passed back)
160
parameters.put("no_shipping", "1"); // no shipping address required (local shipping used)
161

162         String JavaDoc encodedParameters = UtilHttp.urlEncodeArgs(parameters, false);
163         String JavaDoc redirectString = redirectUrl + "?" + encodedParameters;
164         
165         // set the order in the session for cancelled orders
166
request.getSession().setAttribute("PAYPAL_ORDER", orderId);
167         
168         // redirect to paypal
169
try {
170             response.sendRedirect(redirectString);
171         } catch (IOException JavaDoc e) {
172             Debug.logError(e, "Problems redirecting to PayPal", module);
173             request.setAttribute("_ERROR_MESSAGE_", "Problems connecting with PayPal, please contact customer service.");
174             return "error";
175         }
176         
177         return "success";
178     }
179     
180     /** PayPal Call-Back Event */
181     public static String JavaDoc payPalIPN(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
182         ServletContext JavaDoc application = ((ServletContext JavaDoc) request.getAttribute("servletContext"));
183         GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
184         LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
185         
186         // get the webSiteId
187
String JavaDoc webSiteId = CatalogWorker.getWebSiteId(request);
188
189         // get the product store
190
GenericValue productStore = ProductStoreWorker.getProductStore(request);
191
192         // get the payment properties file
193
GenericValue paymentConfig = ProductStoreWorker.getProductStorePaymentSetting(delegator, productStore.getString("productStoreId"), "EXT_PAYPAL", null, true);
194         String JavaDoc configString = null;
195         if (paymentConfig != null) {
196             configString = paymentConfig.getString("paymentPropertiesPath");
197         }
198
199         if (configString == null) {
200             configString = "payment.properties";
201         }
202                
203         // get the confirm URL
204
String JavaDoc confirmUrl = UtilProperties.getPropertyValue(configString, "payment.paypal.confirm");
205         if (confirmUrl == null) {
206             Debug.logError("Payment properties is not configured properly, no confirm URL defined!", module);
207             request.setAttribute("_ERROR_MESSAGE_", "PayPal has not been configured, please contact customer service.");
208             return "error";
209         }
210                 
211         // first verify this is valid from PayPal
212
Map JavaDoc parametersMap = UtilHttp.getParameterMap(request);
213         parametersMap.put("cmd", "_notify-validate");
214         
215         // send off the confirm request
216
String JavaDoc confirmResp = null;
217
218         try {
219             String JavaDoc str = UtilHttp.urlEncodeArgs(parametersMap);
220             URL JavaDoc u = new URL JavaDoc("http://www.paypal.com/cgi-bin/webscr");
221             URLConnection JavaDoc uc = u.openConnection();
222             uc.setDoOutput(true);
223             uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
224             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(uc.getOutputStream());
225             pw.println(str);
226             pw.close();
227
228             BufferedReader JavaDoc in = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(uc.getInputStream()));
229             confirmResp = in.readLine();
230             in.close();
231             Debug.logError("PayPal Verification Response: " + confirmResp, module);
232         } catch (IOException JavaDoc e) {
233             Debug.logError(e, "Problems sending verification message", module);
234         }
235
236         if (confirmResp.trim().equals("VERIFIED")) {
237             // we passed verification
238
Debug.logInfo("Got verification from PayPal, processing..", module);
239         } else {
240             Debug.logError("###### PayPal did not verify this request, need investigation!", module);
241             Set JavaDoc keySet = parametersMap.keySet();
242             Iterator JavaDoc i = keySet.iterator();
243             while (i.hasNext()) {
244                 String JavaDoc name = (String JavaDoc) i.next();
245                 String JavaDoc value = request.getParameter(name);
246                 Debug.logError("### Param: " + name + " => " + value, module);
247             }
248         }
249         
250         // get the user
251
GenericValue userLogin = null;
252         String JavaDoc userLoginId = request.getParameter("custom");
253         if (userLoginId == null)
254             userLoginId = "admin";
255         try {
256             userLogin = delegator.findByPrimaryKey("UserLogin", UtilMisc.toMap("userLoginId", userLoginId));
257         } catch (GenericEntityException e) {
258             Debug.logError(e, "Cannot get UserLogin for: " + userLoginId + "; cannot continue", module);
259             request.setAttribute("_ERROR_MESSAGE_", "Problems getting authentication user.");
260             return "error";
261         }
262                                
263         // get the orderId
264
String JavaDoc orderId = request.getParameter("invoice");
265
266         // get the order header
267
GenericValue orderHeader = null;
268         if (UtilValidate.isNotEmpty(orderId)) {
269             try {
270                 orderHeader = delegator.findByPrimaryKey("OrderHeader", UtilMisc.toMap("orderId", orderId));
271             } catch (GenericEntityException e) {
272                 Debug.logError(e, "Cannot get the order header for order: " + orderId, module);
273                 request.setAttribute("_ERROR_MESSAGE_", "Problems getting order header.");
274                 return "error";
275             }
276         } else {
277             Debug.logError("PayPal did not callback with a valid orderId!", module);
278             request.setAttribute("_ERROR_MESSAGE_", "No valid orderId returned with PayPal Callback.");
279             return "error";
280         }
281
282         if (orderHeader == null) {
283             Debug.logError("Cannot get the order header for order: " + orderId, module);
284             request.setAttribute("_ERROR_MESSAGE_", "Problems getting order header; not a valid orderId.");
285             return "error";
286         }
287
288         // get payment data
289
String JavaDoc paymentCurrency = request.getParameter("mc_currency");
290         String JavaDoc paymentAmount = request.getParameter("mc_gross");
291         String JavaDoc paymentFee = request.getParameter("mc_fee");
292         String JavaDoc transactionId = request.getParameter("txn_id");
293
294         // get the transaction status
295
String JavaDoc paymentStatus = request.getParameter("payment_status");
296
297         // attempt to start a transaction
298
boolean okay = false;
299         boolean beganTransaction = false;
300         try {
301             beganTransaction = TransactionUtil.begin();
302
303             if (paymentStatus.equals("Completed")) {
304                 okay = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
305             } else if (paymentStatus.equals("Failed") || paymentStatus.equals("Denied")) {
306                 okay = OrderChangeHelper.cancelOrder(dispatcher, userLogin, orderId);
307             }
308
309             if (okay) {
310                 // set the payment preference
311
okay = setPaymentPreferences(delegator, dispatcher, userLogin, orderId, request);
312             }
313         } catch (Exception JavaDoc e) {
314             String JavaDoc errMsg = "Error handling PayPal notification";
315             Debug.logError(e, errMsg, module);
316             try {
317                 TransactionUtil.rollback(beganTransaction, errMsg, e);
318             } catch (GenericTransactionException gte2) {
319                 Debug.logError(gte2, "Unable to rollback transaction", module);
320             }
321         } finally {
322             if (!okay) {
323                 try {
324                     TransactionUtil.rollback(beganTransaction, "Failure in processing PayPal callback", null);
325                 } catch (GenericTransactionException gte) {
326                     Debug.logError(gte, "Unable to rollback transaction", module);
327                 }
328             } else {
329                 try {
330                     TransactionUtil.commit(beganTransaction);
331                 } catch (GenericTransactionException gte) {
332                     Debug.logError(gte, "Unable to commit transaction", module);
333                 }
334             }
335         }
336
337
338         if (okay) {
339             // attempt to release the offline hold on the order (workflow)
340
OrderChangeHelper.releaseInitialOrderHold(dispatcher, orderId);
341
342             // call the email confirm service
343
Map JavaDoc emailContext = UtilMisc.toMap("orderId", orderId);
344             try {
345                 Map JavaDoc emailResult = dispatcher.runSync("sendOrderConfirmation", emailContext);
346             } catch (GenericServiceException e) {
347                 Debug.logError(e, "Problems sending email confirmation", module);
348             }
349         }
350
351         return "success";
352     }
353         
354     /** Event called when customer cancels a paypal order */
355     public static String JavaDoc cancelPayPalOrder(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) {
356         ServletContext JavaDoc application = ((ServletContext JavaDoc) request.getAttribute("servletContext"));
357         GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
358         LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
359         GenericValue userLogin = (GenericValue) request.getSession().getAttribute("userLogin");
360         
361         // get the stored order id from the session
362
String JavaDoc orderId = (String JavaDoc) request.getSession().getAttribute("PAYPAL_ORDER");
363                 
364         // attempt to start a transaction
365
boolean beganTransaction = false;
366         try {
367             beganTransaction = TransactionUtil.begin();
368         } catch (GenericTransactionException gte) {
369             Debug.logError(gte, "Unable to begin transaction", module);
370         }
371               
372         // cancel the order
373
boolean okay = OrderChangeHelper.cancelOrder(dispatcher, userLogin, orderId);
374         
375         if (okay) {
376             try {
377                 TransactionUtil.commit(beganTransaction);
378             } catch (GenericTransactionException gte) {
379                 Debug.logError(gte, "Unable to commit transaction", module);
380             }
381         } else {
382             try {
383                 TransactionUtil.rollback(beganTransaction, "Failure in processing PayPal cancel callback", null);
384             } catch (GenericTransactionException gte) {
385                 Debug.logError(gte, "Unable to rollback transaction", module);
386             }
387         }
388         
389         // attempt to release the offline hold on the order (workflow)
390
if (okay)
391             OrderChangeHelper.releaseInitialOrderHold(dispatcher, orderId);
392             
393         request.setAttribute("_EVENT_MESSAGE_", "Previous PayPal order has been cancelled.");
394         return "success";
395     }
396     
397     private static boolean setPaymentPreferences(GenericDelegator delegator, LocalDispatcher dispatcher, GenericValue userLogin, String JavaDoc orderId, ServletRequest JavaDoc request) {
398         Debug.logVerbose("Setting payment prefrences..", module);
399         List JavaDoc paymentPrefs = null;
400         try {
401             Map JavaDoc paymentFields = UtilMisc.toMap("orderId", orderId, "statusId", "PAYMENT_NOT_RECEIVED");
402             paymentPrefs = delegator.findByAnd("OrderPaymentPreference", paymentFields);
403         } catch (GenericEntityException e) {
404             Debug.logError(e, "Cannot get payment preferences for order #" + orderId, module);
405             return false;
406         }
407         if (paymentPrefs != null && paymentPrefs.size() > 0) {
408             Iterator JavaDoc i = paymentPrefs.iterator();
409             while (i.hasNext()) {
410                 GenericValue pref = (GenericValue) i.next();
411                 boolean okay = setPaymentPreference(dispatcher, userLogin, pref, request);
412                 if (!okay)
413                     return false;
414             }
415         }
416         return true;
417     }
418         
419     private static boolean setPaymentPreference(LocalDispatcher dispatcher, GenericValue userLogin, GenericValue paymentPreference, ServletRequest JavaDoc request) {
420         String JavaDoc paymentDate = request.getParameter("payment_date");
421         String JavaDoc paymentType = request.getParameter("payment_type");
422         String JavaDoc paymentAmount = request.getParameter("mc_gross");
423         String JavaDoc paymentStatus = request.getParameter("payment_status");
424         String JavaDoc transactionId = request.getParameter("txn_id");
425
426         List JavaDoc toStore = new LinkedList JavaDoc();
427
428         // PayPal returns the timestamp in the format 'hh:mm:ss Jan 1, 2000 PST'
429
// Parse this into a valid Timestamp Object
430
SimpleDateFormat JavaDoc sdf = new SimpleDateFormat JavaDoc("hh:mm:ss MMM d, yyyy z");
431         java.sql.Timestamp JavaDoc authDate = null;
432         try {
433             authDate = new java.sql.Timestamp JavaDoc(sdf.parse(paymentDate).getTime());
434         } catch (ParseException JavaDoc e) {
435             Debug.logError(e, "Cannot parse date string: " + paymentDate, module);
436             authDate = UtilDateTime.nowTimestamp();
437         } catch (NullPointerException JavaDoc e) {
438             Debug.logError(e, "Cannot parse date string: " + paymentDate, module);
439             authDate = UtilDateTime.nowTimestamp();
440         }
441
442         paymentPreference.set("maxAmount", new Double JavaDoc(paymentAmount));
443         if (paymentStatus.equals("Completed")) {
444             paymentPreference.set("statusId", "PAYMENT_RECEIVED");
445         } else {
446             paymentPreference.set("statusId", "PAYMENT_CANCELLED");
447         }
448         toStore.add(paymentPreference);
449
450
451         GenericDelegator delegator = paymentPreference.getDelegator();
452
453         // create the PaymentGatewayResponse
454
String JavaDoc responseId = delegator.getNextSeqId("PaymentGatewayResponse").toString();
455         GenericValue response = delegator.makeValue("PaymentGatewayResponse", null);
456         response.set("paymentGatewayResponseId", responseId);
457         response.set("paymentServiceTypeEnumId", "PRDS_PAY_EXTERNAL");
458         response.set("orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"));
459         response.set("paymentMethodTypeId", paymentPreference.get("paymentMethodTypeId"));
460         response.set("paymentMethodId", paymentPreference.get("paymentMethodId"));
461
462         // set the auth info
463
response.set("amount", new Double JavaDoc(paymentAmount));
464         response.set("referenceNum", transactionId);
465         response.set("gatewayCode", paymentStatus);
466         response.set("gatewayFlag", paymentStatus.substring(0,1));
467         response.set("gatewayMessage", paymentType);
468         response.set("transactionDate", authDate);
469         toStore.add(response);
470
471         // create a payment record too
472
Map JavaDoc results = null;
473         try {
474             results = dispatcher.runSync("createPaymentFromPreference", UtilMisc.toMap("userLogin", userLogin,
475                     "orderPaymentPreferenceId", paymentPreference.get("orderPaymentPreferenceId"), "comments", "Payment receive via PayPal"));
476         } catch (GenericServiceException e) {
477             Debug.logError(e, "Failed to execute service createPaymentFromPreference", module);
478             request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
479             return false;
480         }
481
482         if ((results == null) || (results.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_ERROR))) {
483             Debug.logError((String JavaDoc) results.get(ModelService.ERROR_MESSAGE), module);
484             request.setAttribute("_ERROR_MESSAGE_", (String JavaDoc) results.get(ModelService.ERROR_MESSAGE));
485             return false;
486         }
487
488         try {
489             delegator.storeAll(toStore);
490         } catch (GenericEntityException e) {
491             Debug.logError(e, "Cannot set payment preference/payment info", module);
492             return false;
493         }
494         return true;
495     }
496
497 }
498
Popular Tags