コード例 #1
0
 def perform_update(self, serializer):
     os_volume_backup = self.get_openstack_volume_backup()
     if serializer.is_valid(raise_exception=True):
         try:
             os_volume_backup.update(
                 name=serializer.validated_data.get('name'),
                 description=serializer.validated_data.get('description'))
         except Exception as e:
             del e  # unused
             handle(self.request,
                    message=_('Unable to update volume backup'))
         except APIBadRequest as e:
             raise APIBadRequest(str(e))
         else:
             # no notifications received after update, we need to sync this volume backup
             activity_helper.start_generic_activity(
                 category_name='volume_backup',
                 activity_class=
                 'volume backup extra details synchronization',
                 backup_id=os_volume_backup.id)
             sync_volume_backup_extra_details.delay(
                 volume_backup_id=os_volume_backup.volume_backup.id,
                 after_update=True)
             activity_helper.end_activity()
     return Response({'detail': _('Updating started')})
コード例 #2
0
 def create_end(self, data, region, timestamp):
     if 'volume_id' in data:
         activity_helper.start_generic_activity(
             category_name='volume',
             activity_class='volume extra details synchronization',
             volume_id=data['volume_id'])
         sync_volume_extra_details.delay(volume_id=data['volume_id'],
                                         region_name=region)
         activity_helper.end_activity()
     return super().create_or_update(data=data,
                                     region=region,
                                     timestamp=timestamp)
コード例 #3
0
 def create_or_update_end(self, data, region, timestamp):
     create_or_update = super().create_or_update(data=data, region=region, timestamp=timestamp)
     if 'backup_id' in data:
         volume_backup_id = data['backup_id']
     else:
         volume_backup_id = data['id']
     # sync incremental status of backup as soon as it is created because incremental flag is not received in
     # notifications
     activity_helper.start_generic_activity(
         category_name='volume_backup', activity_class='volume backup extra details synchronization',
         backup_id=volume_backup_id
     )
     sync_volume_backup_extra_details.delay(volume_backup_id=volume_backup_id)
     activity_helper.end_activity()
     return create_or_update
コード例 #4
0
def refund(request):
    transaction_id = request.data.get('transaction')
    transaction = Transaction.objects.get(id=transaction_id, gateway__name='paypal')
    invoice = transaction.invoice
    payment_id = transaction.external_id

    configure()

    payment = get_payment(payment_id)
    sale_id = get_sale_id(payment)
    sale = paypalrestsdk.Sale.find(sale_id)
    sale.refund({
        'amount': {
            'total': str(transaction.amount),
            'currency': transaction.currency.code
        }})

    # update transaction and invoice status
    activity_helper.start_generic_activity(
        category_name='paypal', activity_class='paypal payment refund',
        invoice_id=invoice.pk
    )

    with db_transaction.atomic():
        new_transaction = Transaction.objects.create(invoice=invoice.pk,
                                                     external_id=payment_id,
                                                     amount=transaction.amount,
                                                     currency=transaction.currency.pk,
                                                     gateway=transaction.gateway.pk,
                                                     fee=0,
                                                     date_initiated=utcnow(),
                                                     extra='',
                                                     refunded_transaction=transaction.pk,
                                                     status=TransactionStatus.SUCCESS)

    db_transaction.on_commit(lambda: invoice_refund_payment.delay(transaction_id=transaction.id,
                                                                  amount=transaction.amount,
                                                                  to_client_credit=False,
                                                                  new_transaction_id=new_transaction.id))

    activity_helper.end_activity()

    return {'status': 'ok'}
