示例#1
0
def charge(request):
    """Endpoint for creating a charge based on a token"""
    token_form = SimpleInvoicePaymentForm(request.POST)
    if not token_form.is_valid():
        raise exceptions.GatewayException(token_form.errors)
    invoice_id = token_form.cleaned_data['invoice']
    charge_token = token_form.cleaned_data['token']
    try:
        inv = Invoice.objects.get(pk=invoice_id,
                                  client__in=request.user.clients.all())
    except Invoice.DoesNotExist:
        raise exceptions.InvoicePaymentException(
            'Invoice {} does not exist'.format(invoice_id),
            invoice_id=invoice_id)
    if inv.balance <= 0:
        raise exceptions.InvoicePaymentException(
            'Invoice {} is already paid'.format(invoice_id),
            invoice_id=invoice_id)
    stripe.api_key = conf.secret_key
    token_id = charge_token.get('id')
    if token_id is None:
        raise exceptions.InvoicePaymentException('Charge failed',
                                                 invoice_id=invoice_id)
    try:
        charge_result = stripe.Charge.create(
            amount=utils.convert_amount_to_api(inv.balance, inv.currency.pk),
            currency=inv.currency.pk.lower(),
            description=_('Invoice {} payment').format(inv.pk),
            metadata={"invoice": inv.pk},
            source=token_id,
            idempotency_key=None)
    except CardError as e:
        LOG.exception(e)
        body = e.json_body
        err = body.get('error', {})
        raise exceptions.InvoicePaymentException(err.get(
            'message', 'Charge failed'),
                                                 invoice_id=invoice_id)
    except StripeError as e:
        LOG.exception(e)
        raise exceptions.InvoicePaymentException('Charge failed',
                                                 invoice_id=invoice_id)
    process_charge(charge=charge_result)
    relative_url = 'billing/invoices/{}'.format(invoice_id)
    return HttpResponseRedirect(
        fleio_join_url(settings.FRONTEND_URL, relative_url))
示例#2
0
def pay_invoice(request):
    invoice_id = request.query_params.get('invoice')
    if invoice_id is None:
        raise exceptions.GatewayException("An 'invoice' parameter is required")
    try:
        inv = Invoice.objects.get(pk=invoice_id,
                                  client__in=request.user.clients.all())
    except Invoice.DoesNotExist:
        raise exceptions.GatewayException(
            'Invoice {} does not exist'.format(invoice_id))
    if inv.balance <= 0:
        raise exceptions.InvoicePaymentException(
            'Invoice {} is already paid'.format(invoice_id),
            invoice_id=invoice_id)

    amount = str(inv.balance)
    pay_message = _('Pay {} {} for invoice {}'.format(amount, inv.currency.pk,
                                                      inv.pk))

    recurring = request.query_params.get('recurring', False)
    recurring = True if (recurring == 'True' or recurring == 'true'
                         or recurring == '1') else False

    if recurring:
        existing_recurrent_payments_config = RecurringPayments.objects.filter(
            client=inv.client).first()
        if existing_recurrent_payments_config:
            raise exceptions.GatewayException(
                _('Recurrent payments were already configured for stripe.'))
        token_form = SetupRecurringPaymentsForm(initial={'invoice': inv.pk})
        stripe.api_key = conf.secret_key
        payment_intent = stripe.PaymentIntent.create(
            amount=utils.convert_amount_to_api(inv.balance, inv.currency.pk),
            currency=inv.currency.pk.lower(),
            setup_future_usage='off_session',
            metadata={"invoice": inv.pk},
        )
        return render(request=request,
                      template_name='stripe/setup_recurring.html',
                      context={
                          'payment_vars':
                          json.dumps({'publicKey': conf.public_key}),
                          'pay_message':
                          pay_message,
                          'client_secret':
                          payment_intent.client_secret,
                          'token_form':
                          token_form
                      })
    token_form = SimpleInvoicePaymentForm(initial={'invoice': inv.pk})
    return render(request=request,
                  template_name='stripe/pay_invoice.html',
                  context={
                      'payment_vars':
                      json.dumps({'publicKey': conf.public_key}),
                      'pay_message': pay_message,
                      'token_form': token_form
                  })
