Exemple #1
0
def adyen_return_handler(request, methodid):
    method = get_object_or_404(InvoicePaymentMethod, pk=methodid, active=True)
    pm = method.get_implementation()

    sig = pm.calculate_signature(request.GET)

    if sig != request.GET['merchantSig']:
        return render(request, 'adyen/sigerror.html')

    # We're going to need the invoice for pretty much everything,
    # so attempt to find it.
    if request.GET['merchantReturnData'] != request.GET[
            'merchantReference'] or not request.GET[
                'merchantReturnData'].startswith(
                    pm.config('merchantref_prefix')):
        AdyenLog(pspReference='',
                 message='Return handler received invalid reference %s/%s' %
                 (request.GET['merchantReturnData'],
                  request.GET['merchantReference']),
                 error=True,
                 paymentmethod=method).save()
        return render(
            request, 'adyen/invalidreference.html', {
                'reference':
                "%s//%s" % (request.GET['merchantReturnData'],
                            request.GET['merchantReference']),
            })

    invoiceid = int(request.GET['merchantReturnData']
                    [len(pm.config('merchantref_prefix')):])
    try:
        invoice = Invoice.objects.get(pk=invoiceid)
    except Invoice.DoesNotExist:
        AdyenLog(
            pspReference='',
            message='Return handler could not find invoice for reference %s' %
            request.GET['merchantReturnData'],
            error=True,
            paymentmethod=method).save()
        return render(request, 'adyen/invalidreference.html', {
            'reference': request.GET['merchantReturnData'],
        })
    manager = InvoiceManager()
    if invoice.processor:
        processor = manager.get_invoice_processor(invoice)
        returnurl = processor.get_return_url(invoice)
    else:
        if invoice.recipient_user:
            returnurl = "%s/invoices/%s/" % (settings.SITEBASE, invoice.pk)
        else:
            returnurl = "%s/invoices/%s/%s/" % (settings.SITEBASE, invoice.pk,
                                                invoice.recipient_secret)

    AdyenLog(pspReference='',
             message='Return handler received %s result for %s' %
             (request.GET['authResult'], request.GET['merchantReturnData']),
             error=False,
             paymentmethod=method).save()
    if request.GET['authResult'] == 'REFUSED':
        return render(request, 'adyen/refused.html', {
            'url': returnurl,
        })
    elif request.GET['authResult'] == 'CANCELLED':
        return HttpResponseRedirect(returnurl)
    elif request.GET['authResult'] == 'ERROR':
        return render(request, 'adyen/transerror.html', {
            'url': returnurl,
        })
    elif request.GET['authResult'] == 'PENDING':
        return render(request, 'adyen/pending.html', {
            'url': returnurl,
        })
    elif request.GET['authResult'] == 'AUTHORISED':
        # NOTE! Adyen strongly recommends not reacting on
        # authorized values, but deal with them from the
        # notifications instead. So we'll do that.
        # However, if we reach this point and it's actually
        # already dealt with by the notification arriving
        # asynchronously, redirect the user properly.
        if invoice.paidat:
            # Yup, it's paid, so send the user off to the page
            # that they came from.
            return HttpResponseRedirect(returnurl)

        # Show the user a pending message. The refresh time is dependent
        # on how many times we've seen this one before.
        status, created = ReturnAuthorizationStatus.objects.get_or_create(
            pspReference=request.GET['pspReference'])
        status.seencount += 1
        status.save()
        return render(request, 'adyen/authorized.html', {
            'refresh': 3**status.seencount,
            'url': returnurl,
        })
    else:
        return render(request, 'adyen/invalidresult.html', {
            'result': request.GET['authResult'],
        })
