3

i am using this app to implement paypal into my application. However when i make the payment and everything, django keeps on complaining that i don't have a csrf_token when i already inserted it into my template form.

This is my template:

    <form method="post" action="/paypal/">
        {% csrf_token %}
        <p>
            To change your subscription, select a membership and the subscription rate:
        </p>
        <select name="membership_input" id="id_membership">
            <option>Silver</option>
            <option>Gold</option>
            <option>Platinum</option>
        </select>
        <select name="subscription_input" id="id_subscription" style = "float: center; margin-left: 30px;">
            <option>Monthly</option>
            <option>Quarterly</option>
            <option>Yearly</option>
        </select></br></br>
        {{ form }}
    </form>

And this is my view that handles the paypal elements:

def paypal(request):
    c = RequestContext(request,{})
    c.update(csrf(request))
    if request.method == 'POST':
    if 'membership_input' in request.POST:
        if 'subscription_input' in request.POST:
                membership = request.POST['membership_input']
            subscription = request.POST['subscription_input']
            if membership == "Gold":
                if subscription == "Quarterly":
                    price = "2400.00"
                if subscription == "Monthly":
                    price = "1000.00"
                if subscription == "Yearly":
                    price = "8000.00"
            elif membership == "Silver":
                if subscription == "Quarterly":
                    price = "1200.00"
                if subscription == "Monthly":
                    price = "500.00"
                if subscription == "Yearly":
                    price = "4000.00"
            elif membership == "Premium":
                if subscription == "Quarterly":
                    price = "4800.00"
                if subscription == "Monthly":
                    price = "2000.00"
                if subscription == "Yearly":
                    price = "16000.00"
            paypal_dict = {"business":settings.PAYPAL_RECEIVER_EMAIL,"amount": price ,"item_name": membership+" membership" ,"invoice": "09876543", "notify_url": "%s%s" % (settings.SITE_NAME, reverse('paypal-ipn')),"return_url": "http://rosebud.mosuma.net",}
                # Create the instance.
                form = PayPalPaymentsForm(initial=paypal_dict)
                context = {"form": form.sandbox()}
            c = RequestContext(request,{"form": form.sandbox()})
                return render_to_response("paypal.html", c)                 
    else:
        return HttpResponseRedirect("/")

if anybody needs my ipn view:

@require_POST
@csrf_exempt
def ipn(request, item_check_callable=None):
    """
    PayPal IPN endpoint (notify_url).
    Used by both PayPal Payments Pro and Payments Standard to confirm transactions.
    http://tinyurl.com/d9vu9d

    PayPal IPN Simulator:
    https://developer.paypal.com/cgi-bin/devscr?cmd=_ipn-link-session
    """
    flag = None
    ipn_obj = None

    # Clean up the data as PayPal sends some weird values such as "N/A"
    print "IPN"
    data = request.POST.copy()
    print "IPN"
    date_fields = ('time_created', 'payment_date', 'next_payment_date', 'subscr_date', 'subscr_effective')
    print "IPN"
    for date_field in date_fields:
    print "IPN"
        if data.get(date_field) == 'N/A':
        print "IPN" 
            del data[date_field]
    print "IPN"
    form = PayPalIPNForm(data)
    print "IPN"
    if form.is_valid():
        try:
            ipn_obj = form.save(commit=False)
        print "IPN"
        except Exception, e:
            flag = "Exception while processing. (%s)" % e
    else:
        flag = "Invalid form. (%s)" % form.errors

    if ipn_obj is None:
        ipn_obj = PayPalIPN()

    ipn_obj.initialize(request)
    if flag is not None:
        ipn_obj.set_flag(flag)
    else:
        # Secrets should only be used over SSL.
        if request.is_secure() and 'secret' in request.GET:
            ipn_obj.verify_secret(form, request.GET['secret'])
        else:
            ipn_obj.verify(item_check_callable)

    ipn_obj.save()
    return HttpResponse("OKAY")

I have already tried using requestContext as mentioned by django and inserted the csrf token but i don't know why it's not working.

Also if i were to enable recurring paypal subscriptions how do i do it?

Any help is appreciated.

Stanwin Siow
  • 437
  • 1
  • 8
  • 21
  • What URL is failing because of CSRF token - ipn or paypal? Can you see a block with hidden input in rendered form template? Does your browser have `csrf_token` cookie? Do you have `django.core.context_processors.csrf` in `TEMPLATE_CONTEXT_PROCESSORS` (actually it's the best way to do this)? If no, maybe problem is what you are overwriting variable `c` before rendering to CSRF token is lost. – ilvar Mar 26 '12 at 02:23
  • hi @ivar thanks for replying. my answer is as follows: There is no URL failing. it's just not hitting the return_url when i click return after making my purchase. and yes i have the django.core.context_processors.csrf. I have a strange feeling that it is my variable C. but let me try and debug more first. – Stanwin Siow Mar 26 '12 at 07:49
  • So your `paypal` view redirects you to Paypal, right? Makes more sense then. You should not be redirected to IPN after your transaction, it's been called by Paypal itself. So do you provide Paypal with your IPN url? Is it on localhost or real server in internet? Is it accessible for Paypal IPN robot? – ilvar Mar 27 '12 at 02:41
  • @ilvar yes it redirects me to Paypal, but according to one tutorial i read online, it says the ipn method is called once the button buy now is pressed? is that wrong or i'm understanding ipn wrongly. – Stanwin Siow Mar 27 '12 at 08:20
  • Yes, IPN URL is requested by paypal when transaction is complete. So you should be sure than your server is accessible by PayPal (i.e. it's not localhost or some VPN host). I see, you're sending `notify_url` to PayPal, please check if this is valid variable for PayPal API and that it's being actually sent to PayPal. Also, check it's value - it should be full URL including "http://" and domain name. – ilvar Mar 28 '12 at 02:08

1 Answers1

0

From Django docs, use RequestContext or "Manually import and use the processor to generate the CSRF token and add it to the template context." e.g.:

    from django.core.context_processors import csrf
    from django.shortcuts import render_to_response

    def my_view(request):
        c = {}
        c.update(csrf(request))
        # ... view code here
        return render_to_response("a_template.html", c)

And here's how you should be using render_to_response:

    return render_to_response('my_template.html', 
                               my_data_dictionary,
                               context_instance=RequestContext(request))

So, remove these lines from top:

    c = RequestContext(request,{})
    c.update(csrf(request))

And change bottom from:

    c = RequestContext(request,{"form": form.sandbox()})
    return render_to_response("paypal.html", c)  

to

    return render_to_response("paypal.html", 
              {"form": form.sandbox(), },
              context_instance=RequestContext(request))

This should fix the problem. Personally, I recommend just using render (from django.shortcuts import render), which takes care of the RequestContext for you.