Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

added ogone integration #31

Closed
wants to merge 33 commits into
from
Commits
Jump to file or symbol
Failed to load files and symbols.
+315 −2
Split
@@ -0,0 +1,38 @@
+from django import forms
+
+
+class OgonePaymentsForm(forms.Form):
+ # Required
+ PSPID = forms.CharField(widget=forms.HiddenInput, required=True)
+ ORDERID = forms.CharField(widget=forms.HiddenInput, required=True) # REF
+ AMOUNT = forms.CharField(widget=forms.HiddenInput, required=True) # * 100
+ CURRENCY = forms.CharField(widget=forms.HiddenInput, required=True)
+ LANGUAGE = forms.CharField(widget=forms.HiddenInput, required=True) # client language
+ # Layout
+ TITLE = forms.CharField(widget=forms.HiddenInput, required=False)
+ LOGO = forms.CharField(widget=forms.HiddenInput, required=False)
+ # Post-payment redirection
+ ACCEPTURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ DECLINEURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ EXCEPTIONURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ CANCELURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ BACKURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ # Miscellanous
+ HOMEURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ CATALOGURL = forms.CharField(widget=forms.HiddenInput, required=False)
+ CN = forms.CharField(widget=forms.HiddenInput, required=False)
+ EMAIL = forms.CharField(widget=forms.HiddenInput, required=False)
+ PM = forms.CharField(widget=forms.HiddenInput, required=False)
+ BRAND = forms.CharField(widget=forms.HiddenInput, required=False)
+ OWNERZIP = forms.CharField(widget=forms.HiddenInput, required=False)
+ OWNERADDRESS = forms.CharField(widget=forms.HiddenInput, required=False)
+ OWNERADDRESS2 = forms.CharField(widget=forms.HiddenInput, required=False)
+ SHASIGN = forms.CharField(widget=forms.HiddenInput, required=False)
+ ALIAS = forms.CharField(widget=forms.HiddenInput, required=False)
+ ALIASUSAGE = forms.CharField(widget=forms.HiddenInput, required=False)
+ ALIASOPERATION = forms.CharField(widget=forms.HiddenInput, required=False)
+ COM = forms.CharField(widget=forms.HiddenInput, required=False)
+ COMPLUS = forms.CharField(widget=forms.HiddenInput, required=False)
+ PARAMPLUS = forms.CharField(widget=forms.HiddenInput, required=False)
+ USERID = forms.CharField(widget=forms.HiddenInput, required=False)
+ CREDITCODE = forms.CharField(widget=forms.HiddenInput, required=False)
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 *-*
+from billing import Integration, IntegrationNotConfigured
+from django.conf import settings
+from django_ogone.ogone import Ogone
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.conf.urls import patterns, url
+from django_ogone.status_codes import get_status_category, get_status_description
+from django_ogone.signals import ogone_payment_accepted, ogone_payment_failed, ogone_payment_cancelled
+from django.http import HttpResponse
+from billing.utils.utilities import Bunch
+from billing.forms.ogone_payments_forms import OgonePaymentsForm
+
+
+class OgonePaymentsIntegration(Integration):
+ display_name = "Ogone Payments Integration"
+ template = "billing/ogone_payments.html"
+
+ def __init__(self, options=None):
+ if not options:
+ options = {}
+ super(OgonePaymentsIntegration, self).__init__(options=options)
+ merchant_settings = getattr(settings, "MERCHANT_SETTINGS")
+ if not merchant_settings or not merchant_settings.get("ogone_payments"):
+ raise IntegrationNotConfigured("The '%s' integration is not correctly "
+ "configured." % self.display_name)
+ bunch = Bunch()
+ bunch.update(merchant_settings["ogone_payments"])
+ self.settings = bunch
+
+ @property
+ def service_url(self):
+ return Ogone.get_action(production=not settings.MERCHANT_TEST_MODE)
+
+ def ogone_notify_handler(self, request):
+ response = Ogone(request=request, settings=self.settings)
+ if response.is_valid():
+ fpath = request.get_full_path()
+ query_string = fpath.split("?", 1)[1]
+ transaction_feedback = query_string.split('&')
+ result = {}
+ for item in transaction_feedback:
+ k, v = item.split("=")
+ result[k] = v
+
+ # Default transaction feedback parameters
+ status = result.get('STATUS', False)
+ orderid = result.get('orderID', '')
+ payid = result.get('PAYID', '')
+ ncerror = result.get('NCERROR', '')
+
+ amount = result.get('amount', '')
+ currency = result.get('currency', '')
+
+ if status and get_status_category(int(status)) == 'success':
+ ogone_payment_accepted.send(sender=self, order_id=orderid, \
+ amount=amount, currency=currency, pay_id=payid, status=status, ncerror=ncerror)
+ return self.ogone_success_handler(request, response=result, description=get_status_description(int(status)))
+
+ if status and get_status_category(int(status)) == 'cancel':
+ ogone_payment_cancelled.send(sender=self, order_id=orderid, \
+ amount=amount, currency=currency, pay_id=payid, status=status, ncerror=ncerror)
+ return self.ogone_cancel_handler(request, response=result, description=get_status_description(int(status)))
+
+ if status and get_status_category(int(status)) == 'decline' or 'exception':
+ ogone_payment_failed.send(sender=self, order_id=orderid, \
+ amount=amount, currency=currency, pay_id=payid, status=status, ncerror=ncerror)
+ return self.ogone_failure_handler(request, response=result, description=get_status_description(int(status)))
+ else:
+ return HttpResponse('signature validation failed!')
+
+ def ogone_success_handler(self, request, response=None, description=''):
+ return render_to_response("billing/ogone_success.html",
+ {"response": response, "message": description},
+ context_instance=RequestContext(request))
+
+ def ogone_failure_handler(self, request, response=None, description=''):
+ return render_to_response("billing/ogone_failure.html",
+ {"response": response, "message": description},
+ context_instance=RequestContext(request))
+
+ def ogone_cancel_handler(self, request, response=None, description=''):
+ return render_to_response("billing/ogone_cancel.html",
+ {"response": response, "message": description},
+ context_instance=RequestContext(request))
+
+ def get_urls(self):
+ urlpatterns = patterns('',
+ url('^ogone_notify_handler/$', self.ogone_notify_handler, name="ogone_notify_handler"),)
+ return urlpatterns
+
+ def add_fields(self, params):
+ for (key, val) in params.iteritems():
+ if isinstance(val, dict):
+ new_params = {}
+ for k in val:
+ new_params["%s__%s" % (key, k)] = val[k]
+ self.add_fields(new_params)
+ else:
+ self.add_field(key, val)
+
+ def form_class(self):
+ return OgonePaymentsForm
+
+ def generate_form(self):
+ # form = self.form_class()(initial=self.fields)
+ # The above form has SHASIGN field which needs to be calculated.
+ # It's easier to use the Ogone module's get_form method which takes care of that.
+ form = Ogone.get_form(self.fields, settings=self.settings)
+ return form
@@ -0,0 +1,4 @@
+<form method="post" action="{{ integration.service_url }}">
+ {{ integration.generate_form.as_p }}
+ <input type="submit" value="checkout!">
+</form>
@@ -35,6 +35,7 @@
from paylane_tests import *
from chargebee_tests import *
from bitcoin_tests import *
+from ogone_payments_tests import *
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,50 @@
+from django.test import TestCase
+from billing import get_integration
+
+
+class OgonePaymentsTestCase(TestCase):
+ def setUp(self):
+ self.op = get_integration("ogone_payments")
+ self.data = {
+ 'orderID': 21,
+ 'ownerstate': u'',
+ 'cn': u'Venkata Ramana',
+ 'language': 'en_US',
+ 'ownertown': u'Hyderabad',
+ 'ownercty': u'IN',
+ 'exceptionurl': u'http://127.0.0.1:8000/offsite/ogone/failure/',
+ 'ownerzip': u'Postcode',
+ 'catalogurl': u'http://127.0.0.1:8000/',
+ 'currency': u'EUR',
+ 'amount': u'579',
+ 'declineurl': u'http://127.0.0.1:8000/offsite/ogone/failure/',
+ 'homeurl': u'http://127.0.0.1:8000/',
+ 'cancelurl': u'http://127.0.0.1:8000/offsite/ogone/failure/',
+ 'accepturl': u'http://127.0.0.1:8000/offsite/ogone/success/',
+ 'owneraddress': u'Near Madapur PS',
+ 'com': u'Order #21: Venkata Ramana',
+ 'email': u'ramana@agiliq.com'
+ }
+ self.op.add_fields(self.data)
+
+ def testFormFields(self):
+ self.assertEquals(self.op.fields, {
+ 'orderID': 21,
+ 'ownerstate': u'',
+ 'cn': u'Venkata Ramana',
+ 'language': 'en_US',
+ 'ownertown': u'Hyderabad',
+ 'ownercty': u'IN',
+ 'exceptionurl': u'http://127.0.0.1:8000/offsite/ogone/failure/',
+ 'ownerzip': u'Postcode',
+ 'catalogurl': u'http://127.0.0.1:8000/',
+ 'currency': u'EUR',
+ 'amount': u'579',
+ 'declineurl': u'http://127.0.0.1:8000/offsite/ogone/failure/',
+ 'homeurl': u'http://127.0.0.1:8000/',
+ 'cancelurl': u'http://127.0.0.1:8000/offsite/ogone/failure/',
+ 'accepturl': u'http://127.0.0.1:8000/offsite/ogone/success/',
+ 'owneraddress': u'Near Madapur PS',
+ 'com': u'Order #21: Venkata Ramana',
+ 'email': u'ramana@agiliq.com'
+ })
View
@@ -0,0 +1,10 @@
+import random, string
+
+class Bunch(dict):
+ def __init__(self, **kw):
+ dict.__init__(self, kw)
+ self.__dict__ = self
+
+def randomword(word_len):
+ rstr = string.lowercase + string.digits
+ return ''.join(random.sample(rstr, word_len))
@@ -51,6 +51,7 @@
<li><a href="{% url 'app.views.offsite_braintree' %}">Braintree Payments (TR)</a></li>
<li><a href="{% url 'app.views.offsite_stripe' %}">Stripe</a></li>
<li><a href="{% url 'app.views.offsite_eway' %}">eWAY</a></li>
+ <li><a href="{% url 'app.views.offsite_ogone' %}">Ogone</a></li>
</ul>
</li>
<li class="dropdown">
@@ -0,0 +1,15 @@
+{% extends 'app/base.html' %}
+{% load render_integration from billing_tags %}
+
+{% block content %}
+Required Parameters from the view
+ <ul>
+ <li> language </li>
+ <li> order id </li>
+ <li> amount </li>
+ <li> currency </li>
+ </ul>
+ You are going to be charged Rs 100 under <a href="http://ogone.com/">Ogone Offsite Payment</a>.
+ <hr />
+{% render_integration og_obj %}
+{% endblock %}
@@ -0,0 +1,5 @@
+{% extends 'app/base.html' %}
+
+{% block content %}
+<p>Payment failed..</p>
+{% endblock %}
@@ -0,0 +1,9 @@
+{% extends "app/base.html" %}
+
+{% block content %}
+The transaction was cancelled!
+<hr />
+Status: {{ message }}
+<hr />
+PAY ID: {{ response.PAYID }}
+{% endblock %}
@@ -0,0 +1,9 @@
+{% extends "app/base.html" %}
+
+{% block content %}
+The transaction failed!
+<hr />
+Status: {{ message }}
+<hr />
+PAY ID: {{ response.PAYID }}
+{% endblock %}
@@ -0,0 +1,9 @@
+{% extends "app/base.html" %}
+
+{% block content %}
+The transaction was successful!
+<hr />
+Status: {{ message }}
+<hr />
+PAY ID: {{ response.PAYID }}
+{% endblock %}
View
@@ -11,6 +11,7 @@
world_pay_obj = get_integration("world_pay")
braintree_obj = get_integration("braintree_payments")
stripe_obj = get_integration("stripe_example")
+ogone_obj = get_integration("ogone_payments")
urlpatterns = patterns('app.views',
url(r'^$', 'index', name='app_index'),
@@ -39,6 +40,7 @@
# redirect handler
url(r'offsite/eway/done/$', 'offsite_eway_done'),
+ url(r'offsite/ogone/$', 'offsite_ogone', name='app_offsite_ogone'),
)
urlpatterns += patterns('',
@@ -60,6 +62,7 @@
urlpatterns += patterns('',
(r'^braintree/', include(braintree_obj.urls)),
)
+
urlpatterns += patterns('',
(r'^stripe/', include(stripe_obj.urls)),
)
@@ -78,3 +81,7 @@
url(r'we_pay_redirect/$', 'we_pay_redirect', name="app_we_pay_redirect"),
url(r'^we_pay_ipn/$', 'we_pay_ipn', name="app_we_pay_ipn"),
)
+
+urlpatterns += patterns('',
+ (r'^ogone/', include(ogone_obj.urls)),
+)
View
@@ -3,15 +3,15 @@
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from django.template import RequestContext
-from django.http import HttpResponse, HttpResponseRedirect
+from django.http import HttpResponseRedirect # , HttpResponse
from billing import CreditCard, get_gateway, get_integration
from billing.gateway import CardNotSupported
from app.forms import CreditCardForm
from app.urls import (authorize_net_obj, google_checkout_obj, world_pay_obj, pay_pal_obj,
amazon_fps_obj, fps_recur_obj, braintree_obj,
- stripe_obj)
+ stripe_obj, ogone_obj)
from django.conf import settings
from django.contrib.sites.models import RequestSite
from billing.utils.paylane import PaylanePaymentCustomer, \
@@ -435,3 +435,37 @@ def bitcoin_done(request):
"address": address,
"result": result
})
+
+
+def offsite_ogone(request):
+ from billing.utils.utilities import randomword
+ fields = {
+ # Required
+ # orderID needs to be unique per transaction.
+ 'orderID': randomword(6),
+ 'currency': u'INR',
+ 'amount': u'10000', # 100.00
+ 'language': 'en_US',
+
+ # Optional; Can be configured in Ogone Account:
+
+ 'exceptionurl': u'%s%s' % ('http://127.0.0.1:8000', reverse("ogone_notify_handler")),
+ 'declineurl': u'%s%s' % ('http://127.0.0.1:8000', reverse("ogone_notify_handler")),
+ 'cancelurl': u'%s%s' % ('http://127.0.0.1:8000', reverse("ogone_notify_handler")),
+ 'accepturl': u'%s%s' % ('http://127.0.0.1:8000', reverse("ogone_notify_handler")),
+
+ # Optional fields which can be used for billing:
+
+ # 'homeurl': u'http://127.0.0.1:8000/',
+ # 'catalogurl': u'http://127.0.0.1:8000/',
+ # 'ownerstate': u'',
+ # 'cn': u'Venkata Ramana',
+ # 'ownertown': u'Hyderabad',
+ # 'ownercty': u'IN',
+ # 'ownerzip': u'Postcode',
+ # 'owneraddress': u'Near Madapur PS',
+ # 'com': u'Order #21: Venkata Ramana',
+ # 'email': u'ramana@agiliq.com'
+ }
+ ogone_obj.add_fields(fields)
+ return render(request, "app/ogone.html", {"og_obj": ogone_obj})
View
@@ -6,6 +6,7 @@ django-paypal==0.1.2
boto==2.8.0
braintree==2.20.0
wepay==0.1.5
+-e git://github.com/arjunc77/django-ogone.git#egg=django-ogone
suds==0.4
requests==1.2.0
django-crispy-forms==1.2.5
@@ -100,6 +100,15 @@ MERCHANT_SETTINGS = {
"ACCOUNT": "",
"MINCONF": 1,
},
+
+ "ogone_payments": {
+ "SHA_PRE_SECRET": 'test1234',
+ "SHA_POST_SECRET": 'test12345',
+ "HASH_METHOD": 'sha512',
+ "PSPID": 'mypspid',
+ "OGONE_TEST_URL": 'https://secure.ogone.com/ncol/test/orderstandard.asp',
+ "OGONE_PROD_URL": 'https://secure.ogone.com/ncol/prod/orderstandard.asp'
+ }
}
# Special case for PayPal because we rely on django-paypal
View
@@ -0,0 +1 @@
+-e git://github.com/arjunc77/django-ogone.git#egg=django-ogone