Exemple #2
0
def payment_post(request):
    nonce = request.POST['payment_method_nonce']
    invoice = get_object_or_404(Invoice, pk=get_int_or_error(request.POST, 'invoice'), deleted=False, finalized=True)
    method = get_object_or_404(InvoicePaymentMethod, pk=get_int_or_error(request.POST, 'method'), active=True)
    pm = method.get_implementation()

    if invoice.processor:
        manager = InvoiceManager()
        processor = manager.get_invoice_processor(invoice)
        returnurl = processor.get_return_url(invoice)
    else:
        if invoice.recipient_user:
            returnurl = "%s/invoices/%s/" % (settings.SITEBASE, invoice.pk)
        else:
            returnurl = "%s/invoices/%s/%s/" % (settings.SITEBASE, invoice.pk, invoice.recipient_secret)

    # Generate the transaction
    result = pm.braintree_sale({
        'amount': '{0}'.format(invoice.total_amount),
        'order_id': '#{0}'.format(invoice.pk),
        'payment_method_nonce': nonce,
        'merchant_account_id': pm.config('merchantacctid'),
        'options': {
            'submit_for_settlement': True,
        }
    })

    trans = result.transaction
    if result.is_success:
        # Successful transaction. Store it for later processing. At authorization, we proceed to
        # flag the payment as done.

        BraintreeLog(transid=trans.id,
                     message='Received successful result for {0}'.format(trans.id),
                     paymentmethod=method).save()

        if trans.currency_iso_code != settings.CURRENCY_ISO:
            BraintreeLog(transid=trans.id,
                         error=True,
                         message='Invalid currency {0}, should be {1}'.format(trans.currency_iso_code, settings.CURRENCY_ISO),
                         paymentmethod=method).save()

            send_simple_mail(settings.INVOICE_SENDER_EMAIL,
                             pm.config('notification_receiver'),
                             'Invalid currency received in Braintree payment',
                             'Transaction {0} paid in {1}, should be {2}.'.format(trans.id, trans.currency_iso_code, settings.CURRENCY_ISO))

            # We'll just throw the "processing error" page, and have
            # the operator deal with the complaints as this is a
            # should-never-happen scenario.
            return render(request, 'braintreepayment/processing_error.html')

        with transaction.atomic():
            # Flag the invoice as paid
            manager = InvoiceManager()
            try:
                def invoice_logger(msg):
                    raise BraintreeProcessingException('Invoice processing failed: %s'.format(msg))

                manager.process_incoming_payment_for_invoice(invoice,
                                                             trans.amount,
                                                             'Braintree id {0}'.format(trans.id),
                                                             0,
                                                             pm.config('accounting_authorized'),
                                                             0,
                                                             [],
                                                             invoice_logger,
                                                             method,
                                                         )
            except BraintreeProcessingException as ex:
                send_simple_mail(settings.INVOICE_SENDER_EMAIL,
                                 pm.config('notification_receiver'),
                                 'Exception occurred processing Braintree result',
                                 "An exception occured processing the payment result for {0}:\n\n{1}\n".format(trans.id, ex))

                return render(request, 'braintreepayment/processing_error.html')

            # Create a braintree transaction - so we can update it later when the transaction settles
            bt = BraintreeTransaction(transid=trans.id,
                                      authorizedat=timezone.now(),
                                      amount=trans.amount,
                                      method=trans.credit_card['card_type'],
                                      paymentmethod=method)
            if invoice.accounting_object:
                bt.accounting_object = invoice.accounting_object
            bt.save()

            send_simple_mail(settings.INVOICE_SENDER_EMAIL,
                             pm.config('notification_receiver'),
                             'Braintree payment authorized',
                             "A payment of %s%s with reference %s was authorized on the Braintree platform for %s.\nInvoice: %s\nRecipient name: %s\nRecipient user: %s\nBraintree reference: %s\n" % (
                                 settings.CURRENCY_ABBREV,
                                 trans.amount,
                                 trans.id,
                                 method.internaldescription,
                                 invoice.title,
                                 invoice.recipient_name,
                                 invoice.recipient_email,
                                 trans.id))

        return HttpResponseRedirect(returnurl)
    else:
        if not trans:
            reason = "Internal error"
        elif trans.status == 'processor_declined':
            reason = "Processor declined: {0}/{1}".format(trans.processor_response_code, trans.processor_response_text)
        elif trans.status == 'gateway_rejected':
            reason = "Gateway rejected: {0}".format(trans.gateway_rejection_reason)
        else:
            reason = "unknown"
        BraintreeLog(transid=trans and trans.id or "UNKNOWN",
                     message='Received FAILED result for {0}'.format(trans and trans.id or "UNKNOWN"),
                     error=True, paymentmethod=method).save()

        return render(request, 'braintreepayment/payment_failed.html', {
            'invoice': invoice,
            'reason': reason,
            'url': returnurl,
        })