forked from CGM_Public/pretix_original
Implement a strong locking check to avoid race conditions during payment
This commit is contained in:
@@ -1098,9 +1098,23 @@ class OrderPayment(models.Model):
|
|||||||
from pretix.base.services.mail import SendMailException
|
from pretix.base.services.mail import SendMailException
|
||||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||||
|
|
||||||
self.state = self.PAYMENT_STATE_CONFIRMED
|
with transaction.atomic():
|
||||||
self.payment_date = now()
|
locked_instance = OrderPayment.objects.select_for_update().get(pk=self.pk)
|
||||||
self.save()
|
if locked_instance.state == self.PAYMENT_STATE_CONFIRMED:
|
||||||
|
# Race condition detected, this payment is already confirmed
|
||||||
|
return
|
||||||
|
|
||||||
|
locked_instance.state = self.PAYMENT_STATE_CONFIRMED
|
||||||
|
locked_instance.payment_date = now()
|
||||||
|
locked_instance.info = self.info # required for backwards compatibility
|
||||||
|
locked_instance.save(update_fields=['state', 'payment_date', 'info'])
|
||||||
|
|
||||||
|
# Do a cheap manual "refresh from db" on non-complex fields
|
||||||
|
for field in self._meta.concrete_fields:
|
||||||
|
if not field.is_relation:
|
||||||
|
setattr(self, field.attname, getattr(locked_instance, field.attname))
|
||||||
|
|
||||||
|
self.refresh_from_db()
|
||||||
|
|
||||||
self.order.log_action('pretix.event.order.payment.confirmed', {
|
self.order.log_action('pretix.event.order.payment.confirmed', {
|
||||||
'local_id': self.local_id,
|
'local_id': self.local_id,
|
||||||
|
|||||||
@@ -1517,6 +1517,7 @@ def test_refund_paid_order_automatically_failed(client, env, monkeypatch):
|
|||||||
p.info_data = {
|
p.info_data = {
|
||||||
'id': 'foo'
|
'id': 'foo'
|
||||||
}
|
}
|
||||||
|
p.save()
|
||||||
p.confirm()
|
p.confirm()
|
||||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||||
|
|
||||||
@@ -1556,6 +1557,7 @@ def test_refund_paid_order_automatically(client, env, monkeypatch):
|
|||||||
p.info_data = {
|
p.info_data = {
|
||||||
'id': 'foo'
|
'id': 'foo'
|
||||||
}
|
}
|
||||||
|
p.save()
|
||||||
p.confirm()
|
p.confirm()
|
||||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user