mirror of
https://github.com/pretix/pretix.git
synced 2026-08-09 10:37:50 +00:00
Paypal2: handle incomming capture webhooks (Z#23240966) (#6456)
* store the state of the payment regardless of the state control.html shows the banner that the payment is in review depending on payment.info * handle capture ressource * Update src/pretix/plugins/paypal2/views.py Co-authored-by: Phin Wolkwitz <wolkwitz@pretix.eu> * add test * cleanup logic regarding uninteresting resource_type * store payment.info during _execute_payment asap --------- Co-authored-by: Phin Wolkwitz <wolkwitz@pretix.eu>
This commit is contained in:
co-authored by
Phin Wolkwitz
parent
ea792e76b2
commit
4d9dfa88fe
@@ -677,6 +677,8 @@ class PaypalMethod(BasePaymentProvider):
|
|||||||
raise PaymentException(_('We had trouble communicating with PayPal'))
|
raise PaymentException(_('We had trouble communicating with PayPal'))
|
||||||
else:
|
else:
|
||||||
pp_captured_order = response.result
|
pp_captured_order = response.result
|
||||||
|
payment.info = json.dumps(pp_captured_order.dict())
|
||||||
|
payment.save()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ReferencedPayPalObject.objects.get_or_create(order=payment.order, payment=payment, reference=pp_captured_order.id)
|
ReferencedPayPalObject.objects.get_or_create(order=payment.order, payment=payment, reference=pp_captured_order.id)
|
||||||
|
|||||||
@@ -357,14 +357,13 @@ def webhook(request, *args, **kwargs):
|
|||||||
if 'resource_type' not in event_json:
|
if 'resource_type' not in event_json:
|
||||||
return HttpResponse("Invalid body, no resource_type given", status=400)
|
return HttpResponse("Invalid body, no resource_type given", status=400)
|
||||||
|
|
||||||
if event_json['resource_type'] not in ["checkout-order", "refund", "capture"]:
|
|
||||||
return HttpResponse("Not interested in this resource type", status=200)
|
|
||||||
|
|
||||||
# Retrieve the Charge ID of the refunded payment
|
# Retrieve the Charge ID of the refunded payment
|
||||||
if event_json['resource_type'] == 'refund':
|
if event_json['resource_type'] == 'checkout-order':
|
||||||
|
payloadid = event_json['resource']['id']
|
||||||
|
elif event_json['resource_type'] == 'refund' or event_json['resource_type'] == 'capture':
|
||||||
payloadid = get_link(event_json['resource']['links'], 'up')['href'].split('/')[-1]
|
payloadid = get_link(event_json['resource']['links'], 'up')['href'].split('/')[-1]
|
||||||
else:
|
else:
|
||||||
payloadid = event_json['resource']['id']
|
return HttpResponse("Not interested in this resource type", status=200)
|
||||||
|
|
||||||
refs = [payloadid]
|
refs = [payloadid]
|
||||||
if event_json['resource'].get('supplementary_data', {}).get('related_ids', {}).get('order_id'):
|
if event_json['resource'].get('supplementary_data', {}).get('related_ids', {}).get('order_id'):
|
||||||
@@ -424,6 +423,8 @@ def webhook(request, *args, **kwargs):
|
|||||||
**event_json,
|
**event_json,
|
||||||
'_order_state': sale.dict(),
|
'_order_state': sale.dict(),
|
||||||
})
|
})
|
||||||
|
payment.info = json.dumps(sale.dict())
|
||||||
|
payment.save()
|
||||||
|
|
||||||
if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED and sale['status'] in ('PARTIALLY_REFUNDED', 'REFUNDED', 'COMPLETED'):
|
if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED and sale['status'] in ('PARTIALLY_REFUNDED', 'REFUNDED', 'COMPLETED'):
|
||||||
if event_json['resource_type'] == 'refund':
|
if event_json['resource_type'] == 'refund':
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
@@ -409,7 +410,8 @@ def test_webhook_mark_paid(env, client, monkeypatch):
|
|||||||
order.payments.update(state=OrderPayment.PAYMENT_STATE_PENDING)
|
order.payments.update(state=OrderPayment.PAYMENT_STATE_PENDING)
|
||||||
|
|
||||||
pp_order = Result(get_test_order())
|
pp_order = Result(get_test_order())
|
||||||
monkeypatch.setattr("paypalcheckoutsdk.orders.OrdersGetRequest", lambda *args: pp_order)
|
mock_orders_get_request = MagicMock(return_value=pp_order)
|
||||||
|
monkeypatch.setattr("paypalcheckoutsdk.orders.OrdersGetRequest", mock_orders_get_request)
|
||||||
monkeypatch.setattr("pretix.plugins.paypal2.payment.PaypalMethod.init_api", init_api)
|
monkeypatch.setattr("pretix.plugins.paypal2.payment.PaypalMethod.init_api", init_api)
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
ReferencedPayPalObject.objects.create(order=order, payment=order.payments.first(),
|
ReferencedPayPalObject.objects.create(order=order, payment=order.payments.first(),
|
||||||
@@ -497,7 +499,7 @@ def test_webhook_mark_paid(env, client, monkeypatch):
|
|||||||
"resource_version": "2.0"
|
"resource_version": "2.0"
|
||||||
}
|
}
|
||||||
), content_type='application_json')
|
), content_type='application_json')
|
||||||
|
mock_orders_get_request.assert_called_once_with('806440346Y391300T')
|
||||||
order.refresh_from_db()
|
order.refresh_from_db()
|
||||||
assert order.status == Order.STATUS_PAID
|
assert order.status == Order.STATUS_PAID
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user