package er.wopaypal; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Enumeration; import java.util.Locale; import org.apache.commons.lang3.CharEncoding; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORequest; import com.webobjects.appserver.WOResponse; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSLog; import com.webobjects.foundation.NSMutableArray; public class PayPalSingleItemHyperlink extends PayPalSingleItemLinkBase { /** The cgi command we're calling on PayPal's server. */ protected static String PAYPAL_CGI_COMMAND = "?cmd=_xclick"; /** Constructor * * @param context WOContext */ public PayPalSingleItemHyperlink(WOContext context) { super(context); } /** Makes the component stateless. * * @return boolean */ @Override public boolean isStateless() { return true; } /** Assembles the url to send to PayPal for the single item purchase * * @return String */ public String payPalPurchaseHref() { StringBuffer sb = WOPayPal.baseUrl(); sb.append(PayPalSingleItemLinkBase.PAYPAL_CGI_NAME); sb.append(PAYPAL_CGI_COMMAND); sb.append(payPalUrlParams()); return sb.toString(); } /** Assembles the string of parameters for the payPalPurchaseHref. It returns the binding values encoded into the format PayPal expects in order to successfully process the url params. * * @return String */ 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)); StringBuilder sb = new StringBuilder(); sb.append("&business=" + urlEncode(payPalBusinessName) ); // required!!! if (userDefinableQuantity!=null) { sb.append("&undefined_quantity=" + (userDefinableQuantity.booleanValue() ? "1" : "0") ); } if (itemName != null) { sb.append("&item_name=" + urlEncode(itemName) ); } if (itemNumber != null) { sb.append("&item_number=" + urlEncode(itemNumber) ); } if (custom != null) { sb.append("&custom=" + urlEncode(custom) ); } if (amount != null) { sb.append("&amount=" + currencyFormatter.format(Double.valueOf(amount)) ); } if (currencyCode != null) { sb.append("¤cy_code=" + urlEncode(currencyCode) ); } if (collectShippingAddress != null) { sb.append("&no_shipping=" + (collectShippingAddress.booleanValue() ? "0" : "1") ); } if (allowCustomerNote != null) { sb.append("&no_note=" + (allowCustomerNote.booleanValue() ? "0" : "1") ); } if (logoURL != null) { sb.append("&image_url=" + PayPalEmailURLUTF8Encoder.encode(logoURL) ); } if (returnURL != null) { sb.append("&return=" + PayPalEmailURLUTF8Encoder.encode(returnURL) ); } if (cancelURL != null) { sb.append("&cancel_return=" + PayPalEmailURLUTF8Encoder.encode(cancelURL) ); } if (notifyURL != null) { sb.append("¬ify_url=" + PayPalEmailURLUTF8Encoder.encode(notifyURL) ); } else { if (useIPN != null && useIPN.booleanValue()) { sb.append("¬ify_url=" + PayPalEmailURLUTF8Encoder.encode(defaultNotificationURL()) ); } } if (tax_rate != null) { sb.append("&tax_rate=" + taxFormatter.format(Double.valueOf(tax_rate)) ); } return sb.toString(); } /** * URL encodes the input string. * @param input to encode * @return the encoded input string or null if the encoding fails */ private String urlEncode(String input) { String output = null; if (input != null) { try { output = URLEncoder.encode(input, CharEncoding.UTF_8); } catch (UnsupportedEncodingException uee) { NSLog.err.appendln("Could not URL encode input string. Error: " + uee.getMessage()); } } return output; } /** additionalBindingList is a NSArray of bindings to pull when we synchronize our values with the WOComponent's binding settings. It's a simple way to customize the bindings that should be pulled, in addition to the superclass' base list of bindings that it cares about (baseBindingList()). * * @return NSArray */ @Override protected NSArray additionalBindingList() { NSMutableArray bindingArray = new NSMutableArray(); // super.bindingList(); bindingArray.addObjectsFromArray(new NSArray(new Object[] {})); return bindingArray; } /** Manually synchronizes the values from the WOComponent. It does this by enumerating first through the baseBindingList() and then the additionalBindingList() */ protected void pullBindings() { Enumeration enumeration = baseBindingList().objectEnumerator(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); takeValueForKey(valueForBinding(key), key); } enumeration = additionalBindingList().objectEnumerator(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); takeValueForKey(valueForBinding(key), key); } } /** Resets the values pulled from the WOComponent to null. */ @Override public void reset() { Enumeration enumeration = baseBindingList().objectEnumerator(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); takeValueForKey(null, key); } enumeration = additionalBindingList().objectEnumerator(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); takeValueForKey(null, key); } super.reset(); } /** Overrides the default behavior and tells the Component to synchronize its ivar values with those bound to the WOComponent's bindings by calling pullBindings() * * @param r WOResponse * @param c WOContext */ @Override public void appendToResponse(WOResponse r, WOContext c) { pullBindings(); super.appendToResponse(r,c); } /** Overrides the default behavior and tells the Component to synchronize its ivar values with those bound to the WOComponent's bindings by calling pullBindings() * * @param r WORequest * @param c WOContext */ @Override public void takeValuesFromRequest(WORequest r, WOContext c) { pullBindings(); super.takeValuesFromRequest(r,c); } /** Overrides the default behavior and tells the Component to synchronize its ivar values with those bound to the WOComponent's bindings by calling pullBindings() * * @param r WOResponse * @param c WOContext * @return WOActionResults */ @Override public WOActionResults invokeAction(WORequest r, WOContext c) { pullBindings(); return super.invokeAction(r,c); } }