Example #1
0
def process_invoice(request):
    if 'enrollment' not in request.session:
        return redirect('enrollment:registration')
    enrollment = get_or_create_enrollment(request)

    if enrollment.state == 'registration':
        # Whoops, how did we get here without going through payment first? Redirect back.
        return redirect('enrollment:payment_method')
    elif enrollment.state == 'payment':
        # Cool, this is where we want to be.
        pass
    elif enrollment.state == 'complete':
        # Registration has already been completed, redirect forwards to results page
        return redirect('enrollment:result')

    for user in enrollment.users.all():
        user.pending_user = User.create_pending_user(user.memberid)
        user.save()
        librato.increment('sherpa.medlemmer.innmeldinger')

    if enrollment.relation_type == 'family':
        librato.increment('sherpa.familiemedlemskap.innmelding.faktura_valgt')

    prepare_and_send_email(request, enrollment)
    enrollment.save_prices()
    enrollment.state = 'complete'
    enrollment.result = 'success_invoice'
    enrollment.save()
    return redirect('enrollment:result')
Example #2
0
def process_card(request):
    if 'enrollment' not in request.session:
        return redirect('enrollment:registration')
    enrollment = get_or_create_enrollment(request)

    if enrollment.state == 'registration':
        # Whoops, how did we get here without going through payment first? Redirect back.
        # Note, *this* makes it impossible to use a previously verified transaction id
        # on a *second* registration by skipping the payment view and going straight to this check.
        return redirect('enrollment:payment_method')
    elif enrollment.state == 'payment':
        # Cool, this is where we want to be.
        pass
    elif enrollment.state == 'complete':
        # Registration has already been completed, redirect forwards to results page
        return redirect('enrollment:result')

    # The client's transaction id CAN differ from the one we think is active. Let them override it,
    # given that the transaction id is already registered. Note that the transaction id from the
    # GET parameter is obviously untrusted input.
    try:
        enrollment.transactions.update(active=False)
        active_transaction = enrollment.transactions.get(transaction_id=request.GET['transactionId'])
        active_transaction.active = True
        active_transaction.save()
    except Transaction.DoesNotExist:
        # They returned with a transaction id which we haven't registered on them - cannot see this happen
        # without them tampering with the GET parameter, we'll have to send them back with an error message.
        messages.error(request, 'invalid_transaction_id')
        enrollment.state = 'payment'
        enrollment.save()
        return redirect('enrollment:payment_method')

    if request.GET.get('responseCode') == 'OK':
        try:
            librato.increment('sherpa.requests.nets.process')
            r = requests.get(settings.NETS_PROCESS_URL, params={
                'merchantId': settings.NETS_MERCHANT_ID,
                'token': settings.NETS_TOKEN,
                'operation': 'SALE',
                'transactionId': active_transaction.transaction_id
            })
            response = r.text.encode('utf-8')

            dom = ET.fromstring(response)
            response_code = dom.find(".//ResponseCode")
            response_text = dom.find(".//ResponseText")
            payment_verified = False

            tx_already_processed_explicit = response_code.text == '98'
            tx_already_processed_general = (
                response_code.text == '99'
                and response_text is not None
                and response_text.text == 'Transaction already processed'
            )

            if response_code is None:
                # Crap, we didn't get the expected response from Nets.
                # This has happened a few times before. We'll have to handle it ourselves.
                logger.error(
                    "Mangler 'ResponseCode' element fra Nets",
                    extra={
                        'request': request,
                        'nets_response': response,
                        'enrollment': enrollment,
                        'transaction_id': active_transaction.transaction_id
                    }
                )
                enrollment.state = 'payment'
                enrollment.save()
                context = current_template_layout(request)
                return render(request, 'central/enrollment/payment-process-error.html', context)
            elif tx_already_processed_explicit or tx_already_processed_general:
                # The transaction might have already been processed if the user resends the process_card
                # request - recheck nets with a Query request and verify those details
                sale_response = response
                librato.increment('sherpa.requests.nets.query')
                r = requests.get(settings.NETS_QUERY_URL, params={
                    'merchantId': settings.NETS_MERCHANT_ID,
                    'token': settings.NETS_TOKEN,
                    'transactionId': active_transaction.transaction_id
                })
                response = r.text.encode('utf-8')
                dom = ET.fromstring(response)
                order_amount = int(dom.find(".//OrderInformation/Amount").text)
                captured_amount = int(dom.find(".//Summary/AmountCaptured").text)
                credited_amount = int(dom.find(".//Summary/AmountCredited").text)

                if order_amount == (captured_amount - credited_amount) == enrollment.total_price() * 100:
                    payment_verified = True
                else:
                    logger.warning(
                        "Nets: Prosessert transaksjon matcher ikke forventet beløp",
                        extra={
                            'request': request,
                            'enrollment': enrollment,
                            'nets_sale_response': sale_response,
                            'nets_query_response': response,
                            'transaction_id': active_transaction.transaction_id,
                            'payment_verified': payment_verified,
                            'order_amount': order_amount,
                            'captured_amount': captured_amount,
                            'credited_amount': credited_amount,
                            'total_price_100': enrollment.total_price() * 100
                        }
                    )

            elif response_code.text == 'OK':
                payment_verified = True

            if payment_verified:
                # Mark the transaction as successful
                active_transaction.state = 'success'
                active_transaction.save()

                # Register the payment in focus
                for user in enrollment.users.all():
                    focus_user = FocusEnrollment.objects.get(memberid=user.memberid)
                    focus_user.paid = True
                    focus_user.save()
                    user.pending_user = User.create_pending_user(user.memberid)
                    user.save()
                    librato.increment('sherpa.medlemmer.innmeldinger')

                if enrollment.relation_type == 'family':
                    librato.increment('sherpa.familiemedlemskap.innmelding.kort_betalt')

                prepare_and_send_email(request, enrollment)
                enrollment.save_prices()
                enrollment.state = 'complete'
                enrollment.result = 'success_card'
                enrollment.save()
            else:
                active_transaction.state = 'fail'
                active_transaction.save()

                enrollment.state = 'registration'
                enrollment.result = 'fail'
                enrollment.save()
        except requests.ConnectionError:
            logger.warning(
                "Nets `process` feil",
                exc_info=sys.exc_info(),
                extra={'request': request}
            )
            enrollment.state = 'payment'
            enrollment.save()
            context = current_template_layout(request)
            return render(request, 'central/enrollment/payment-process-error.html', context)

    else:
        active_transaction.state = 'cancel'
        active_transaction.save()

        enrollment.state = 'registration'
        enrollment.result = 'cancel'
        enrollment.save()
    return redirect('enrollment:result')