Skip to content

Commit

Permalink
Merge pull request odero#12 from odero/develop
Browse files Browse the repository at this point in the history
Support Django1.8 and py3
  • Loading branch information
odero committed Nov 11, 2015
2 parents d460c5c + 345fc5d commit c259414
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ language: python

python:
- "2.7"
- "3.3"
- "3.4"

# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install: pip install -r requirements-test.txt
Expand Down
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
History
-------
0.3.5 (2015-11-11)
++++++++++++++++++
- Support Django 1.8
- Support Py33 and Py34
- Return proper IPN response

0.3.4 (2015-08-12)
++++++++++++++++++
- Restructure flow to better support IPN processing
Expand Down
2 changes: 1 addition & 1 deletion django_pesapal/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.3.4'
__version__ = '0.3.5'
1 change: 1 addition & 0 deletions django_pesapal/templates/django_pesapal/post_payment.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ <h3 class="panel-title">{% trans "Redirect Page" %}</h3>
{{ message }}
</blockquote>
<a href="{{ transaction_completed_url }}" class="btn btn-success pull-right">{% trans "Finish Ordering" %}</a>
<a href="{{ transaction_status_url }}" class="btn btn-info pull-left">{% trans "Check Status" %}</a>
</div>
</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions django_pesapal/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

from django.test import TestCase


class UserModelTestCase(TestCase):

pass
6 changes: 5 additions & 1 deletion django_pesapal/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-

from __future__ import absolute_import

from django.conf.urls import patterns, url

import views
from . import views

