0

I can't seem to get my app to accept POST requests from a different domain. I'm trying to make an PayPal IPN handler in my app.

When a user clicks the "Subscribe" button on my page, PayPal sends an IPN (a POST), to my IPN handler.

I can see in my AppEngine logs that a POST request is received, but it is empty (e.g. no arguments, my logging.debug messages aren't showing up in the logs, etc.)

So I test my handler by making a POST to it within my app, and the handler works as expected.

I'm assuming it's a security feature to not accept POSTs from outside sources? If so, how do I make my app accept POSTs from PayPal?

Here's what my handler looks like at the moment (it's just for testing):

class BaseHandler(tornadotoad.mixin.RequestHandler, tornado.web.RequestHandler):
    # ...

class IPNHandler(BaseHandler):
    def post(self):
        if is_ajax(self.request):
            logging.info('AJAX')
        logging.info(self.request.arguments)
        self.write("This is the IPN Handler\n'")
        self.write(self.request.arguments)
        return

Thanks in advance.

P.S. I'm using PayPal's Sandbox Test Tool to send the IPN

john2x
  • 22,546
  • 16
  • 57
  • 95
  • 1
    There's no security issue that I know of that would prevent this. Are you sure the request from PayPal actually contains the data you want? – Travis Webb Apr 27 '12 at 04:31
  • No, there's no 'security feature'. What is `is_ajax`? What status code does your handler return? Are you sure you're using the right URL and your handler is being called at all? Can you show us a simple demo app that exhibits the problem, and a command line (curl/wget) that demonstrates it? – Nick Johnson Apr 27 '12 at 04:32
  • How are you making sure that post is coming from PayPal. Also, could you tell which integration model with PayPay you are trying? – Karthik Ananth Apr 27 '12 at 04:53
  • @NickJohnson is_ajax is just a function which checks the request's headers if it contains 'XMLHttpRequest'. I *think* my handler is being called, since I get this `2012-04-27 11:13:50.294 /ipn 302 23ms 0kb 173.0.82.126 - - [26/Apr/2012:20:13:50 -0700] "POST /ipn HTTP/1.1" 302 0 - - "myapp.appspot.com" ms=23 cpu_ms=0 api_cpu_ms=0 cpm_usd=0.000108 ` in my logs when sending the IPN. – john2x Apr 27 '12 at 06:30
  • @KarthikAnanth I'm using the [Website Payments Standard](https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_html_wp_standard_overview) methods. – john2x Apr 27 '12 at 06:34
  • @john2x The header line indicates you're sending a 302 in response to the request. Why that is depends on your code - perhaps you're requiring login? – Nick Johnson Apr 27 '12 at 10:39

3 Answers3

2

I found my mistake. I put the url for the handler together with the other urls, which has login: required in app.yaml.

I've fixed this and now PayPal's IPN is getting through.

Thanks everyone!

john2x
  • 22,546
  • 16
  • 57
  • 95
1

A few hunches here.

  1. Maybe "/ipn" is not being routed to IPNHandler. Perhaps another deprecated handler?

  2. Maybe the app version you are looking at in your logs is not the same as the one you have. Perhaps you can deploy a new version of your code and test against the new one.

  3. Maybe the POST request Paypal is sending you has no arguments.

P.S. More info on how you are performing tests from Paypal's end, showing other relevant parts of your code, and any other relevant info could help. :)

Albert
  • 3,611
  • 3
  • 28
  • 52
  • I'm using PayPal's [IPN test tool](https://developer.paypal.com/devscr?cmd=_tools-session) to simulate sending an IPN. (You'll need to register a dummy account at http://developer.paypal.com). Once in the tool, enter `http://wmp-ipn-handler-test.appspot.com/ipn` in the **IPN Handler URL** and click "Send". To test if `/ipn` is working, go [here](http://wmp-ipn-handler-test.appspot.com/subscribe) and there will be a form which POSTs to /ipn as well. – john2x Apr 27 '12 at 07:29
  • Your link to your app subscription gives me a "Server Error". – Albert Apr 27 '12 at 07:45
  • I just tested your /ipn by sending it post requests. It seems to work fine. There is NO "security feature" that is stopping requests from Paypal. Look at the way you are using Paypal's IPN Simulator. There might be something amiss there. – Albert Apr 27 '12 at 07:48
0

Just a hunch, and I might be way out of my league here but for tornado I don't seem to be able to find either a method or an attribute of that name in the docs...

At least for webapp I believe arguments is an instance method:

 logging.info(self.request.arguments())

see the docs here.

Speediro
  • 543
  • 2
  • 9
  • I'm using Tornado on GAE, where `arguments` is a dict. – john2x Apr 27 '12 at 06:36
  • Excuse the misdirection. I just glanced over my code (webapp-based) which does exactly what you want to do and I do get all my arguments back (using the IPN simulator...). So in response to your question whether it is a security issue; that is a definite no. – Speediro Apr 27 '12 at 07:17