mirror of
https://github.com/pretix/pretix.git
synced 2026-05-09 15:54:03 +00:00
PayPal: Prevent race condition between refund and incoming webhook (Z#23185186) (#4911)
This commit is contained in:
@@ -916,7 +916,9 @@ class PaypalMethod(BasePaymentProvider):
|
|||||||
|
|
||||||
def execute_refund(self, refund: OrderRefund):
|
def execute_refund(self, refund: OrderRefund):
|
||||||
self.init_api()
|
self.init_api()
|
||||||
|
with transaction.atomic():
|
||||||
|
# Lock payment that we are creating refund for to prevent race condition with incoming webhook
|
||||||
|
OrderPayment.objects.select_for_update(of=OF_SELF).get(pk=refund.payment_id)
|
||||||
try:
|
try:
|
||||||
pp_payment = None
|
pp_payment = None
|
||||||
payment_info_data = None
|
payment_info_data = None
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ from decimal import Decimal
|
|||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
from django.db import transaction
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from django.http import (
|
from django.http import (
|
||||||
Http404, HttpResponse, HttpResponseBadRequest, JsonResponse,
|
Http404, HttpResponse, HttpResponseBadRequest, JsonResponse,
|
||||||
@@ -62,6 +63,7 @@ from pretix.base.payment import PaymentException
|
|||||||
from pretix.base.services.cart import add_payment_to_cart, get_fees
|
from pretix.base.services.cart import add_payment_to_cart, get_fees
|
||||||
from pretix.base.settings import GlobalSettingsObject
|
from pretix.base.settings import GlobalSettingsObject
|
||||||
from pretix.control.permissions import event_permission_required
|
from pretix.control.permissions import event_permission_required
|
||||||
|
from pretix.helpers import OF_SELF
|
||||||
from pretix.helpers.http import redirect_to_url
|
from pretix.helpers.http import redirect_to_url
|
||||||
from pretix.multidomain.urlreverse import eventreverse
|
from pretix.multidomain.urlreverse import eventreverse
|
||||||
from pretix.plugins.paypal2.client.customer.partners_merchantintegrations_get_request import (
|
from pretix.plugins.paypal2.client.customer.partners_merchantintegrations_get_request import (
|
||||||
@@ -450,6 +452,9 @@ def webhook(request, *args, **kwargs):
|
|||||||
logger.exception('PayPal error on webhook. Event data: %s' % str(event_json))
|
logger.exception('PayPal error on webhook. Event data: %s' % str(event_json))
|
||||||
return HttpResponse('Refund not found', status=500)
|
return HttpResponse('Refund not found', status=500)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
# Lock payment in case a refund is currently still running
|
||||||
|
payment = OrderPayment.objects.select_for_update(of=OF_SELF).get(pk=payment.pk)
|
||||||
known_refunds = {r.info_data.get('id'): r for r in payment.refunds.all()}
|
known_refunds = {r.info_data.get('id'): r for r in payment.refunds.all()}
|
||||||
if refund['id'] not in known_refunds:
|
if refund['id'] not in known_refunds:
|
||||||
payment.create_external_refund(
|
payment.create_external_refund(
|
||||||
|
|||||||
Reference in New Issue
Block a user