Skip to content

Commit

Permalink
Handle all types of return from MercadoPago
Browse files Browse the repository at this point in the history
Also refactor and comment
  • Loading branch information
Delawen committed Sep 12, 2020
1 parent 3bbfa1c commit c16c9bb
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 78 deletions.
16 changes: 3 additions & 13 deletions pretix_mercadopago/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def settings_form_fields(self):
def settings_content_render(self, request):
settings_content = ""
if self.settings.connect_client_id and not self.settings.secret:
# Use MercadoPAgo connect
# Use MercadoPago connect
if not self.settings.connect_user_id:
settings_content = (
"<p>{}</p>"
Expand Down Expand Up @@ -219,11 +219,11 @@ def execute_payment(self, request: HttpRequest, payment_obj: OrderPayment):
"currency_id": payment_obj.order.event.currency
}
],
"auto_return": 'approved', # solo para las ordenes aprobadas, all
"auto_return": 'all', # solo para las ordenes aprobadas, all
"back_urls": {
"failure":
build_absolute_uri(request.event,
'plugins:pretix_mercadopago:abort'),
'plugins:pretix_mercadopago:return'),
"pending":
build_absolute_uri(request.event,
'plugins:pretix_mercadopago:return'),
Expand Down Expand Up @@ -263,16 +263,6 @@ def execute_payment(self, request: HttpRequest, payment_obj: OrderPayment):
link = preferenceResult["response"]["init_point"]
else:
link = preferenceResult["response"]["sandbox_init_point"]
# messages.error(request, _('Debug ' + str(link) ))
# return str(link)
# if link.method == "REDIRECT" and link.rel == "approval_url":
# if request.session.get('iframe_session', False):
# signer = signing.Signer(salt='safe-redirect')
# return (
# build_absolute_uri(request.event, 'plugins:mercadopago:redirect') + '?url=' +
# urllib.parse.quote(signer.sign(link))
# )
# else:
return link
else:
messages.error(request, _('We had trouble communicating with MercadoPago' + str(preferenceResult["response"])))
Expand Down
4 changes: 1 addition & 3 deletions pretix_mercadopago/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@
from pretix.multidomain import event_url

from .views import (
abort, oauth_disconnect, redirect_view, success, webhook,
oauth_disconnect, redirect_view, success, webhook,
)