示例#3
0
def pay_invoice(request):
    invoice_id = request.query_params.get('invoice')
    try:
        Invoice.objects.get(pk=invoice_id, client__in=request.user.clients.all())  # type: Invoice
    except Invoice.DoesNotExist:
        raise gateway_exceptions.GatewayException(_('Invoice {} does not exist').format(invoice_id))
    try:
        configure()
        payment = create_payment(invoice_id)
    except Exception as create_payment_exception:
        raise gateway_exceptions.InvoicePaymentException(message=str(create_payment_exception), invoice_id=invoice_id)

    return HttpResponseRedirect(get_approval_url(payment))
示例#4
0
def pay_invoice(request):
    invoice_id = request.query_params.get('invoice')

    try:
        process_test_payment(test_mode=conf.test_mode)
    except Exception as create_payment_exception:
        # handle possible exception
        raise gateway_exceptions.InvoicePaymentException(
            message=str(create_payment_exception), invoice_id=invoice_id)
    # redirect to invoice
    relative_url = 'billing/invoices/{}'.format(invoice_id)
    return HttpResponseRedirect(
        fleio_join_url(settings.FRONTEND_URL, relative_url))
示例#5
0
def pay_invoice(request):
    invoice_id = request.query_params.get('invoice')
    try:
        Invoice.objects.get(
            pk=invoice_id,
            client__in=request.user.clients.all())  # type: Invoice
    except Invoice.DoesNotExist:
        raise gateway_exceptions.GatewayException(
            _('Invoice {} does not exist').format(invoice_id))
    try:
        payu_client = PayUClient(invoice_id=invoice_id, request=request)
        return payu_client.create_order()
    except Exception as create_payment_exception:
        raise gateway_exceptions.InvoicePaymentException(
            message=str(create_payment_exception), invoice_id=invoice_id)
示例#6
0
def process_charge(charge):
    """Process a charge result"""
    gateway = Gateway.objects.get(name='stripe')
    external_id = charge.id
    transaction_id = None
    transaction_status = charge_status(charge)
    invoice_id = charge.metadata.get('invoice')
    if external_id is not None:
        try:
            existing_transaction = Transaction.objects.get(
                external_id=external_id, gateway=gateway)
            transaction_id = existing_transaction.id
        except Transaction.DoesNotExist:
            real_amount = utils.convert_amount_from_api(
                charge.amount, charge.currency)
            serializer_data = {
                'invoice': invoice_id,
                'external_id': external_id,
                'amount': real_amount,
                'currency': charge.currency.upper(),
                'gateway': gateway.pk,
                'fee': gateway.get_fee(amount=real_amount),
                'date_initiated':
                datetime.datetime.fromtimestamp(charge.created),
                'extra': {},
                'status': transaction_status
            }
            tr_ser = AddTransactionSerializer(data=serializer_data)
            if tr_ser.is_valid(raise_exception=False):
                new_transaction = tr_ser.save()
                transaction_id = new_transaction.id
            else:
                LOG.error('Could not process charge for stripe: {}'.format(
                    json.dumps(tr_ser.errors)))
                raise exceptions.InvoicePaymentException(
                    'Could not process charge for invoice {}.',
                    invoice_id=invoice_id)
        else:
            # Update the transaction status only
            existing_transaction.status = transaction_status
            existing_transaction.save(update_fields=['status'])
    gateway.log_callback(external_id=external_id,
                         status=charge.status,
                         data=charge,
                         error=(charge.status == 'failed'),
                         error_code=charge.failure_code,
                         error_info=charge.failure_message)
    if transaction_status == TransactionStatus.FAILURE:
        raise exceptions.GatewayException(charge.failure_message or 'error')
    else:
        if transaction_status == TransactionStatus.SUCCESS:
            activity_helper.start_generic_activity(
                category_name='stripe',
                activity_class='stripe payment',
                invoice_id=invoice_id)

            invoice_add_payment.delay(invoice_id=invoice_id,
                                      amount=utils.convert_amount_from_api(
                                          charge.amount, charge.currency),
                                      currency_code=charge.currency.upper(),
                                      transaction_id=transaction_id)

            activity_helper.end_activity()
示例#7
0
def process_refund(refund):
    # FIXME(tomo): This does not support partial refunds
    # Partial refunds should be allowed if the invoice balance is higher than the requested amount
    # Right now, creating a partial refund will set the transaction to refunded even if you refund
    # less than the payment value.
    gateway = Gateway.objects.get(name='stripe')
    external_id = refund.id
    existing_transaction_id = None
    invoice_id = None
    if refund.status == 'succeeded':
        if external_id is not None:
            try:
                existing_transaction = Transaction.objects.get(
                    external_id=refund.charge, gateway=gateway)
                existing_transaction_id = existing_transaction.pk
                invoice_id = existing_transaction.invoice_id
            except Transaction.DoesNotExist:
                raise exceptions.GatewayException('Transaction does not exist')
            else:
                existing_transaction.status = TransactionStatus.REFUNDED
                existing_transaction.save(update_fields=['status'])
        gateway.log_callback(external_id=external_id,
                             status=refund.status,
                             data=refund,
                             error=False)
        # Create a new refund transaction
        real_amount = utils.convert_amount_from_api(refund.amount,
                                                    refund.currency)
        created_date = datetime.datetime.fromtimestamp(refund.created)
        new_transaction_status = TransactionStatus.REFUNDED
        new_refund_transaction = {
            'invoice': invoice_id,
            'external_id': external_id,
            'amount': real_amount,
            'currency': refund.currency,
            'gateway': gateway.pk,
            'fee': gateway.get_fee(amount=decimal.Decimal(real_amount)),
            'date_initiated': created_date,
            'extra': {
                'balance_transaction': refund.balance_transaction
            },
            'refunded_transaction': existing_transaction_id,
            'status': new_transaction_status
        }
        tr_ser = AddTransactionSerializer(data=new_refund_transaction)
        if tr_ser.is_valid(raise_exception=False):
            new_transaction = tr_ser.save()
            new_transaction_id = new_transaction.id

            activity_helper.start_generic_activity(
                category_name='stripe',
                activity_class='stripe payment refund',
                invoice_id=invoice_id)

            invoice_refund_payment.delay(
                transaction_id=new_transaction.refunded_transaction.pk,
                amount=utils.convert_amount_from_api(refund.amount,
                                                     refund.currency),
                to_client_credit=False,
                new_transaction_id=new_transaction_id)

            activity_helper.end_activity()
        else:
            LOG.error(tr_ser.errors)
            raise exceptions.InvoicePaymentException(
                'Unable to process refund', invoice_id=invoice_id)
    elif refund.status == 'failed':
        gateway.log_callback(external_id=external_id,
                             status=refund.status,
                             data=refund,
                             error=(refund.status == 'failed'),
                             error_info=refund.failure_reason)
        raise exceptions.GatewayException(
            _('Refund for transaction {} failed').format(external_id))
示例#8
0
def process_response(resp):
    gateway = Gateway.objects.get(name='romcard')
    external_id = resp.get('external_id')
    transaction_status = resp.get('transaction_status')
    transaction_error = resp.get('error', False)
    invoice = invoice_id_from_api(resp.get('invoice'))
    transaction_id = None
    if external_id is not None and not transaction_error:
        # Check for duplicate transaction based on external ID and NONCE
        possible_duplicates = Transaction.objects.filter(
            external_id=external_id, gateway=gateway)
        for pdup in possible_duplicates:
            if (pdup.extra.get('RRN') == resp.get('transaction_extra',
                                                  {}).get('RRN')
                    and pdup.extra.get('NONCE') == resp.get(
                        'transaction_extra', {}).get('NONCE')):
                # Dupliocate transaction
                LOG.warning('Romcard duplicate transaction {} ignored'.format(
                    external_id))
                return HttpResponseRedirect(
                    fleio_join_url(settings.FRONTEND_URL, 'billing/invoices'))

        existing_transaction = Transaction.objects.filter(
            external_id=external_id,
            gateway=gateway,
            refunded_transaction__isnull=True).first()
        if existing_transaction:
            transaction_id = existing_transaction.pk
            # Update the transaction status only
            existing_transaction.status = transaction_status
            existing_transaction.save(update_fields=['status'])
        else:
            serializer_data = {
                'invoice': invoice,
                'external_id': external_id,
                'amount': resp['amount'],
                'currency': resp['currency'],
                'gateway': gateway.pk,
                'fee': gateway.get_fee(amount=decimal.Decimal(resp['amount'])),
                'date_initiated': resp['transaction_date'],
                'extra': resp['transaction_extra'],
                'status': resp['transaction_status']
            }
            tr_ser = AddTransactionSerializer(data=serializer_data)
            if tr_ser.is_valid(raise_exception=False):
                new_transaction = tr_ser.save()
                transaction_id = new_transaction.pk
            else:
                LOG.error('Romcard transaction error: {}'.format(
                    tr_ser.errors))
                raise exceptions.InvoicePaymentException('Transaction error',
                                                         invoice_id=invoice)

    gateway.log_callback(external_id=external_id,
                         status=resp.get('transaction_status', 'unknown'),
                         data=resp.get('log_data'),
                         error=transaction_error,
                         error_code=resp.get('error_code'),
                         error_info=resp.get('error_info'))
    if transaction_error:
        raise exceptions.InvoicePaymentException(resp.get(
            'error_info', 'error'),
                                                 invoice_id=invoice)
    else:
        relative_invoice_url = 'billing/invoices/{0}'.format(invoice)
        relative_staff_invoice_url = 'staff/billing/invoices/{0}'.format(
            invoice)
        if transaction_status == TransactionStatus.PREAUTH:
            activity_helper.start_generic_activity(
                category_name='romcard',
                activity_class='romcard payment',
                invoice_id=invoice)

            invoice_add_payment.delay(invoice_id=invoice,
                                      amount=resp.get('amount'),
                                      currency_code=resp.get('currency'),
                                      transaction_id=transaction_id)

            activity_helper.end_activity()

            return HttpResponseRedirect(
                fleio_join_url(settings.FRONTEND_URL, relative_invoice_url))
        elif transaction_status == TransactionStatus.CONFIRMED:
            if resp.get('is_recurring', False):
                activity_helper.start_generic_activity(
                    category_name='romcard',
                    activity_class='romcard payment',
                    invoice_id=invoice)
                invoice_add_payment.delay(invoice_id=invoice,
                                          amount=resp.get('amount'),
                                          currency_code=resp.get('currency'),
                                          transaction_id=transaction_id)
                activity_helper.end_activity()
            Transaction.objects.filter(
                external_id=external_id,
                refunded_transaction__isnull=True).update(
                    status=TransactionStatus.CONFIRMED)
            return HttpResponseRedirect(
                fleio_join_url(settings.FRONTEND_URL,
                               relative_staff_invoice_url))
        elif transaction_status in (TransactionStatus.REFUNDED,
                                    TransactionStatus.PARTIAL_REFUNDED):
            existing_transaction = Transaction.objects.filter(
                external_id=external_id,
                refunded_transaction__isnull=True).first()
            if not existing_transaction:
                LOG.error(
                    'Error when processing transaction that should have RRN (external_id) set to {}'
                    .format(external_id))
                raise exceptions.InvoicePaymentException('Transaction error',
                                                         invoice_id=invoice)

            new_refund_transaction = {
                'invoice': invoice,
                'external_id': external_id,
                'amount': resp.get('amount'),
                'currency': resp['currency'],
                'gateway': gateway.pk,
                'fee': gateway.get_fee(amount=decimal.Decimal(resp['amount'])),
                'date_initiated': resp['transaction_date'],
                'extra': resp['transaction_extra'],
                'refunded_transaction': existing_transaction.pk,
                'status': transaction_status
            }
            tr_ser = AddTransactionSerializer(data=new_refund_transaction)
            if tr_ser.is_valid(raise_exception=False):
                new_transaction = tr_ser.save()
            else:
                LOG.error('Romcard transaction error: {}'.format(
                    tr_ser.errors))
                raise exceptions.InvoicePaymentException('Transaction error',
                                                         invoice_id=invoice)

            activity_helper.start_generic_activity(
                category_name='romcard',
                activity_class='romcard payment refund',
                invoice_id=invoice)

            invoice_refund_payment.delay(transaction_id=transaction_id,
                                         amount=resp.get('amount'),
                                         to_client_credit=False,
                                         new_transaction_id=new_transaction.pk)

            activity_helper.end_activity()

            return HttpResponseRedirect(
                fleio_join_url(settings.FRONTEND_URL,
                               relative_staff_invoice_url))
        else:
            LOG.warning('Romcard callback not processed: {}'.format(resp))
            return HttpResponseRedirect(
                fleio_join_url(settings.FRONTEND_URL, 'billing/invoices'))
