Skip to content

Commit

Permalink
add option to auto verify payments on IPN call
Browse files Browse the repository at this point in the history
  • Loading branch information
lovvskillz committed Nov 21, 2019
1 parent e1dc72f commit 3042a69
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 15 deletions.
7 changes: 6 additions & 1 deletion CHANGES.md
@@ -1,7 +1,12 @@
# Changes

## 2019-11-21 1.5.0
- add optional `GLOBEE_AUTO_VERIFY` to settings.py
- `True` - fetches the payment information directly from GloBee after the IPN view was called
- `False` - saves the IPN response in the database without further validation checks

## 2019-04-01 1.4.0
- set `unique=True` for `payment_id` and `custom_payment_id`
- set `unique=True` for `payment_id` and `custom_payment_id`
- set the default payment status to `unpaid`
- add optional `GLOBEE_PARANOID_MODE` setting
- `True` - IPN view will always respond with status code `200`
Expand Down
9 changes: 8 additions & 1 deletion README.md
Expand Up @@ -28,7 +28,14 @@ You can find the GloBee API docs [here](https://globee.com/docs/payment-api/v1).
```python
GLOBEE_AUTH_KEY = "YOUR GLOBEE X-AUTH-KEY"
GLOBEE_TESTNET = True # set this to False in production mode
GLOBEE_PARANOID_MODE = False # optional (default is False). True - IPN view will always respond with status code "200"

# False: IPN view will respond with status code "400" if an "KeyError", "ValueError" or "ValidationError" occurs
# True: IPN view will always respond with status code "200"
GLOBEE_PARANOID_MODE = False # optional (default: False)

# False: saves the IPN response in the database without further verify checks. see docs on how to verify the payment yourself.
# True: fetches the payment information directly from GloBee after the IPN view was called
GLOBEE_AUTO_VERIFY = False # optional (default: False)
```


Expand Down
9 changes: 6 additions & 3 deletions docs/README.md
Expand Up @@ -10,6 +10,7 @@
* [Get payment details for payment request and currency](#get-payment-currency-details)
* [Get payment methods](#get-payment-methods)
* [Get IPN signal](#get-globee-ipn-signal)
* [Verfify IPN signal](#verify-the-incoming-payment-data)

### ping
```python
Expand Down Expand Up @@ -49,7 +50,7 @@ def my_payment_view(request):

# validate required fields for globee payments
try:
payment.check_required_fields():
payment.check_required_fields()
except ValidationError as e:
# process error
print(e)
Expand Down Expand Up @@ -157,6 +158,7 @@ from globee.signals import globee_valid_ipn

@receiver(globee_valid_ipn)
def crypto_payment_ipn(sender, **kwargs):
# payment / sender contains the payment data sent to the IPN view
payment = sender

# check if payment is confirmed or use any other payment status
Expand All @@ -173,7 +175,7 @@ def crypto_payment_ipn(sender, **kwargs):

```

if you don't trust the ipn response, you can also get the payment data from GloBee
### verify the incoming payment data

```python
from django.dispatch import receiver
Expand All @@ -184,13 +186,14 @@ from globee.core import GlobeePayment

@receiver(globee_valid_ipn)
def crypto_payment_ipn(sender, **kwargs):
# payment / sender contains the payment data sent to the IPN view
payment = sender
globee_payment = GlobeePayment()
# OR set payment id in init
# globee_payment = GlobeePayment(payment_id=payment.payment_id)

try:
# get the payment data from globee
# get the payment data directly from GloBee
payment_data = globee_payment.get_payment_by_id(payment.payment_id)
# you don't need to set the payment id if you have already set the payment id in GlobeePayment init
# payment_data = globee_payment.get_payment_by_id()
Expand Down
5 changes: 1 addition & 4 deletions globee/tests.py
Expand Up @@ -188,13 +188,13 @@ def test_create_payment_invalid_urls(self):

@override_settings(GLOBEE_TESTNET=True)
@override_settings(GLOBEE_PARANOID_MODE=False)
@override_settings(ROOT_URLCONF='globee.urls')
class GlobeePaymentIPNTestCase(TestCase):

def setUp(self):
GlobeeIPN.objects.all().delete()
self.assertEqual(0, GlobeeIPN.objects.count())

@override_settings(ROOT_URLCONF='globee.urls')
def test_ipn_view_valid(self):
count_before = 0
self.assertEqual(count_before, GlobeeIPN.objects.all().count())
Expand Down Expand Up @@ -223,7 +223,6 @@ def test_ipn_view_valid(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(count_before + 1, GlobeeIPN.objects.all().count())

@override_settings(ROOT_URLCONF='globee.urls')
def test_ipn_view_invalid_payment_id_not_provided(self):
count_before = 0
self.assertEqual(count_before, GlobeeIPN.objects.all().count())
Expand Down Expand Up @@ -251,7 +250,6 @@ def test_ipn_view_invalid_payment_id_not_provided(self):
self.assertEqual(response.status_code, 400)
self.assertEqual(count_before, GlobeeIPN.objects.all().count())

@override_settings(ROOT_URLCONF='globee.urls')
def test_ipn_view_invalid_key_error(self):
count_before = 0
self.assertEqual(count_before, GlobeeIPN.objects.all().count())
Expand All @@ -263,7 +261,6 @@ def test_ipn_view_invalid_key_error(self):
self.assertEqual(response.status_code, 400)
self.assertEqual(count_before, GlobeeIPN.objects.all().count())

@override_settings(ROOT_URLCONF='globee.urls')
def test_ipn_view_invalid_total(self):
count_before = 0
self.assertEqual(count_before, GlobeeIPN.objects.all().count())
Expand Down
15 changes: 10 additions & 5 deletions globee/views.py
@@ -1,13 +1,16 @@
from datetime import datetime
from logging import getLogger
from json import loads as json_loads, dumps as json_dumps

from django.core.exceptions import ValidationError
from pytz import utc as pytz_utc

from django.conf import settings
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

from globee.core import GlobeePayment
from globee.models import GlobeeIPN


Expand All @@ -18,8 +21,12 @@
@csrf_exempt
def globee_ipn_view(request):
paranoid = getattr(settings, 'GLOBEE_PARANOID_MODE', False)
payment_data = json_loads(request.body.decode("utf-8"))

auto_validate = getattr(settings, 'GLOBEE_AUTO_VERIFY', False)
payment_response = request.body.decode("utf-8")
payment_data = json_loads(payment_response)
if auto_validate:
globee_payment = GlobeePayment()
payment_data = globee_payment.get_payment_by_id(payment_data['id'])
pretty_data = json_dumps(payment_data, indent=4, sort_keys=True)
logger.debug('Globee POST data: %s' % pretty_data)

Expand Down Expand Up @@ -48,10 +55,8 @@ def globee_ipn_view(request):
logger.error('Key %s not found in payment data.' % e)
status = 200 if paranoid else 400
return HttpResponse(status=status)
except ValueError as e:
except (ValueError, ValidationError) as e:
logger.error(e)
status = 200 if paranoid else 400
return HttpResponse(status=status)

return HttpResponse(status=200)

2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -9,7 +9,7 @@

setup(
name='django-globee',
version='1.4.0',
version='1.5.0',
packages=find_packages(),
include_package_data=True,
license='MIT License',
Expand Down

0 comments on commit 3042a69

Please sign in to comment.