Why Java servlet can't get Paypal IPN messages everytime? - servlets

I have a Java servlet running on my notebook with Windows Vista, I set up a static IP, did port forwarding and registered for a free DDNS service, now my servlet is running, I gave the url to Paypal to send me IPN messages, I went on to it's sandbox site got to the test tools page, tried to send test messages by clicking the "Send IPN" button, most of the time it would fail, the error is : "IPN delivery failed. Unable to connect to the specified URL. Please verify the URL and try again."
But maybe 1 in 10 times, it might be successful and my servlet would get the message, and I looked at the messages I got, they are in correct format. So I called Paypal asking why, he said I shouldn't run the servlet on my notebook, in stead I should run it on the web server, but I told him my ISP doesn't support Java on their server, and since I did all the above steps, shouldn't it be the same to run the servlet on my notebook ? He said his test showed he couldn't get to my servlet, but I asked why maybe 1 in 10 times it could get through ? If there is something wrong with running it on my notebook, then 100% times it should fail, am I correct on this point ? But anyway he said that's all he could do, and I should troubleshoot it myself. The servlet looks like this :
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
public class PayPal_Servlet extends HttpServlet
{
static boolean Debug=true;
static String PayPal_Url="https://www.paypal.com/cgi-bin/webscr",Sandbox_Url="https://www.sandbox.paypal.com/cgi-bin/webscr",
Dir_License_Messages="C:/Dir_License_Messages/";
static TransparencyExample Transparency_Example;
static PayPal_Message_To_License_File_Worker PayPal_message_to_license_file_worker;
// Initializes the servlet.
public void init(ServletConfig config) throws ServletException
{
super.init(config);
if (!new File(Dir_License_Messages).exists()) new File(Dir_License_Messages).mkdirs();
System.gc();
}
/** Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* #param request servlet request
* #param response servlet response
*/
protected void processRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
{
// Read post from PayPal system and add 'cmd'
Enumeration en=request.getParameterNames();
String str="cmd=_notify-validate";
while (en.hasMoreElements())
{
String paramName=(String)en.nextElement();
String paramValue=request.getParameter(paramName);
str=str+"&"+paramName+"="+URLEncoder.encode(paramValue);
}
// Post back to PayPal system to validate
// NOTE: change http: to https: in the following URL to verify using SSL (for increased security).
// using HTTPS requires either Java 1.4 or greater, or Java Secure Socket Extension (JSSE) and configured for older versions.
URL u=new URL(Debug?Sandbox_Url:PayPal_Url);
URLConnection uc=u.openConnection();
uc.setDoOutput(true);
uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
PrintWriter pw=new PrintWriter(uc.getOutputStream());
pw.println(str);
pw.close();
BufferedReader in=new BufferedReader(new InputStreamReader(uc.getInputStream()));
String res=in.readLine();
in.close();
// Assign posted variables to local variables
String itemName=request.getParameter("item_name");
String itemNumber=request.getParameter("item_number");
String paymentStatus=request.getParameter("payment_status");
String paymentAmount=request.getParameter("mc_gross");
String paymentCurrency=request.getParameter("mc_currency");
String txnId=request.getParameter("txn_id");
String receiverEmail=request.getParameter("receiver_email");
String payerEmail=request.getParameter("payer_email");
if (res.equals("VERIFIED")) // Check notification validation
{
// check that paymentStatus=Completed
// check that txnId has not been previously processed
// check that receiverEmail is your Primary PayPal email
// check that paymentAmount/paymentCurrency are correct
// process payment
}
else if (res.equals("INVALID")) // Log for investigation
{
}
else // Log for error
{
}
// ===========================================================================
if (txnId!=null)
{
Write_File_Safe_Fast(Dir_License_Messages+txnId+".txt",new StringBuffer(str.replace("&","\n")),false);
}
// ===========================================================================
String Message_File_List[]=Tool_Lib.Get_File_List_From_Dir(Dir_License_Messages);
response.setContentType("text/html");
PrintWriter out=response.getWriter();
String title="Reading All Request Parameters",Name="",Value;
out.println("<Html><Head><Title>"+title+"</Title></Head>\n<Body Bgcolor=\"#FDF5E6\">\n<H1 Align=Center>"+title+"</H1>\n"+
"<Table Border=1 Align=Center>\n"+"<Tr Bgcolor=\"#FFAD00\"><Th>Parameter Name</Th><Th>Parameter Value(s) Messages = "+Message_File_List.length+"</Th></Tr>");
Enumeration paramNames=request.getParameterNames();
while(paramNames.hasMoreElements())
{
String paramName=(String)paramNames.nextElement();
out.print("<Tr><Td>"+paramName+"</Td><Td>");
String[] paramValues=request.getParameterValues(paramName);
if (paramValues.length == 1)
{
String paramValue=paramValues[0];
if (paramValue.length() == 0) out.print("<I>No Value</I>");
else
{
out.println(paramValue+"</Td></Tr>");
// Out("paramName = "+paramName+" paramValue = "+paramValue);
// if (paramName.startsWith("Name")) Name=paramValue;
// else if (paramName.startsWith("Value")) Write_File_Safe_Fast("C:/Dir_Data/"+Name,new StringBuffer(paramValue),false);
}
}
else
{
out.println("<Ul>");
for (int i=0;i<paramValues.length;i++) out.println("<Li>"+paramValues[i]);
out.println("</Ul></Td</Tr>");
}
}
out.println("</Table>\n</Body></Html>");
}
/** Handles the HTTP <code>GET</code> method.
* #param request servlet request
* #param response servlet response
*/
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { processRequest(request,response); }
/** Handles the HTTP <code>POST</code> method.
* #param request servlet request
* #param response servlet response
*/
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException { processRequest(request,response); }
// Returns a short description of the servlet.
public String getServletInfo() { return "Short description"; }
// Destroys the servlet.
public void destroy() { System.gc(); }
public static void Write_File_Safe_Fast(String File_Path,StringBuffer Str_Buf,boolean Append)
{
FileOutputStream fos=null;
BufferedOutputStream bos=null;
try
{
fos=new FileOutputStream(File_Path,Append);
bos=new BufferedOutputStream(fos);
for (int j=0;j<Str_Buf.length();j++) bos.write(Str_Buf.charAt(j));
}
catch (Exception e) { e.printStackTrace(); }
finally
{
try
{
if (bos!=null)
{
bos.close();
bos=null;
}
if (fos!=null)
{
fos.close();
fos=null;
}
}
catch (Exception ex) { ex.printStackTrace(); }
}
System.gc();
}
}
I use Netbean6.7 to develop the servlet, and the code was from Paypal's JSP sample code, what can I do to debug the problem ?