示例#9
0
def confirm_payment(request):
    # PayPal does a full-page redirect to the return_url that was specified when the payment was created,
    # with PayerID and paymentId appended to the URL.
    payment_id = request.query_params.get('paymentId')
    payer_id = request.query_params.get('PayerID')

    configure()

    payment = get_payment(payment_id)
    invoice_id = get_invoice_id(payment)
    amount = get_payment_amount(payment)

    LOG.info('Payment %s for invoice %s processed' % (payment_id, invoice_id))
    if payment.execute({'payer_id': payer_id}):
        sale_id = get_sale_id(payment)
        sale = paypalrestsdk.Sale.find(sale_id)

        try:
            existing_transaction = Transaction.objects.get(external_id=payment_id,
                                                           gateway=gateway)
            transaction_id = existing_transaction.id
        except Transaction.DoesNotExist:
            serializer_data = {'invoice': invoice_id,
                               'external_id': payment_id,
                               'amount': amount.total,
                               'currency': amount.currency,
                               'gateway': gateway.pk,
                               'fee': sale.transaction_fee.value,
                               'date_initiated': payment.update_time,
                               'extra': None,
                               'status': TransactionStatus.SUCCESS}
            tr_ser = AddTransactionSerializer(data=serializer_data)
            if tr_ser.is_valid(raise_exception=False):
                new_transaction = tr_ser.save()
                transaction_id = new_transaction.id
            else:
                raise gateway_exceptions.InvoicePaymentException(message=tr_ser.errors, invoice_id=invoice_id)
        else:
            # Update the transaction status only
            existing_transaction.status = TransactionStatus.SUCCESS
            existing_transaction.save(update_fields=['status'])

        activity_helper.start_generic_activity(
            category_name='paypal', activity_class='paypal payment',
            invoice_id=invoice_id
        )

        invoice_add_payment.delay(invoice_id=invoice_id,
                                  amount=amount.total,
                                  currency_code=amount.currency,
                                  transaction_id=transaction_id)

        activity_helper.end_activity()
    else:
        raise gateway_exceptions.InvoicePaymentException(message=format_error(payment), invoice_id=invoice_id)

    gateway.log_callback(external_id=payment_id,
                         status=payment.state,
                         data='',
                         error=False,
                         error_code='',
                         error_info='')

    return HttpResponseRedirect(get_invoice_url(invoice_id))
