From: <ms...@us...> - 2009-09-29 17:31:10
|
Revision: 9995 http://wonder.svn.sourceforge.net/wonder/?rev=9995&view=rev Author: mschrag Date: 2009-09-29 17:30:59 +0000 (Tue, 29 Sep 2009) Log Message: ----------- WONDER-328 Sandbox support for WOPayPal Modified Paths: -------------- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/.classpath trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAction.java trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAddToCartHyperlink.java trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemFormLink.java trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemHyperlink.java trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemLinkBase.java trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalViewShoppingCartHyperlink.java trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/WOPayPal.java Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/.classpath =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/.classpath 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/.classpath 2009-09-29 17:30:59 UTC (rev 9995) @@ -1,9 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry kind="src" path="Sources"/> - <classpathentry exported="true" kind="con" path="WOFramework/ERExtensions"/> <classpathentry exported="true" kind="con" path="WOFramework/ERDirectToWeb"/> - <classpathentry exported="true" kind="con" path="WOFramework/ERJars"/> <classpathentry exported="true" kind="con" path="WOFramework/ERJavaMail"/> <classpathentry exported="true" kind="con" path="WOFramework/ERPrototypes"/> <classpathentry exported="true" kind="con" path="WOFramework/JavaWOExtensions"/> @@ -18,5 +16,7 @@ <classpathentry exported="true" kind="con" path="WOFramework/JavaWOJSPServlet"/> <classpathentry exported="true" kind="con" path="WOFramework/JavaXML"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="WOFramework/ERJars"/> + <classpathentry kind="con" path="WOFramework/ERExtensions"/> <classpathentry kind="output" path="bin"/> </classpath> Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAction.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAction.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAction.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -11,6 +11,8 @@ import com.webobjects.eocontrol.*; import com.webobjects.eoaccess.*; +import er.extensions.foundation.ERXProperties; + /** PayPalAction is a DirectAction subclass that holds all the functionality for processing information that PayPal would send back to the application, including processing Instant Payment Notification communications, and responding to the successful and cancelled transaction pages to which PayPal will return users. Its action handler is PayPalAction, so your url will take the form: http://www.yoursite.com/cgi-bin/WebObjects/yourAppName.woa/wa/PayPalAction/actionName... */ public class PayPalAction extends WODirectAction { @@ -21,6 +23,9 @@ /** The cgi portion of PayPal's url for doing Instant Payment Notification verifications */ public static final String paypalCgi="/cgi-bin/webscr"; + /** PayPal developer sandbox URL + */ + public static final String sandboxSite = "www.sandbox.paypal.com"; /** Constructor * @@ -39,22 +44,33 @@ * * The notification gets picked up by the PayPalNotificationListenerClass, which then hands it to the delegate class you assigned to handle the notification. Pretty simple. */ - public void ipnAction() { // processor for Instant Payment Notifications + public WOActionResults ipnAction() { // processor for Instant Payment Notifications + boolean isSandboxMode = false; + WORequest ppIPNRequest = request(); // the incoming PayPal IPN (Instant Payment Notification) if (NSLog.debugLoggingAllowedForLevel(NSLog.DebugLevelInformational)) { NSLog.debug.appendln("PayPal's request looks like: " + ppIPNRequest + "\n\n"); NSLog.debug.appendln("PayPal's request content looks like: " + ppIPNRequest.contentString() + "\n\n"); } + + WOResponse ppValidationResponse = null; // PayPal's validation of our echoed data + String ppValidationResponseString = null; + boolean connectionSuccess; + if (ppIPNRequest.formValues().containsKey("test_ipn")) { + isSandboxMode = true; + } else { + isSandboxMode = false; + } String returnString = ppIPNRequest.contentString() + "&cmd=_notify-validate"; - - WOHTTPConnection ppEchoConnection = new WOHTTPConnection(paypalSite, 80); // our echo to PayPal - WOResponse ppValidationResponse = new WOResponse(); // PayPal's validation of our echoed data - + WOHTTPConnection ppEchoConnection = new WOHTTPConnection(paypalSite, 80); // our echo to PayPal + if (isSandboxMode) { + ppEchoConnection = new WOHTTPConnection(sandboxSite, 80); // our echo to PayPal + } // assemble User-Agent header StringBuffer ua = new StringBuffer(); - ua.append("WebObjects/5.1 [en] ("); + ua.append("WebObjects/ " + ERXProperties.webObjectsVersion() + " ("); ua.append(System.getProperty("os.arch")); ua.append("; "); ua.append(System.getProperty("os.name")); @@ -69,20 +85,26 @@ headers.setObjectForKey(ua.toString(),"User-Agent"); // the response back to PayPal - WORequest paypalEchoRequest = new WORequest("POST", paypalCgi, "HTTP/1.1", headers, null, null); + WORequest paypalEchoRequest; + paypalEchoRequest = new WORequest("POST", paypalCgi, "HTTP/1.1", headers, null, null); paypalEchoRequest.setContent(returnString); ppEchoConnection.setReceiveTimeout(90 * 1000); // 90 second timeout -- this might be too long!?! - boolean success = ppEchoConnection.sendRequest(paypalEchoRequest); - if (success) { - ppValidationResponse = ppEchoConnection.readResponse(); // read PayPal's validation + connectionSuccess = ppEchoConnection.sendRequest(paypalEchoRequest); + if (connectionSuccess) { + ppValidationResponse = ppEchoConnection.readResponse(); // read PayPal's validation + } + + ppValidationResponseString = ppValidationResponse.contentString(); + + if (connectionSuccess) { // PayPal's response *content* will either be "VERIFIED" or "INVALID" if (NSLog.debugLoggingAllowedForLevel(NSLog.DebugLevelInformational)) { NSLog.debug.appendln("the response looks like: " + ppValidationResponse + "\n\n"); - NSLog.debug.appendln("the response content looks like: " + ppValidationResponse.contentString() + "\n\n"); + NSLog.debug.appendln("the response content looks like: " + ppValidationResponseString + "\n\n"); } - if (ppValidationResponse.contentString().equalsIgnoreCase("VERIFIED")) { + if (ppValidationResponseString.equalsIgnoreCase("VERIFIED")) { if (((String)ppIPNRequest.formValueForKey("payment_status")).equalsIgnoreCase("completed")) { //should check previous txn_id's to be sure this isn't a duplicate notification @@ -101,12 +123,11 @@ NSNotificationCenter.defaultCenter().postNotification(PayPalNotificationListener.DeniedPayPalPaymentReceivedNotification, ppIPNRequest); } else { - // the payment_status value is not any of the accepted values + // the payment_status value is not any of the accepted values } - } else if (ppValidationResponse.contentString().equalsIgnoreCase("INVALID")) { - // possible fraud!!! - NSNotificationCenter.defaultCenter().postNotification(PayPalNotificationListener.InvalidPayPalPaymentReceivedNotification, ppIPNRequest); - + } else if (ppValidationResponseString.equalsIgnoreCase("INVALID")) { + // possible fraud!!! + NSNotificationCenter.defaultCenter().postNotification(PayPalNotificationListener.InvalidPayPalPaymentReceivedNotification, ppIPNRequest); } else { // received unaccepted response content string value -- log error and incoming i.p. address NSLog.err.appendln("PayPalAction->ipnAction: PayPal transaction validation returned unaccepted validation status from i.p: " + (((String)ppIPNRequest.headerForKey("REMOTE_ADDR") != null) ? (String)ppIPNRequest.headerForKey("REMOTE_ADDR") : "- unknown -")); @@ -115,6 +136,7 @@ NSLog.err.appendln("PayPalAction->ipnAction: PayPal transaction validation connection failed."); } + return new OKResponse(); } /** Provides a default method to return the page to which PayPal will send users after a successful transaction. @@ -150,4 +172,24 @@ } + + private static class HTTPStatusResponse extends WOResponse { + public static void setResponse( WOResponse response, int statusInt, String statusString ) { + String contentString = "HTTP/1.0 "+statusInt+" "+statusString; + response.appendContentString( contentString ); + response.setHeader( ""+contentString.length(), "content-length" ); + response.setHeader( "text/html", "content-type" ); + response.setStatus( statusInt ); + } + public HTTPStatusResponse( int statusInt, String statusString ) { + super(); + HTTPStatusResponse.setResponse( this, statusInt, statusString ); + } + } + + private static class OKResponse extends HTTPStatusResponse { + public OKResponse() { + super( 200, "OK" ); + } + } } Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAddToCartHyperlink.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAddToCartHyperlink.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalAddToCartHyperlink.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -19,7 +19,7 @@ /** The cgi command we're calling on PayPal's server. */ - protected static String PAYPAL_CGI_COMMAND = "cart/add=1"; + protected static String PAYPAL_CGI_COMMAND = "?cmd=_cart&add=1"; /** Constructor @@ -37,9 +37,9 @@ * PayPal shopping cart. */ public String addToCartHref() { - StringBuffer sb = new StringBuffer(); + StringBuffer sb = WOPayPal.baseUrl(); - sb.append(WOPayPal.PAYPAL_SECURE_URL_BASE); // required -- duh!!! + sb.append(PayPalSingleItemLinkBase.PAYPAL_CGI_NAME); sb.append(PAYPAL_CGI_COMMAND); sb.append(payPalUrlParams()); Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemFormLink.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemFormLink.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemFormLink.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -119,6 +119,10 @@ } else if (key.equals("notify_url") && useIPN.booleanValue()) { boundValues.addObject(new NSDictionary(new Object[] { notifyURL, "notify_url"}, new Object[] {"value", "key"})); + } else if (key.equals("tax_rate")) { + boundValues.addObject(new NSDictionary(new Object[] { + dollarFormatter.format(Double.valueOf(tax_rate)), "tax_rate"}, + new Object[] {"value", "key"})); } else { // received some other binding value somehow } Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemHyperlink.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemHyperlink.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemHyperlink.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -52,8 +52,7 @@ * @return String */ public String payPalPurchaseHref() { - StringBuffer sb = new StringBuffer(); - sb.append(WOPayPal.PAYPAL_SECURE_URL_BASE); // required -- duh!!! + StringBuffer sb = WOPayPal.baseUrl(); sb.append(PayPalSingleItemLinkBase.PAYPAL_CGI_NAME); sb.append(PAYPAL_CGI_COMMAND); sb.append(payPalUrlParams()); @@ -67,6 +66,7 @@ */ public String payPalUrlParams() { // this should probably have much more robust error handling DecimalFormat currencyFormatter = new DecimalFormat("##0.00", new DecimalFormatSymbols(Locale.US)); + DecimalFormat taxFormatter = new DecimalFormat("##0.000", new DecimalFormatSymbols(Locale.US)); StringBuffer sb = new StringBuffer(); sb.append("&business=" + urlEncode(payPalBusinessName) ); // required!!! @@ -110,8 +110,10 @@ sb.append("¬ify_url=" + PayPalEmailURLUTF8Encoder.encode(defaultNotificationURL()) ); } } + if (tax_rate != null) { + sb.append("&tax_rate=" + taxFormatter.format(Double.valueOf(tax_rate)) ); + } - return sb.toString(); } Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemLinkBase.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemLinkBase.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalSingleItemLinkBase.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -71,6 +71,10 @@ /** use the default IPN Notification URL from the PayPalAction class? */ public Boolean useDefaultIPNURL; + + /** Transaction-based tax override variable. + */ + public String tax_rate; /** Constructor. * @@ -99,7 +103,8 @@ "cancelURL", "notifyURL", "useIPN", - "useDefaultIPNURL" }); + "useDefaultIPNURL", + "tax_rate"}); } /** for subclasses to add additional bindings Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalViewShoppingCartHyperlink.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalViewShoppingCartHyperlink.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/PayPalViewShoppingCartHyperlink.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -19,7 +19,7 @@ /** The cgi command we're calling on PayPal's server. */ - protected static String PAYPAL_CGI_COMMAND = "cart/display=1"; + protected static String PAYPAL_CGI_COMMAND = "?cmd=_cart&display=1"; /** Constructor * @@ -35,9 +35,9 @@ * */ public String viewShoppingCartHref() { - StringBuffer sb = new StringBuffer(); + StringBuffer sb = WOPayPal.baseUrl(); - sb.append(WOPayPal.PAYPAL_SECURE_URL_BASE); + sb.append(PayPalSingleItemLinkBase.PAYPAL_CGI_NAME); sb.append(PAYPAL_CGI_COMMAND); sb.append(payPalUrlParams()); Modified: trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/WOPayPal.java =================================================================== --- trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/WOPayPal.java 2009-09-29 17:20:42 UTC (rev 9994) +++ trunk/Wonder/Frameworks/BusinessLogic/WOPayPal/Sources/er/wopaypal/WOPayPal.java 2009-09-29 17:30:59 UTC (rev 9995) @@ -11,6 +11,9 @@ import com.webobjects.foundation.*; import com.webobjects.eocontrol.*; import com.webobjects.eoaccess.*; + +import er.extensions.foundation.ERXProperties; + import java.util.*; /** WOPayPal is the principal class in the framework. It gets initialized first, and contains the setup for initializing the framework's functionality @@ -18,9 +21,14 @@ public class WOPayPal { public static final String PAYPAL_URL_BASE = "http://www.paypal.com/"; public static final String PAYPAL_SECURE_URL_BASE = "https://www.paypal.com/"; + public static final String PAYPAL_SANDBOX_URL_BASE = "https://www.sandbox.paypal.com/"; public static final Class[] NotificationClassArray = { com.webobjects.foundation.NSNotification.class }; private static NSMutableSet _retainer = new NSMutableSet(); + /** Property name to determine if we are using the sandbox or the live site + */ + public static final String SANDBOX_MODE_PROP = "er.wopaypal.sandboxmode"; + /** Constructor. */ public WOPayPal() { @@ -73,6 +81,25 @@ PayPalNotificationListener.ValidPayPalPaymentReceivedNotification, null); } + + /** + * Does the er.wopaypal.sandboxmode is set to true? + */ + public static final boolean isSandboxMode() { + return ERXProperties.booleanForKeyWithDefault(SANDBOX_MODE_PROP, false); + } + + /** + * Return the base URL for the PayPal site, either the live or sandbox URL. + */ + public static final StringBuffer baseUrl() { + StringBuffer sb = new StringBuffer(); + if (WOPayPal.isSandboxMode()) { + sb.append(WOPayPal.PAYPAL_SANDBOX_URL_BASE); + } else { + sb.append(WOPayPal.PAYPAL_SECURE_URL_BASE); + } + return sb; + } - } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |