Example #1
0
def create_transaction(request):
    """This view is called by the phone app to initiate a new transaction"""
    if request.method != 'POST' or 'data' not in request.POST:
        raise PermissionDenied

    transaction = json.loads(request.POST['data'])
    product = transaction.get('product', '')

    if transaction['ticket'] is not None and request.user.is_anonymous():
        # Ticket operations require that the user is authenticated
        return HttpResponseBadRequest(json.dumps({
            'errors': [{
                'message': 'Cannot apply ticket operation when user is not authenticated',
                'code': error_codes.TICKET_OPERATION_WHILE_NOT_AUTHENTICATED,
            }]
        }))

    if transaction['ticket'] == 'kun_lagre':
        order = Order(
            ticket_transaction=True,
            amount=0,
            user=request.user,
            language_code=transaction['språk'],
        )
        order.save()
    elif product == 'cabin_visit':
        order = cabin_visit(transaction, request.user)
    else:
        return HttpResponseBadRequest(json.dumps({
            'errors': [{
                'message': "Unknown product '%s'" % product,
                'code': error_codes.USER_HAS_NO_TICKET,
            }]
        }))

    cancel_return_url = 'https://%s%s' % (
        request.site.domain,
        reverse('payment:postmessage_callback'),
    )

    accept_return_url = 'https://%s%s' % (
        request.site.domain,
        reverse('payment:postmessage_callback'),
    )

    server_callback_url = 'https://%s%s' % (
        request.site.domain,
        reverse('payment:payment_provider_callback'),
    )

    input_parameters = {
        'merchant': settings.DIBS_MERCHANT_ID,
        'orderId': order.get_order_id(),
        'amount': order.amount, # The sum is provided in øre
        'currency': 'NOK', # ISO 4217
        'captureNow': 1,
        'acceptReturnUrl': accept_return_url,
        'cancelReturnUrl': cancel_return_url,
        'callbackUrl': server_callback_url,
        'language': transaction['språk'],
    }

    #
    # Ticket (stored payment card) handling
    #

    if transaction['ticket'] is not None:
        if transaction['ticket'] == 'lagre':
            # User uses card, but wants to save their ticket
            input_parameters['createTicketAndAuth'] = 1

        elif transaction['ticket'] == 'bruk_lagret':
            # User claims to have a saved ticket
            if request.user.dibs_payment_ticket is None:
                # They thought they did, but they don't
                return HttpResponseBadRequest(json.dumps({
                    'errors': [{
                        'message': 'User has no ticket stored',
                        'code': error_codes.USER_HAS_NO_TICKET,
                    }]
                }))

            # We'll perform the DIBS server-to-server call here and return the response to the client
            try:
                dibs_response, order, payment_accepted = dibs.authorize_ticket(request, order)
                if payment_accepted and not order.ticket_transaction:
                    order.try_to_send_email_receipt()
                return HttpResponse(json.dumps(dibs_response))
            except:
                # Downstream handles exception logging, so just return an error message
                return {
                    'errors': [{
                        'message': 'Internal error during ticket authorization, please try again',
                        'code': error_codes.INTERNAL_SERVER_ERROR,
                    }]
                }

        elif transaction['ticket'] == 'kun_lagre':
            # Just create and save a new ticket; no transaction
            input_parameters['createTicket'] = 1
            # Force amount to 1 since DIBS doesn't allow 0 even though it is irrelevant in this situation
            input_parameters['amount'] = 1
            del input_parameters['captureNow']

    #
    # End ticket handling
    #

    input_parameters['MAC'] = dibs.calculate_hmac(input_parameters)
    return HttpResponse(json.dumps(input_parameters))