Search code examples
pythondjangourlurlconf

how to match an url with django urlconf?


Im implementing a payment module called mercadopago (like paypal) and I need to handle a http request that is send to my site when someone make a payment(IPN) with information in in an url of this type:

POST /notifications?topic=payment&id=identificador-de-notificacion-de-pago

(mercadopago send a POST request to my site every time a payment impact)

but i cant make it match with the django url system. i tried the following url:

    url(r'^notifications$', 'views.notifications', name='notifications'),

I tried with diferent combination and consulted the apache log file and threw me error 500

The view that handdle the url is the following:

    @csrf_exempt
    def IpnProxy(request, **kwargs):
        mp = mercadopago.MP("*********", "*********") 
        paymentInfo = mp.get_payment_info(kwargs["id"])
        if paymentInfo["status"] == 200:
            return paymentInfo["response"]
        else:
            return None

I dont know if have to configure singals or something else.

Maybe im getting it wrong but mercadopago make the post request to my server, I cant change that. Here is their documentation http://developers.mercadopago.com/documentation/instant-payment-notifications?lang=en_US And here is their example project in python: https://github.com/mercadopago/sdk-python/blob/master/examples/instant-payment-notifications/receive-ipn.py


Solution

  • You are encoding the parameters incorrectly for a POST in Django. POST requests get their parameters encoded in the request body. Please take a look at the Request and response objects documentation for Django. If you really want to use the URL you provided you will need to use a GET instead of a POST.

    --- EDIT ---

    Give the following a try: In your urls.py file after you've imported notification.

    url(r'^notification$', notification, name='notification')
    

    In your settings.py:

    APPEND_SLASH=False
    

    You will almost certainly need to also turn of CSRF protection since you won't have a CSRF cookie.

    You will be able to retrieve the parameters as follows:

    def notification(request, **kwargs):
        body = "topic = '{0}'\nid = '{1}'\n".format(request.GET.get('topic'), request.GET.get('id'))
        response = HttpResponse(body, content_type="text/plain")
        return response
    

    Testing then gives us:

    hackworth:~$ curl -X POST "http://127.0.0.1:8000/notification?topic=payment&id=identificador-de-notificacion-de-pago"
    topic = 'payment'
    id = 'identificador-de-notificacion-de-pago'
    

    All of the above is a bad idea since POST requests generally have a body, and Django really does not expect query parameters on a POST url. Also, there is now a security vulnerability since CSRF protection had to be turned off to make this work.

    The way the documentation reads, you will receive a URL from mercadopago that you retrive with a get request. It is not clear that that they will send you a POST request with query parameters.