コード例 #5
0
def run():
    lock_file = getattr(settings, 'PROCESS_CLIENT_CRON_LOCK_FILE', '/var/fleio/process_client_cron_lock_file.pid')
    try:
        fp = open(lock_file, 'a+')
    except FileNotFoundError:
        LOG.error('Could not create or open {} lock file'.format(lock_file))
        return
    try:
        fcntl.flock(fp.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
    except IOError:
        LOG.error('**Process clients cron is already running**')
        return

    if settings.UPDATE_RELATIVE_PRICES_BEFORE_PROCESSING_CLIENTS:
        ExchangeRateManager.update_relative_prices()

    activity_helper.start_generic_activity(
        category_name='cron',
        activity_class='cron process clients',
    )

    resellers_enabled = staff_active_features.is_enabled('billing.reseller')

    for client in Client.objects.all():  # type: Client
        try:
            LOG.debug('Processing client {}'.format(client))

            reference_datetime = utcnow()
            client_operations = ClientOperations(client, reference_datetime=reference_datetime)

            if client.status == ClientStatus.active:
                client_operations.process_client_services()

            client_operations.process_cancellation_requests()

            # update client usage
            client_operations.update_usage()

            # the client is assigned to a suspended reseller, skip some processing
            skip = resellers_enabled and client.reseller_resources
            skip = skip and client.reseller_resources.service.client.status == ClientStatus.suspended

            if not skip:
                if client.status == ClientStatus.suspended:
                    # check if client should be resumed
                    if client_operations.evaluate_and_resume_if_enough_credit():
                        LOG.debug('Client resumed')
                elif client.status == ClientStatus.active:
                    # check if client should be suspended
                    if client_operations.evaluate_and_suspend_if_overdue():
                        LOG.debug('Client suspended')
                    else:
                        client_operations.evaluate_and_send_low_credit_notifications()

            if not skip:
                # if client suspended process possible services with suspend override
                if client.status == ClientStatus.suspended:
                    client_operations.process_services_with_suspend_override()

                client_operations.process_client_suspended_services()

            for message in client_operations.summary.get_formatted_summary():
                LOG.info(message)

        except Exception as e:
            LOG.exception('Error processing client {} - {}'.format(client, e))

    activity_helper.end_activity()
コード例 #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):
    request_body = request.body
    if not PayURoUtils.verify_hash(request_body):
        raise gateway_exceptions.GatewayException(
            _('Did not receive or received invalid signature.'))
    gateway = Gateway.objects.get(name='payuro')
    invoice_id = request.data.get('REFNOEXT', None)
    if not invoice_id:
        raise gateway_exceptions.GatewayException(
            _('Missing fleio invoice id.'))
    external_id = request.data.get('REFNO')
    total_amount = request.data.get('IPN_TOTALGENERAL', None)
    currency = request.data.get('CURRENCY')
    status = request.data.get('ORDERSTATUS')
    invoice = Invoice.objects.get(id=invoice_id)
    if 'TOKEN_HASH' in request.data:
        try:
            recurrent_payments_config = RecurringPayments.objects.create(
                client=invoice.client,
                active=True,
                token_hash=request.data['TOKEN_HASH'],
                ipn_cc_mask=request.data['IPN_CC_MASK'],
                ipn_cc_exp_date=request.data['IPN_CC_EXP_DATE'],
            )
            create_new_recurring_payments_ordering(
                client=recurrent_payments_config.client,
                gateway_app_name=PayURoConfig.name)
        except Exception as e:
            del e  # unused
            pass
    if status == PayUROOrderStatus.preauth:
        transaction_status = PayUROOrderStatus.to_fleio_transaction_status[
            PayUROOrderStatus.preauth]
        serializer_data = {
            'invoice': invoice_id,
            'external_id': external_id,
            'amount': total_amount,
            'currency': currency,
            'gateway': gateway.pk,
            'fee': gateway.get_fee(amount=decimal.Decimal(total_amount)),
            'date_initiated': request.data.get('SALEDATE'),
            'extra': {},
            'status': transaction_status
        }
        add_transaction_serializer = AddTransactionSerializer(
            data=serializer_data)
        if add_transaction_serializer.is_valid(raise_exception=False):
            db_transaction = add_transaction_serializer.save()
            activity_helper.start_generic_activity(
                category_name='payuro',
                activity_class='payuro payment',
                invoice_id=invoice_id)
            invoice_add_payment.delay(invoice_id=invoice_id,
                                      amount=total_amount,
                                      currency_code=currency,
                                      transaction_id=db_transaction.id)
            activity_helper.end_activity()

        else:
            LOG.error(
                _('PayU Ro transaction error: {}').format(
                    add_transaction_serializer.errors))
            raise gateway_exceptions.GatewayException('Add transaction error')

    ipn_response = PayURoUtils.build_ipn_response(params=request_body)
    return Response({'detail': ipn_response})
コード例 #11
0
def refund(request):
    gateway = Gateway.objects.get(name='payuro')
    transaction_id = request.query_params.get('transaction')
    transaction = Transaction.objects.get(id=transaction_id)
    invoice = transaction.invoice
    now = utcnow()
    data = {
        'MERCHANT': conf.merchant,
        'ORDER_REF': transaction.external_id,
        'ORDER_AMOUNT': str(transaction.amount),
        'ORDER_CURRENCY': transaction.currency.code,
        'IRN_DATE': now.strftime('%Y-%m-%d %H:%M:%S'),
        'AMOUNT': str(transaction.amount),
    }
    # TODO: from python 3.6 use **data instead of getting each value as keys are ordered in the dict
    order_hash = PayURoUtils.calculate_signature([
        data.get('MERCHANT'),
        data.get('ORDER_REF'),
        data.get('ORDER_AMOUNT'),
        data.get('ORDER_CURRENCY'),
        data.get('IRN_DATE'),
        data.get('AMOUNT')
    ])
    data['ORDER_HASH'] = order_hash
    response = requests.post(url=REFUND_ORDER_URL, data=data)
    if response.status_code == 200 or response.status_code == 201:
        response_text = response.text
        response_text = response_text.replace('<EPAYMENT>', '')
        response_params = response_text.split('|')
        order_ref = response_params[0]
        response_code = response_params[1]
        if response_code == '1':
            existing_transaction = Transaction.objects.filter(
                external_id=order_ref).first()
            if existing_transaction:
                new_refund_transaction = {
                    'invoice':
                    invoice.id,
                    'external_id':
                    transaction.external_id,
                    'amount':
                    str(transaction.amount),
                    'currency':
                    transaction.currency.code,
                    'gateway':
                    gateway.pk,
                    'fee':
                    gateway.get_fee(
                        amount=decimal.Decimal(transaction.amount)),
                    'date_initiated':
                    now,
                    'extra': {},
                    '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='payuro',
                        activity_class='payuro payment refund',
                        invoice_id=invoice.id)

                    invoice_refund_payment.delay(
                        transaction_id=transaction_id,
                        amount=transaction.amount,
                        to_client_credit=False,
                        new_transaction_id=new_transaction.pk)

                    activity_helper.end_activity()
                else:
                    LOG.error(
                        _('PayU Ro transaction error: {}').format(
                            transaction_serializer.errors))
                    raise gateway_exceptions.GatewayException(
                        _('Transaction error {}').format(
                            transaction_serializer.errors))

            else:
                raise gateway_exceptions.GatewayException(
                    _('Could not find existing transaction to mark as captured in db.'
                      ))
        else:
            raise gateway_exceptions.GatewayException(
                _('Could not perform capture action. Details: {}').format(
                    REFUND_ERROR_CODE_MEANINGS.get(response_code)))
    else:
        raise gateway_exceptions.GatewayException(
            _('Error when making request to capture transaction.'))
    return Response({'detail': _('Ok')})
コード例 #12
0
ファイル: payu.py プロジェクト: PIPONCHOV/backendfleio-test
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'})
コード例 #13
0
ファイル: payu.py プロジェクト: PIPONCHOV/backendfleio-test
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 ''))