示例#10
0
def callback(request):
    if not PayUUtils.validate_open_payu_signature(
            open_payu_signature=request.headers.get('OpenPayu-Signature',
                                                    None),
            body=request.body,
    ):
        raise gateway_exceptions.GatewayException(
            'Did not receive or received invalid OpenPayu-Signature')
    gateway = Gateway.objects.get(name='payu')
    order_details = request.data.get('order', None)
    if not order_details:
        raise Exception('No order details')
    external_id = order_details.get('orderId')
    invoice_id = PayUUtils.get_invoice_id_from_external_order_id(
        external_order_id=order_details.get('extOrderId'))
    transaction_status = order_details.get('status')
    total_amount = PayUUtils.get_payu_amount_in_fleio_amount(
        amount=order_details.get('totalAmount'))
    if order_details.get('status') == PayUTransactionStatus.canceled:
        # process refund for pre auth transaction
        existing_transaction = Transaction.objects.filter(
            external_id=external_id,
            gateway=gateway,
            refunded_transaction__isnull=True).first()
        if not existing_transaction:
            raise gateway_exceptions.GatewayException(
                'Could not process cancellation notification because there is no transaction to refund'
            )
        new_refund_transaction = {
            'invoice': invoice_id,
            'external_id': external_id,
            'amount': str(total_amount),
            'currency': order_details.get('currencyCode'),
            'gateway': gateway.pk,
            'fee': gateway.get_fee(amount=decimal.Decimal(total_amount)),
            'date_initiated': utcnow(),
            'extra': {},
            'refunded_transaction': existing_transaction.pk,
            'status': TransactionStatus.REFUNDED
        }
        transaction_serializer = AddTransactionSerializer(
            data=new_refund_transaction)
        if transaction_serializer.is_valid(raise_exception=False):
            new_transaction = transaction_serializer.save()
            activity_helper.start_generic_activity(
                category_name='payu',
                activity_class='payu payment refund',
                invoice_id=existing_transaction.invoice.id)

            invoice_refund_payment.delay(
                transaction_id=existing_transaction.id,
                amount=total_amount,
                to_client_credit=False,
                new_transaction_id=new_transaction.pk)

            activity_helper.end_activity()
        else:
            LOG.error('PayU transaction error: {}'.format(
                transaction_serializer.errors))
            raise gateway_exceptions.GatewayException(
                'Could not process cancellation notification because serialized data is invalid'
            )
        return Response({'detail': 'Ok'})
    # process pre-auth, confirmation notifications
    existing_transaction = Transaction.objects.filter(
        external_id=external_id,
        gateway=gateway,
        refunded_transaction__isnull=True).first()
    if existing_transaction:
        # Update the transaction status and mark invoice as paid (still needs capture if automatic capture is not
        # enabled in PayU) if client successfully made the payment
        existing_transaction.status = PayUTransactionStatus.to_transaction_model_status.get(
            transaction_status)
        existing_transaction.save(update_fields=['status'])
        if (transaction_status
                == PayUTransactionStatus.waiting_for_confirmation
                or (transaction_status == PayUTransactionStatus.completed
                    and existing_transaction.invoice
                    and existing_transaction.invoice.is_unpaid())):
            activity_helper.start_generic_activity(
                category_name='payu',
                activity_class='payu payment',
                invoice_id=invoice_id)
            invoice_add_payment.delay(
                invoice_id=invoice_id,
                amount=total_amount,
                currency_code=order_details.get('currencyCode'),
                transaction_id=existing_transaction.id)
            activity_helper.end_activity()
        return Response({'detail': 'Ok'})
    elif transaction_status == PayUTransactionStatus.pending:
        serializer_data = {
            'invoice':
            invoice_id,
            'external_id':
            external_id,
            'amount':
            total_amount,
            'currency':
            order_details.get('currencyCode'),
            'gateway':
            gateway.pk,
            'fee':
            gateway.get_fee(amount=decimal.Decimal(total_amount)),
            'date_initiated':
            order_details.get('orderCreateDate'),
            'extra': {},
            'status':
            PayUTransactionStatus.to_transaction_model_status.get(
                transaction_status)
        }
        add_transaction_serializer = AddTransactionSerializer(
            data=serializer_data)
        if add_transaction_serializer.is_valid(raise_exception=False):
            add_transaction_serializer.save()
        else:
            LOG.error('PayU transaction error: {}'.format(
                add_transaction_serializer.errors))
            raise gateway_exceptions.InvoicePaymentException(
                'Transaction error', invoice_id=invoice_id)
    return Response({'detail': 'Ok'})
