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')
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')