event_patterns = [
url(r'^mercadopago/', include([
url(r'^abort/$', abort, name='abort'),
url(r'^return/$', success, name='return'),
url(r'^redirect/$', redirect_view, name='redirect'),

url(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/abort/', abort, name='abort'),
url(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/return/', success, name='return'),

event_url(r'^webhook/$', webhook, name='webhook', require_live=False),
Expand Down
97 changes: 35 additions & 62 deletions pretix_mercadopago/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import json
import logging
from decimal import Decimal

Expand All @@ -14,7 +13,6 @@
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django_scopes import scopes_disabled
#from paypalrestsdk.openid_connect import Tokeninfo

from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
from pretix.base.payment import PaymentException
Expand All @@ -32,6 +30,7 @@ def admin_view(request, *args, **kwargs):
r._csp_ignore = True
return r


@xframe_options_exempt
def redirect_view(request, *args, **kwargs):
signer = signing.Signer(salt='safe-redirect')
Expand All @@ -46,69 +45,60 @@ def redirect_view(request, *args, **kwargs):
r._csp_ignore = True
return r

# Return url for MercadoPago when payment is pending or success


def success(request, *args, **kwargs):
pid = request.GET.get('preference_id')
orderid = request.GET.get('external_reference')
merchant_order_id = request.GET.get('merchant_order_id')
collection_id = request.GET.get('collection_id')
status = request.GET.get('collection_status')
urlkwargs = {}

# Ask MercadoPago again about the status
# to avoid pishing!
# (don't trust any call to this url)
mp = Mercadopago(request.event).init_api()
paymentInfo = mp.get_payment(collection_id)

payment = None
if paymentInfo["status"] == 200:
if orderid == paymentInfo['response']['external_reference']:
payment = OrderPayment.objects.get(pk=orderid)
payment.info = json.dumps(paymentInfo['response'], indent=4)
else:
payment = None
messages.error(request, _('Invalid attempt to pay order ' + orderid))

else:
messages.error(request, str(e))
return None


# Documentation for payment object:
# https://www.mercadopago.com.ar/developers/es/reference/payments/resource/
if payment:
if status == 'approved' == paymentInfo['response']['status']:
order = payment.order
mpstatus = paymentInfo['response']['status']

# Something fishy detected
if status != mpstatus:
messages.error(request, _('Invalid attempt to pay order ' + orderid))
elif mpstatus == 'approved':
payment.order.status = Order.STATUS_PAID
payment.order.save()
payment.state ='confirmed'
payment.save()
if status == 'pending' == paymentInfo['response']['status']:
payment.state = 'confirmed'
elif (mpstatus == 'pending') or (mpstatus == 'authorized') or (mpstatus == 'in_process') or (mpstatus == 'in_mediation'):
payment.order.status = Order.STATUS_PENDING
payment.order.save()
payment.state ='pending'
payment.save()


"""
return redirect(eventreverse(request.event, 'presale:event.checkout', kwargs=urlkwargs))
payment.state = 'pending'
elif (mpstatus == 'cancelled'):
payment.order.status = Order.STATUS_CANCELED
payment.state = 'canceled'
elif (mpstatus == 'rejected'):
payment.order.status = Order.STATUS_CANCELED
payment.state = 'failed'
elif (mpstatus == 'refunded') or (mpstatus == 'charged_back'):
payment.order.status = Order.STATUS_CANCELED
payment.state = 'refunded'

payment.info = paymentInfo['response']['status_detail']
payment.order.save()
payment.save()

if 'cart_namespace' in kwargs:
urlkwargs['cart_namespace'] = kwargs['cart_namespace']
if request.session.get('payment_mercadopago_payment'):
payment = OrderPayment.objects.get(pk=request.session.get('payment_mercadopago_payment'))
else:
payment = None
if pid == request.session.get('payment_mercadopago_id', None):
if payment:
prov = Mercadopago(request.event)
try:
resp = prov.execute_payment(request, payment)
except PaymentException as e:
messages.error(request, str(e))
urlkwargs['step'] = 'payment'
return redirect(eventreverse(request.event, 'presale:event.checkout', kwargs=urlkwargs))
if resp:
return resp
else:
messages.error(request, _('Invalid response from MercadoPago received.'))
logger.error('Session did not contain payment_mercadopago_id')
urlkwargs['step'] = 'payment'
return redirect(eventreverse(request.event, 'presale:event.checkout', kwargs=urlkwargs))
"""
if payment:
return redirect(eventreverse(request.event, 'presale:event.order', kwargs={
'order': payment.order.code,
Expand All @@ -119,23 +109,6 @@ def success(request, *args, **kwargs):
return redirect(eventreverse(request.event, 'presale:event.checkout', kwargs=urlkwargs))


def abort(request, *args, **kwargs):
messages.error(request, _('It looks like you canceled the MercadoPago payment'))

if request.session.get('payment_mercadoapgo_payment'):
payment = OrderPayment.objects.get(pk=request.session.get('payment_mercadopago_payment'))
else:
payment = None

if payment:
return redirect(eventreverse(request.event, 'presale:event.order', kwargs={
'order': payment.order.code,
'secret': payment.order.secret
}) + ('?paid=no' if payment.order.status == Order.STATUS_PAID else ''))
else:
return redirect(eventreverse(request.event, 'presale:event.checkout', kwargs={'step': 'payment'}))


@csrf_exempt
@require_POST
@scopes_disabled()
Expand Down

0 comments on commit c16c9bb

Please sign in to comment.