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