Add payment provider specific details to the API

This commit is contained in:
Raphael Michel
2019-08-30 17:04:22 +02:00
parent e3a4ec93fc
commit aa99dbc830
9 changed files with 81 additions and 13 deletions

View File

@@ -297,12 +297,22 @@ class PaymentURLField(serializers.URLField):
})
class PaymentDetailsField(serializers.Field):
def to_representation(self, value: OrderPayment):
pp = value.payment_provider
if not pp:
return {}
return pp.api_payment_details(value)
class OrderPaymentSerializer(I18nAwareModelSerializer):
payment_url = PaymentURLField(source='*', allow_null=True, read_only=True)
details = PaymentDetailsField(source='*', allow_null=True, read_only=True)
class Meta:
model = OrderPayment
fields = ('local_id', 'state', 'amount', 'created', 'payment_date', 'provider', 'payment_url')
fields = ('local_id', 'state', 'amount', 'created', 'payment_date', 'provider', 'payment_url',
'details')
class OrderRefundSerializer(I18nAwareModelSerializer):

View File

@@ -608,22 +608,24 @@ class Event(EventMixin, LoggedModel):
question_map=question_map
)
def get_payment_providers(self) -> dict:
def get_payment_providers(self, cached=False) -> dict:
"""
Returns a dictionary of initialized payment providers mapped by their identifiers.
"""
from ..signals import register_payment_providers
responses = register_payment_providers.send(self)
providers = {}
for receiver, response in responses:
if not isinstance(response, list):
response = [response]
for p in response:
pp = p(self)
providers[pp.identifier] = pp
if not cached or not hasattr(self, '_cached_payment_providers'):
responses = register_payment_providers.send(self)
providers = {}
for receiver, response in responses:
if not isinstance(response, list):
response = [response]
for p in response:
pp = p(self)
providers[pp.identifier] = pp
return OrderedDict(sorted(providers.items(), key=lambda v: str(v[1].verbose_name)))
self._cached_payment_providers = OrderedDict(sorted(providers.items(), key=lambda v: str(v[1].verbose_name)))
return self._cached_payment_providers
def get_html_mail_renderer(self):
"""

View File

@@ -1196,7 +1196,7 @@ class OrderPayment(models.Model):
"""
Cached access to an instance of the payment provider in use.
"""
return self.order.event.get_payment_providers().get(self.provider)
return self.order.event.get_payment_providers(cached=True).get(self.provider)
def _mark_paid(self, force, count_waitinglist, user, auth, ignore_date=False, overpaid=False):
from pretix.base.signals import order_paid

View File

@@ -657,6 +657,15 @@ class BasePaymentProvider:
obj.info = '{}'
obj.save(update_fields=['info'])
def api_payment_details(self, payment: OrderPayment):
"""
Will be called to populate the ``details`` parameter of the payment in the REST API.
:param payment: The payment in question.
:return: A serializable dictionary
"""
return {}
class PaymentException(Exception):
pass
@@ -720,6 +729,12 @@ class BoxOfficeProvider(BasePaymentProvider):
def order_change_allowed(self, order: Order) -> bool:
return False
def api_payment_details(self, payment: OrderPayment):
return {
"pos_id": payment.info_data.get('pos_id', None),
"receipt_id": payment.info_data.get('receipt_id', None),
}
def payment_control_render(self, request, payment) -> str:
if not payment.info:
return
@@ -864,6 +879,11 @@ class OffsettingProvider(BasePaymentProvider):
def order_change_allowed(self, order: Order) -> bool:
return False
def api_payment_details(self, payment: OrderPayment):
return {
"orders": payment.info_data.get('orders', []),
}
def payment_control_render(self, request: HttpRequest, payment: OrderPayment) -> str:
return _('Balanced against orders: %s' % ', '.join(payment.info_data['orders']))

View File

@@ -395,6 +395,20 @@ class Paypal(BasePaymentProvider):
'retry': retry, 'order': payment.order}
return template.render(ctx)
def api_payment_details(self, payment: OrderPayment):
sale_id = None
for trans in payment.info_data.get('transactions', []):
for res in trans.get('related_resources', []):
if 'sale' in res and 'id' in res['sale']:
sale_id = res['sale']['id']
return {
"payer_email": payment.info_data.get('payer', {}).get('payer_info', {}).get('email'),
"payer_id": payment.info_data.get('payer', {}).get('payer_info', {}).get('payer_id'),
"cart_id": payment.info_data.get('cart', None),
"payment_id": payment.info_data.get('id', None),
"sale_id": sale_id,
}
def payment_control_render(self, request: HttpRequest, payment: OrderPayment):
template = get_template('pretixplugins/paypal/control.html')
ctx = {'request': request, 'event': self.event, 'settings': self.settings,

View File

@@ -411,6 +411,12 @@ class StripeMethod(BasePaymentProvider):
}
return template.render(ctx)
def api_payment_details(self, payment: OrderPayment):
return {
"id": payment.info_data.get("id", None),
"payment_method": payment.info_data.get("payment_method", None)
}
def payment_control_render(self, request, payment) -> str:
if payment.info:
payment_info = json.loads(payment.info)