HI, try to use my library:
http://paypal-nvp.sourceforge.net/index.htm
I hope it will help you. If you have any questions, improvements you can contact me. You find my email in the comments of the source.

Related

SoapFault handling with Spring WS client - WebServiceGatewaySupport and WebServiceTemplate

I am trying to write a Spring WS client using WebServiceGatewaySupport. I managed to test the client for a successful request and response. Now I wanted to write test cases for soap faults.
public class MyClient extends WebServiceGatewaySupport {
public ServiceResponse method(ServiceRequest serviceRequest) {
return (ServiceResponse) getWebServiceTemplate().marshalSendAndReceive(serviceRequest);
}
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringBootTest(classes = SpringTestConfig.class)
#DirtiesContext
public class MyClientTest {
#Autowired
private MyClient myClient;
private MockWebServiceServer mockServer;
#Before
public void createServer() throws Exception {
mockServer = MockWebServiceServer.createServer(myClient);
}
}
My question is how do i stub the soap fault response in the mock server, so that my custom FaultMessageResolver will be able to unmarshall soap fault?
I tried couple of things below, but nothing worked.
// responsePayload being SoapFault wrapped in SoapEnvelope
mockServer.expect(payload(requestPayload))
.andRespond(withSoapEnvelope(responsePayload));
// tried to build error message
mockServer.expect(payload(requestPayload))
.andRespond(withError("soap fault string"));
// tried with Exception
mockServer.expect(payload(requestPayload))
.andRespond(withException(new RuntimeException));
Any help is appreciated. Thanks!
Follow Up:
Ok so, withSoapEnvelope(payload) I managed to get the controller to go to my custom MySoapFaultMessageResolver.
public class MyCustomSoapFaultMessageResolver implements FaultMessageResolver {
private Jaxb2Marshaller jaxb2Marshaller;
#Override
public void resolveFault(WebServiceMessage message) throws IOException {
if (message instanceof SoapMessage) {
SoapMessage soapMessage = (SoapMessage) message;
SoapFaultDetailElement soapFaultDetailElement = (SoapFaultDetailElement) soapMessage.getSoapBody()
.getFault()
.getFaultDetail()
.getDetailEntries()
.next();
Source source = soapFaultDetailElement.getSource();
jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath("com.company.project.schema");
Object object = jaxb2Marshaller.unmarshal(source);
if (object instanceof CustomerAlreadyExistsFault) {
throw new CustomerAlreadyExistsException(soapMessage);
}
}
}
}
But seriously!!! I had to unmarshall every message and check the instance of it. Being a client I should be thorough with all possible exceptions of the service here, and create custom runtime exceptions and throw it from the resolver. Still at the end, its been caught in WebServiceTemplate and re thrown as just a runtime exception.
You could try with something like this:
#Test
public void yourTestMethod() // with no throw here
{
Source requestPayload = new StringSource("<your request>");
String errorMessage = "Your error message from WS";
mockWebServiceServer
.expect(payload(requestPayload))
.andRespond(withError(errorMessage));
YourRequestClass request = new YourRequestClass();
// TODO: set request properties...
try {
yourClient.callMethod(request);
}
catch (Exception e) {
assertThat(e.getMessage()).isEqualTo(errorMessage);
}
mockWebServiceServer.verify();
}
In this part of code mockWebServiceServer represents the instance of MockWebServiceServer class.

Servlet Response wrapper to add getHeaderNames and getHeaders methods to Servet 2.4 spec container not working

Since Servlet 3.0, HttpServletResponse#getHeaderNames() and HttpServletResponse#getHeaders() has been available. However, I'm using an older spec, specifically Servlet 2.4.
Having looked at the resource, How can I get the HTTP status code out of a ServletResponse in a ServletFilter?, I got an idea of how to write a wrapper. If I understand it right, I have to use setHeader() to facilitate the creation of getHeaderNames() and getHeaders(). I think I have a solid footing on how to store the headers to simulate the usage of these missing methods.
The problem is the filter which leverages this wrapper does not seem to be calling setHeader() automatically. I don't get it. I presume sincegetStatus() is working properly, I'm expecting setHeader() to behave in the same fashion. Specifically, I'm looking to print out all the response headers, after calling chain.doFilter(). I'm not sure what I'm doing wrong here. Maybe there is something wrong with how I'm storing header name-value pairs.
I would appreciate any help. Thank you.
public class ServletResponseWrapper extends HttpServletResponseWrapper {
private int httpStatus = SC_OK;
private HashMap<String, String> hashMapHeaders = new HashMap<String, String>();
public ServletResponseWrapper(HttpServletResponse response) {
super(response);
}
#Override
public void sendError(int sc) throws IOException {
httpStatus = sc;
super.sendError(sc);
}
#Override
public void sendError(int sc, String msg) throws IOException {
httpStatus = sc;
super.sendError(sc, msg);
}
#Override
public void setStatus(int sc) {
httpStatus = sc;
super.setStatus(sc);
}
public int getStatus() {
return httpStatus;
}
#Override
public void sendRedirect(String location) throws IOException {
httpStatus = SC_MOVED_TEMPORARILY;
super.sendRedirect(location);
}
#Override
public void setHeader(String name, String value) {
hashMapHeaders.put(name, value);
super.setHeader(name, value);
}
public String getHeader(String name) {
return hashMapHeaders.get(name);
}
public Enumeration<String> getHeaderNames() {
Enumeration<String> enumerationHeaderNames = Collections.enumeration(hashMapHeaders.keySet());
return enumerationHeaderNames;
}
}
public class ServletResponseWrapperFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletResponseWrapper servletResponseWrapper = new ServletResponseWrapper( (HttpServletResponse) response );
chain.doFilter( request, servletResponseWrapper );
// Process response
// This works, even though I never explicitly call the setStatus() method
int status = response.getStatus();
// This returns NULL because no header values get set; I presume setHeader() gets called implicitly
Enumeration<String> headerNames = servletResponseWrapper.getHeaderNames();
}
public void init(FilterConfig config) throws ServletException {
//empty
}
public void destroy() {
// empty
}
}
web.xml file
<display-name>Tomcat App</display-name>
<filter>
<filter-name>ResponseHeadersFilter</filter-name>
<filter-class>com.company.filters.ResponseHeadersFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ResponseHeadersFilter</filter-name>
<url-pattern>/testfilter.jsp</url-pattern>
</filter-mapping>
I took the vendor's servlet out of the equation. The filter now fires on an empty JSP file. Tomcat is also hooked to a front-end web server, IIS. I disabled IIS. Now, I'm accessing the website directly over Tomcat, via port 8080. Despite all this, I dot see any response headers.
Using Fiddler, the response headers I see are few but existing, namely:
(Cache) Date
(Entity) Content- Length, Content-Type
(Miscellaneous) Server
And status response, i.e. HTTP/1.1 200 OK
I can get by without getting response headers in the filter. But the big question I have is this is a bug with Servlet version 2.4 or is there some kind of OS Server and/or Tomcat configuration change I need to enable? Unless there's some Tomcat configuration, I'm led to believe this is likely a bug. Perhaps a clean install using the default configuration of the Tomcat version I'm using, 5.5.28, would resolve the problem, but I cannot attempt that at this time.