示例#11
0
def refund(request):
    gateway = Gateway.objects.get(name='payu')
    transaction_id = request.query_params.get('transaction')
    transaction = Transaction.objects.get(id=transaction_id)
    invoice = transaction.invoice
    payu_client = PayUClient(invoice_id=invoice.id, request=request)
    if transaction.status == Transaction.TRANSACTION_STATUS.CONFIRMED:
        # do a refund for transaction status confirmed
        try:
            response = payu_client.refund(
                transaction_external_id=transaction.external_id)
        except Exception as e:
            raise gateway_exceptions.GatewayException(
                'Invalid payu refund action: {}'.format(str(e)))
        if response.status_code == 200 or response.status_code == 201:
            response_text = json.loads(response.text)
            refund_data = response_text.get('refund', {})
            new_refund_transaction = {
                'invoice':
                invoice.id,
                'external_id':
                transaction.external_id,
                'amount':
                str(
                    PayUUtils.get_payu_amount_in_fleio_amount(
                        refund_data.get('amount'))),
                'currency':
                refund_data.get('currencyCode'),
                'gateway':
                gateway.pk,
                'fee':
                gateway.get_fee(amount=decimal.Decimal(transaction.amount)),
                'date_initiated':
                refund_data.get('creationDateTime'),
                'extra': {
                    'refundId': refund_data.get('refundId'),
                    'extRefundId': refund_data.get('extRefundId'),
                },
                'refunded_transaction':
                transaction.pk,
                'status':
                TransactionStatus.REFUNDED
            }
            transaction_serializer = AddTransactionSerializer(
                data=new_refund_transaction)
            if transaction_serializer.is_valid(raise_exception=False):
                new_transaction = transaction_serializer.save()
                activity_helper.start_generic_activity(
                    category_name='payu',
                    activity_class='payu payment refund',
                    invoice_id=invoice.id)

                invoice_refund_payment.delay(
                    transaction_id=transaction_id,
                    amount=PayUUtils.get_payu_amount_in_fleio_amount(
                        refund_data.get('amount')),
                    to_client_credit=False,
                    new_transaction_id=new_transaction.pk)

                activity_helper.end_activity()
            else:
                LOG.error('PayU transaction error: {}'.format(
                    transaction_serializer.errors))
                raise gateway_exceptions.InvoicePaymentException(
                    'Transaction error', invoice_id=invoice.id)
            return Response({'detail': 'Ok'})
    else:
        # do a cancellation request for when transaction was not yet confirmed
        try:
            payu_client.cancel(transaction_external_id=transaction.external_id)
        except Exception as e:
            raise gateway_exceptions.GatewayException(
                'Invalid payu refund action: {}'.format(str(e)))
        return Response({'detail': 'Ok'})
    response_text = json.loads(response.text)
    status = response_text.get('status')
    status_desc = status.get('statusDesc')
    raise Exception('Could not make capture action. {}'.format(
        status_desc if status_desc else ''))