urlpatterns = patterns(
'',
Expand Down
38 changes: 28 additions & 10 deletions django_pesapal/views.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
# -*- coding: utf-8 -*-

from __future__ import absolute_import

import logging
import oauth2 as oauth
import requests

from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.db.models.loading import get_model
from django.http import HttpResponse
from django.http import HttpResponse, QueryDict
from django.shortcuts import get_object_or_404
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import View, RedirectView, TemplateView

from xml.etree import cElementTree as ET

import conf as settings
from . import conf as settings

import logging
import oauth2 as oauth
import requests
import urllib

DEFAULT_TYPE = "MERCHANT"
Transaction = get_model(settings.PESAPAL_TRANSACTION_MODEL)
Expand Down Expand Up @@ -148,12 +151,14 @@ def get_payment_status(self, **kwargs):
class PaymentResponseMixin(object):

def build_url_params(self):
url_params = '?' + urllib.urlencode(
url_params = QueryDict(mutable=True)
url_params.update(
{
'pesapal_merchant_reference': self.transaction.merchant_reference,
'pesapal_transaction_tracking_id': self.transaction.pesapal_transaction
}
)
url_params = '?' + url_params.urlencode()
return url_params

def get_payment_status_url(self):
Expand Down Expand Up @@ -196,6 +201,7 @@ def get_context_data(self, **kwargs):
ctx = super(TransactionCompletedView, self).get_context_data(**kwargs)

ctx['transaction_completed_url'] = self.get_order_completion_url()
ctx['transaction_status_url'] = self.get_payment_status_url()
ctx['payment_status'] = self.transaction.payment_status

if self.transaction.payment_status == Transaction.PENDING:
Expand Down Expand Up @@ -265,18 +271,30 @@ class TransactionStatusView(UpdatePaymentStatusMixin, RedirectView):
def get_redirect_url(self, *args, **kwargs):

params = self.get_params()

self.process_payment_status()

# redirect back to Transaction completed view
url = reverse('transaction_completed')
url += '?' + urllib.urlencode(params)

query_dict = QueryDict(mutable=True)
query_dict.update(params)
url += '?' + query_dict.urlencode()

return url


class IPNCallbackView(UpdatePaymentStatusMixin, PaymentResponseMixin, View):

def build_ipn_response(self):
params = self.get_params()
params['pesapal_notification_type'] = self.request.GET.get('pesapal_notification_type')

query_dict = QueryDict(mutable=True)
query_dict.update(params)
response = query_dict.urlencode()
return HttpResponse(response)

def get(self, request, *args, **kwargs):
self.process_payment_status()
return HttpResponse('OK')
response = self.build_ipn_response()
return response
55 changes: 35 additions & 20 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,55 @@
Usage
======

Take a look at the sandbox app for a quick overview on how to use `django-pesapal`.
Install django-pesapal::

To use django-pesapal in a project::
pip install django-pesapal

Then use it in a project::

import django_pesapal

#. Add `django_pesapal` to your `INSTALLED_APPS` setting like this::

INSTALLED_APPS = (
...
'django_pesapal',
)

#. Include the `django_pesapal` URLconf in your project urls.py like this::

url(r'^payments/', include('django_pesapal.urls')),

#. You can set your own return url by adding this to `settings.py`::

PESAPAL_TRANSACTION_DEFAULT_REDIRECT_URL = 'app_name:url_name' # this needs to be a reversible

#. Run `python manage.py migrate` to create the models.

#. Create a method that receives payment details and returns the pesapal iframe url::

from django.views.generic import TemplateView
from django_pesapal.views import PaymentRequestMixin
from django_pesapal.models import Transaction

class PaymentView(TemplateView, PaymentRequestMixin):
"""
This view returns secure payment form from pesapal
"""
template_name = 'testapp/payment.html'
class PaymentView(PaymentRequestMixin):

def get_context_data(self, **kwargs):
ctx = super(PaymentView, self).get_context_data(**kwargs)
def get_pesapal_payment_iframe(self):

'''
Authenticates with pesapal to get the payment iframe src
'''
order_info = {
'first_name': 'Some',
'last_name': 'User',
'amount': 100,
'description': 'Payment for X',
'reference': 2,
'email': 'pesapal@example.com'
'reference': 2, # some object id
'email': 'user@example.com',
}

# get_payment_url returns the URL of the secure payment form from pesapal
# You can use this URL in an iframe
ctx['pesapal_url'] = self.get_payment_url(**order_info)
return ctx

iframe_src_url = self.get_payment_url(**order_info)
return iframe_src_url

Once processing is complete the user will be redirected to the intermediate processing where
they can update check the status of the payment
#. Once payment has been processed, you will be redirected to an intermediate screen where the user can finish ordering. Clicking the "Finish Ordering" button will check the payment status to ensure that the payment was successful and then redirects the user to `PESAPAL_TRANSACTION_DEFAULT_REDIRECT_URL`.

**NOTE:** You can override the intermediate (`post_payment.html`) processing template if you
need to have a customized look.
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Django>=1.7,<=1.7.8
wheel==0.23.0
oauth2==1.5.211
requests==2.1
Django>=1.7
wheel==0.26.0
oauth2==1.9.0.post1
requests[security]>=2.8.1

# Custom requirements
git+https://github.com/dcramer/django-uuidfield.git@9bd27e9#egg=django-uuidfield
4 changes: 2 additions & 2 deletions runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@

def run_tests(*test_args):
if not test_args:
test_args = ['tests']
test_args = ['django_pesapal.tests']

# Run tests
test_runner = NoseTestSuiteRunner(verbosity=1)
test_runner = NoseTestSuiteRunner()

failures = test_runner.run_tests(test_args)

Expand Down
6 changes: 5 additions & 1 deletion sandbox/sandbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@
PESAPAL_OAUTH_CALLBACK_URL ='transaction_completed'
PESAPAL_OAUTH_SIGNATURE_METHOD ='SignatureMethod_HMAC_SHA1'
PESAPAL_TRANSACTION_DEFAULT_REDIRECT_URL = 'payment'
PESAPAL_DEMO = True
PESAPAL_OAUTH_CALLBACK_URL = 'transaction_completed'
PESAPAL_OAUTH_SIGNATURE_METHOD = 'SignatureMethod_HMAC_SHA1'
PESAPAL_TRANSACTION_DEFAULT_REDIRECT_URL = 'transaction_completed'
PESAPAL_TRANSACTION_FAILED_REDIRECT_URL = ''
PESAPAL_ITEM_DESCRIPTION = False
PESAPAL_TRANSACTION_MODEL = 'testapp.Transaction'
Expand All @@ -128,4 +132,4 @@
try:
from local_config import *
except ImportError:
pass
pass
10 changes: 6 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
packages=find_packages(exclude=['sandbox*']),
package_data={'django_pesapal': ['templates/django_pesapal/*.html']},
install_requires=[
'Django>=1.7,<=1.7.8',
'oauth2==1.5.211',
'Django>=1.7',
'oauth2==1.9.0.post1',
'django-uuidfield<=0.6.0',
'requests==2.1',
'requests[security]==2.8.1',
],
dependency_links=[
"https://github.com/dcramer/django-uuidfield/archive/9bd27e9.zip#egg=django-uuidfield-0.6.0",
Expand All @@ -55,7 +55,9 @@
'Natural Language :: English',
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)
)
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py27, py33
envlist = py27, py33, py34

[testenv]
setenv =
Expand Down

0 comments on commit c259414

Please sign in to comment.