mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Stripe: Removed global webhook, added test for webhook
This commit is contained in:
@@ -2,12 +2,6 @@ from django.conf.urls import include, url
|
||||
|
||||
from .views import webhook
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^stripe/', include([
|
||||
url(r'^webhook/$', webhook, name='webhook'),
|
||||
])),
|
||||
]
|
||||
|
||||
event_patterns = [
|
||||
url(r'^stripe/', include([
|
||||
url(r'^webhook/$', webhook, name='webhook'),
|
||||
|
||||
@@ -9,12 +9,14 @@ from django.views.decorators.http import require_POST
|
||||
from pretix.base.models import Event, Order
|
||||
from pretix.base.services.orders import mark_order_refunded
|
||||
from pretix.plugins.stripe.payment import Stripe
|
||||
from pretix.presale.utils import event_view
|
||||
|
||||
logger = logging.getLogger('pretix.plugins.stripe')
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
@require_POST
|
||||
@event_view
|
||||
def webhook(request, *args, **kwargs):
|
||||
event_json = json.loads(request.body.decode('utf-8'))
|
||||
|
||||
@@ -28,7 +30,7 @@ def webhook(request, *args, **kwargs):
|
||||
elif event_json['data']['object']['object'] == "dispute":
|
||||
charge_id = event_json['data']['object']['charge']
|
||||
else:
|
||||
return HttpResponse("unhandled", status=200)
|
||||
return HttpResponse("Not interested in this data type", status=200)
|
||||
|
||||
prov = Stripe(request.event)
|
||||
prov._init_api()
|
||||
@@ -40,21 +42,19 @@ def webhook(request, *args, **kwargs):
|
||||
|
||||
metadata = charge['metadata']
|
||||
if 'event' not in metadata:
|
||||
return HttpResponse('Event not given', status=200)
|
||||
return HttpResponse('Event not given in charge metadata', status=200)
|
||||
|
||||
if int(metadata['event']) != request.event.pk:
|
||||
return HttpResponse('Not interested in this event', status=200)
|
||||
|
||||
try:
|
||||
event = Event.objects.get(id=metadata['event'])
|
||||
except Event.DoesNotExist:
|
||||
return HttpResponse('Event not found', status=200)
|
||||
|
||||
try:
|
||||
order = event.orders.objects.get(id=metadata['order'])
|
||||
order = request.event.orders.get(id=metadata['order'])
|
||||
except Order.DoesNotExist:
|
||||
return HttpResponse('Order not found', status=200)
|
||||
|
||||
order.log_action('pretix.plugins.stripe.event', data=event_json)
|
||||
|
||||
if order.status == Order.STATUS_PAID and (charge['refunded']['total_count'] > 0 or charge['dispute']):
|
||||
if order.status == Order.STATUS_PAID and (len(charge['refunds']) > 0 or charge['dispute']):
|
||||
mark_order_refunded(order)
|
||||
|
||||
return HttpResponse(status=200)
|
||||
|
||||
0
src/tests/plugins/stripe/__init__.py
Normal file
0
src/tests/plugins/stripe/__init__.py
Normal file
135
src/tests/plugins/stripe/test_webhook.py
Normal file
135
src/tests/plugins/stripe/test_webhook.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import Event, Order, Organizer
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env():
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
event = Event.objects.create(
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), live=True
|
||||
)
|
||||
o1 = Order.objects.create(
|
||||
code='FOOBAR', event=event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=Decimal('13.37'), payment_provider='banktransfer'
|
||||
)
|
||||
return event, o1
|
||||
|
||||
|
||||
def get_test_charge(order: Order):
|
||||
return {
|
||||
"id": "ch_18TY6GGGWE2Is8TZHanef25",
|
||||
"object": "charge",
|
||||
"amount": 1337,
|
||||
"amount_refunded": 1000,
|
||||
"application_fee": None,
|
||||
"balance_transaction": "txn_18TY6GGGWE2Ias8TkwY6o51W",
|
||||
"captured": True,
|
||||
"created": 1467642664,
|
||||
"currency": "eur",
|
||||
"customer": None,
|
||||
"description": None,
|
||||
"destination": None,
|
||||
"dispute": None,
|
||||
"failure_code": None,
|
||||
"failure_message": None,
|
||||
"fraud_details": {},
|
||||
"invoice": None,
|
||||
"livemode": False,
|
||||
"metadata": {
|
||||
"code": order.code,
|
||||
"order": str(order.pk),
|
||||
"event": str(order.event.pk),
|
||||
},
|
||||
"order": None,
|
||||
"paid": True,
|
||||
"receipt_email": None,
|
||||
"receipt_number": None,
|
||||
"refunded": False,
|
||||
"refunds": [],
|
||||
"shipping": None,
|
||||
"source": {
|
||||
"id": "card_18TY5wGGWE2Ias8Td38PjyPy",
|
||||
"object": "card",
|
||||
"address_city": None,
|
||||
"address_country": None,
|
||||
"address_line1": None,
|
||||
"address_line1_check": None,
|
||||
"address_line2": None,
|
||||
"address_state": None,
|
||||
"address_zip": None,
|
||||
"address_zip_check": None,
|
||||
"brand": "Visa",
|
||||
"country": "US",
|
||||
"customer": None,
|
||||
"cvc_check": "pass",
|
||||
"dynamic_last4": None,
|
||||
"exp_month": 12,
|
||||
"exp_year": 2016,
|
||||
"fingerprint": "FNbGTMaFvhRU2Y0E",
|
||||
"funding": "credit",
|
||||
"last4": "4242",
|
||||
"metadata": {},
|
||||
"name": "Carl Cardholder",
|
||||
"tokenization_method": None,
|
||||
},
|
||||
"source_transfer": None,
|
||||
"statement_descriptor": None,
|
||||
"status": "succeeded"
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_partial_refund(env, client, monkeypatch):
|
||||
charge = get_test_charge(env[1])
|
||||
charge['refunds'] = {
|
||||
"object": "list",
|
||||
"data": [
|
||||
{
|
||||
"id": "re_18otImGGWE2Ias8TY0QvwKYQ",
|
||||
"object": "refund",
|
||||
"amount": "12300",
|
||||
"balance_transaction": "txn_18otImGGWE2Ias8T4fLOxesC",
|
||||
"charge": "ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
"created": 1472729052,
|
||||
"currency": "eur",
|
||||
"metadata": {},
|
||||
"reason": None,
|
||||
"receipt_number": None,
|
||||
"status": "succeeded"
|
||||
}
|
||||
]
|
||||
}
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", lambda *args: charge)
|
||||
|
||||
client.post('/dummy/dummy/stripe/webhook/', json.dumps(
|
||||
{
|
||||
"id": "evt_18otImGGWE2Ias8TUyVRDB1G",
|
||||
"object": "event",
|
||||
"api_version": "2016-03-07",
|
||||
"created": 1472729052,
|
||||
"data": {
|
||||
"object": {
|
||||
"id": "ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
"object": "charge",
|
||||
# Rest of object is ignored anway
|
||||
}
|
||||
},
|
||||
"livemode": True,
|
||||
"pending_webhooks": 1,
|
||||
"request": "req_977XOWC8zk51Z9",
|
||||
"type": "charge.refunded"
|
||||
}
|
||||
), content_type='application_json')
|
||||
|
||||
order = env[1]
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_REFUNDED
|
||||
Reference in New Issue
Block a user