Skip to content

Commit d310859

Browse files
committed
Implement netaxept gateway
1 parent f4f1a4d commit d310859

30 files changed

+1234
-66
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ test.db
1717
.idea
1818
*.iml
1919

20+
# Code
21+
.vscode/

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ This module provides implementations for the following payment-gateways:
5454

5555
[More Stripe information](docs/stripe.md)
5656

57+
### Netaxept
58+
Implemented features:
59+
- Authorization
60+
- Capture
61+
- Refund
62+
63+
[More Netaxept information](docs/netaxept.md)
5764

5865
## The example project
5966
The source distribution includes an example project that lets one exercise
@@ -75,7 +82,7 @@ Install the django-payment dependencies (the example project has identical depen
7582

7683
Then point your browser to:
7784

78-
http://127.0.0.1:8000/admin
85+
http://127.0.0.1:8000/admin/
7986

8087
Create a new payment (make sure the captured amount currency is the same as the total currency)
8188

@@ -94,7 +101,8 @@ To run unit tests:
94101
pip install pytest-django
95102
pytest
96103

97-
To lint, typecheck, test, and verify you didn't forget to create a migration:
104+
To lint, typecheck, test on all supported versions of python and django.
105+
Also to verify you didn't forget to create a migration:
98106

99107
pip install tox
100108
tox

devel-requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pytest-django
2+
flake8
3+
mypy
4+
python-language-server
5+

docs/design.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ is impossible to abstract over the myriad ways the different payment gateways do
2323

2424
Here is a diagram of how the different parts interact:
2525

26-
![payment with stripe sequence diagram](payment-with-stripe.png)
26+
![payment with stripe sequence diagram](stripe-authorization.png)
2727

2828

2929
Our changes

docs/netaxept.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Netaxept
2+
3+
## Configuration
4+
5+
In the PAYMENT_GATEWAYS setting, configure the netaxept connection params:
6+
7+
`merchant_id`, `secret`, `base_url`, and `after_terminal_url`.
8+
9+
The production base_url is:
10+
11+
`https://epayment.nets.eu/`
12+
13+
14+
## Design
15+
16+
Netaxept works by taking the user to a hosted page and then redirecting the user to the merchant in order to finish
17+
processing the payment.
18+
We chose not to provide such a view in the payment application (we do provide an example view in the example_project),
19+
This means a project that uses netaxept payment will have to implement its own after_terminal view.
20+
21+
- The first reason is that it's not possible to design a simple, generic response that we can show to users of the
22+
application (because we don't know anything about the application)
23+
- The second reason is that after a successful payment something more than just acknowledging the payment
24+
usually needs to happen in the application (for instance setting the status of an order, sending an email, etc).
25+
26+
It's not impossible to solve those two problems with configuration, application-provided functions, and signals
27+
but it doesn't seem like all this complexity is worth it, compared to reimplementing a simple, straightforward webhook.

example_project/settings.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ def abspath(*args):
5959

6060
ROOT_URLCONF = 'urls'
6161

62+
DATETIME_FORMAT = "Y-m-d @ H:i:s e"
63+
6264
TEMPLATES = [
6365
{
6466
'BACKEND': 'django.template.backends.django.DjangoTemplates',
@@ -80,14 +82,16 @@ def abspath(*args):
8082
DATETIME_FORMAT = 'Y-m-d @ H:i:s e'
8183

8284
# Enable specific currencies (djmoney)
83-
CURRENCIES = ['USD', 'EUR', 'JPY', 'GBP', 'CAD', 'CHF']
85+
CURRENCIES = ['USD', 'EUR', 'JPY', 'GBP', 'CAD', 'CHF', 'NOK']
8486

8587
DUMMY = 'dummy'
8688
STRIPE = 'stripe'
89+
NETAXEPT = 'netaxept'
8790

8891
CHECKOUT_PAYMENT_GATEWAYS = {
8992
DUMMY: 'Dummy gateway',
9093
STRIPE: 'Stripe',
94+
NETAXEPT: 'Netaxept',
9195
}
9296

9397
PAYMENT_GATEWAYS = {
@@ -117,4 +121,17 @@ def abspath(*args):
117121
},
118122
},
119123
},
124+
NETAXEPT: {
125+
'module': 'payment.gateways.netaxept',
126+
'config': {
127+
'auto_capture': True,
128+
'template_path': 'payment/netaxept.html',
129+
'connection_params': {
130+
'base_url': os.environ.get('NETAXEPT_BASE_URL') or 'https://test.epayment.nets.eu',
131+
'after_terminal_url': 'http://localhost:8000/example/netaxept/after_terminal',
132+
'merchant_id': os.environ.get('NETAXEPT_MERCHANT_ID'),
133+
'secret': os.environ.get('NETAXEPT_SECRET'),
134+
}
135+
}
136+
},
120137
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<html>
2+
<body>
3+
4+
<p>Annulled: {{ query_response.annulled }}</p>
5+
6+
<p>Authorized: {{ query_response.authorized }}</p>
7+
8+
<p>Status code: {{ query_response.raw_response.status_code }}</p>
9+
10+
<p>Raw response:
11+
<pre> {{ query_response.raw_response.text }} </pre>
12+
</p>
13+
14+
</body>
15+
</html>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<html>
2+
3+
<body>
4+
5+
<H3>Payments</H3>
6+
7+
{% for payment in payments %}
8+
<div><a href="{%url 'view_payment' payment.id %}">Payment {{payment.id}} - {{payment.total}} ({{payment.gateway}}) </a></div>
9+
{% endfor %}
10+
11+
</body>
12+
</html>

example_project/templates/operation_list.html renamed to example_project/templates/view_payment.html

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,20 @@ <H3>Payment</H3>
1212
<li>captured amount: {{ payment.captured_amount }}</li>
1313
</ul>
1414

15-
<a href="{%url 'admin:payment_payment_change' payment.id %}">See payment in admin </a>
1615

1716
<H3>Operations</H3>
1817
<ul>
1918
{% if payment.gateway == 'stripe' %}
2019
<li><a href="{% url 'stripe_elements_token' payment.id %}">Authorize - Elements token</a></li>
2120
<li><a href="{% url 'stripe_checkout' payment.id %}">Authorize - Checkout</a></li>
2221
<li><a href="{% url 'stripe_payment_intents_manual_flow' payment.id %}">Authorize - Payment intents manual flow</a>
22+
{% elif payment.gateway == 'netaxept' %}
23+
<li><a href="{% url 'netaxept_register_and_goto_terminal' payment.id %}">Register and Goto Terminal</a></li>
24+
{% if payment.token %}
25+
<li><a href="{% url 'netaxept_query' payment.token %}">Query</a></li>
26+
{% endif %}
2327
{% endif %}
24-
25-
<li><a href="{% url 'capture' payment.id %}">Capture</a></li>
28+
<li><a href="{%url 'admin:payment_payment_change' payment.id %}">See payment in admin</a></li>
2629
</ul>
2730

2831
</body>

example_project/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
from django.urls import path, include
33

44
import views
5+
from views import netaxept
56
from views import stripe
67

78
example_urlpatterns = [
9+
path('', views.list_payments, name='list_payments'),
810
path('<payment_id>', views.view_payment, name='view_payment'),
9-
path('<payment_id>/capture', views.capture, name='capture'),
1011
path('stripe/', include(stripe.urls)),
12+
path('netaxept/', include(netaxept.urls)),
1113
]
1214

1315
urlpatterns = [

0 commit comments

Comments
 (0)