Wicket and responding with "not HTML" to requests

I'm sure this has been answered somewhere else - but I don't know where
I need to respond to HTTP requests from a partner, in our wicket website. The partner expected the response body to say "OK" or anything else in the case of an error
Is there a "nice" way to do this? ... or am I going to be stuck adding a servlet to my (previously) pretty Wicket application?
You can use resources for that:
class OkResource implements IResource {
#Override
public void respond(Attributes attributes) {
WebResponse resp = (WebResponse) attributes.getResponse();
resp.setContentType("text/plain");
resp.write("OK");
}
}
And register it in your Application class
#Override
protected void init() {
super.init();
getSharedResources().add("confirm", new OkResource());
mountResource("confirm", new SharedResourceReference("confirm"));
}
so that it can be accessed through something like http://host/app/confirm.
Just observe that here you registering a single instance of the resource, so it must be thread-safe, since multiple requests can call it simultaneously.
[EDIT]
In Wicket 1.4:
class OkResource extends Resource {
#Override
public IResourceStream getResourceStream() {
return new StringResourceStream("ok", "text/plain");
}
}
#Override
protected void init() {
super.init();
getSharedResources().add("confirm", new OkResource());
mountSharedResource("confirm", "confirm");
}

Using Spring 3 #ExceptionHandler with commons FileUpload and SizeLimitExceededException/MaxUploadSizeExceededException

I am having trouble with catching and gracefully handling commons fileupload's FileUploadBase.SizeLimitExceededException or spring's MaxUploadSizeExceededException when uploading large files.
From what I can tell these exceptions are thrown during data binding, before the controller is actually reached, therefore resulting in a 500 and no calling of the exception handler method. Has anyone come across this before, and what is the best way for handling these exceptions properly?
thanks to thetoolman for this simple solution. I extended it a bit. I wanted to leave the file handling untouched and transport the Exception to the Controller.
package myCompany;
public class DropOversizeFilesMultipartResolver extends CommonsMultipartResolver {
/**
* Parse the given servlet request, resolving its multipart elements.
*
* Thanks Alexander Semenov # http://forum.springsource.org/showthread.php?62586
*
* #param request
* the request to parse
* #return the parsing result
*/
#Override
protected MultipartParsingResult parseRequest(final HttpServletRequest request) {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
List fileItems;
try {
fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
} catch (FileUploadBase.SizeLimitExceededException ex) {
request.setAttribute(EXCEPTION_KEY, ex);
fileItems = Collections.EMPTY_LIST;
} catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
return parseFileItems(fileItems, encoding);
}
}
and in the controller
#InitBinder("fileForm")
protected void initBinderDesignForm(WebDataBinder binder) {
binder.setValidator(new FileFormValidator());
}
#RequestMapping(value = "/my/mapping", method = RequestMethod.POST)
public ModelAndView acceptFile(HttpServletRequest request, Model model, FormData formData,
BindingResult result) {
Object exception = request.getAttribute(DropOversizeFilesMultipartResolver.EXCEPTION_KEY);
if (exception != null && FileUploadBase.SizeLimitExceededException.class.equals(exception.getClass())) {
result.rejectValue("file", "<your.message.key>");
LOGGER.error(exception);
}
the spring config remains the same. It would be really nice to have the exception transported to the validator, but I haven't figured out how to do this yet.
I know this is old, but I was looking for a solution to this as well and could not find anything. We are providing RESTful services using Spring and we are doing file upload and were not sure how to handle this. I came up with the following and hopefully it will be useful to someone:
All our exceptions are handled with annotations, so we have our error handler resolver set-up like this:
#Configuration
public class MyConfig{
#Bean
public AnnotationMethodHandlerExceptionResolver exceptionResolver(){
final AnnotationMethodHandlerExceptionResolver resolver = new AnnotationMethodHandlerExceptionResolver();
resolver.setMessageConverters(messageConverters());
resolver;
}
}
Then a common class that can handle the exception
public class MultipartExceptionHandler
{
#ExceptionHandler(MaxUploadSizeExceededException.class)
#ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
#ResponseBody
protected CustomError handleMaxUploadSizeExceededException(final HttpServletRequest request,
final HttpServletResponse response, final Throwable e)
throws IOException
{
logger.error(e);
CustomError c = new CustomErrorMaxFileSize("Max file size exceeded", MAX_FILE_SIZE);
return c;
}
#ExceptionHandler(MultipartException.class)
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
#ResponseBody
protected CustomError handleGenericMultipartException(final HttpServletRequest request,
final HttpServletResponse response, final Throwable e)
throws IOException
{
logger.error(e);
CustomError c = new CustomErrorGeneric("There was a problem with the upload");
return c;
}
}
Then we subclass the commons multipart resolver and implement the HandlerExceptionResolver interface
#Component(value="multipartResolver") // Spring expects this name
public class MyMultipartResolver extends CommonsMultipartResolver implements HandlerExceptionResolver
{
// This is the Spring bean that handles exceptions
// We defined this in the Java configuration file
#Resource(name = "exceptionResolver")
private AnnotationMethodHandlerExceptionResolver exceptionResolver;
// The multipart exception handler with the #ExceptionHandler annotation
private final MultipartExceptionHandler multipartExceptionHandler = new MultipartExceptionHandler();
// Spring will call this when there is an exception thrown from this
// multipart resolver
#Override
public ModelAndView resolveException(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handlerParam,
final Exception ex)
{
// Notice that we pass this.multipartExceptionHandler
// and not the method parameter 'handlerParam' into the
// exceptionResolver. We do this because the DispatcherServlet
// doDispatch() method calls checkMultipart() before determining
// the handler for the request. If doing the multipart check fails
// with a MultipartException, Spring will never have a reference
// to the handler and so 'handlerParam' will be null at this point.
return exceptionResolver.resolveException(request, response, this.multipartExceptionHandler, ex);
}
}
This seems to be a quite common problem. I've had similar problems and similar questions have been asked, see for example this question. I have yet to see a nice solution to the problem. You could use a vanilla servlet filter to handle these exceptions, but that will duplicate your error handling since you already have an ExceptionHandler.

Handle http post request

I have the following scenario to implement:
I have an ASP.NET Web site. On a click of a button in my site the user is redirected to a 3rd party site. When the user does some actions in this 3rd party site, the site starts sending http post requests to my site with a special message every 1 minute.
Now, the problem is that I should handle and process these requests, but I do not know how to do it. Please note that the requests that are sent from the 3rd party site DO NOT open my site by the http post requests. These requests are some kind of background requests, i.e. they do not open a page directly, so they should be handled using another approach.
I have the solution in Java. It is called Servlet. By the help of the servlet I can do the thing that I want in Java. However, I need the same functionality in ASP.NET? Does anybody have a solution for this?
Thanks a lot!
P.S. Just for your reference, here is the Java code for the servlet:
package payment;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import beans.action.PaymentBean;
public class EPayRequestCatcher extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet{
static final long serialVersionUID = 1L;
public EPayRequestCatcher() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException{
doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException{
String encoded = request.getParameter("encoded");
PaymentUtil util = new PaymentUtil();
if (encoded != null) {
String decoded = util.getDecodedB64Data(encoded);
int invStart = decoded.indexOf("=") + 1;
int invEnd = decoded.indexOf(":", invStart);
String invoice = decoded.substring(invStart, invEnd);
System.out.println("" + invoice);
String checksum = request.getParameter("checksum");
PaymentBean bean = new PaymentBean();
String responseStatus = bean.getEpayRequest(encoded, checksum);
if (!responseStatus.equals("")) {
String responseData = "INVOICE=" + invoice + ":STATUS=" + responseStatus + "\n";
System.out.println(responseData);
response.getWriter().append(responseData);
}
}
else {
return;
}
}
}
TheVisitor,
if I understood well, an external website will POST some data to your ASP.NET website; you'll (probably) define a page to receive that post and don't know how to handle it, right?
Well, you can try something like:
protected void Page_Load(object sender, EventArgs e)
{
string encoded = Request["encoded"];
string checksum = Request["checksum"];
// do stuff
Response.Write("some response");
}
This could be enough, depending on you requirements.
HTH

Resources