Beispiel #1
0
    def get_fee(self):
        """ Return the fee that is withheld on this payment.

        This is depended on the payment method. Actual percentages are
        stored in the client properties
        """
        if not hasattr(settings, 'DOCDATA_FEES'):
            raise PaymentException("Missing fee DOCDATA_FEES")
        fees = settings.DOCDATA_FEES
        if not fees.get('transaction'):
            raise PaymentException("Missing fee 'transaction'")
        if not fees.get('payment_methods'):
            raise PaymentException("Missing fee 'payment_methods'")
        transaction_fee = fees['transaction']

        pm = self.default_pm.lower()

        try:
            pm_fee = fees['payment_methods'][pm]
        except KeyError:
            raise PaymentException("Missing fee {0}".format(pm))

        if '%' in str(pm_fee):
            part = Decimal(pm_fee.replace('%', '')) / 100
            return self.order_payment.amount.amount * part
        else:
            return pm_fee + transaction_fee
Beispiel #2
0
    def create_payment(self):
        """
        Create a new payment
        """

        if self.order_payment.amount.currency != XOF:
            raise PaymentException(
                "Can only do Vitepay payments in XOF, Communauté Financière Africaine (BCEAO)."
            )

        if self.merchant != 'vitepay':
            raise PaymentException(
                "Not a VitePay order-payment. Merchant is {0}".format(
                    self.merchant))

        payment = self.MODEL_CLASSES[0](order_payment=self.order_payment)
        # Amount on the payment should be in CFA * 100
        payment.amount_100 = int(self.order_payment.amount.amount * 100)
        payment.description = "Thanks for your donation!"
        payment.callback_url = self._get_callback_url()
        payment.return_url = '{0}/orders/{1}/success'.format(
            get_current_host(), self.order_payment.order.id)

        payment.decline_url = '{0}/orders/{1}/failed'.format(
            get_current_host(), self.order_payment.order.id)

        payment.cancel_url = '{0}/orders/{1}/failed'.format(
            get_current_host(), self.order_payment.order.id)

        payment.order_id = 'opc-{0}'.format(self.order_payment.id)
        payment.save()
        return payment
Beispiel #3
0
    def get_authorization_action(self):

        client = gateway.DocdataClient(self.credentials, self.live_mode)

        # Get the language that the user marked as his / her primary language
        # or fallback on the default LANGUAGE_CODE in settings

        try:
            client_language = self.order_payment.order.user.primary_language
        except AttributeError:
            client_language = properties.LANGUAGE_CODE

        if self.order_payment.payment_method == 'docdataDirectdebit':
            try:
                client.start_remote_payment(
                    order_key=self.payment.payment_cluster_key,
                    payment=self.payment,
                    payment_method='SEPA_DIRECT_DEBIT')
                return {'type': 'success'}
            except DocdataPaymentException as i:
                raise PaymentException(i)
        else:
            return_url_base = get_current_host()
        try:
            url = client.get_payment_menu_url(
                order_key=self.payment.payment_cluster_key,
                credentials=self.credentials,
                order_id=self.order_payment.order_id,
                return_url=return_url_base,
                client_language=client_language,
            )
        except DocdataPaymentException as i:
            raise PaymentException(i)

        default_act = False
        if self.payment.ideal_issuer_id:
            default_act = True
        if self.payment.default_pm == 'paypal_express_checkout':
            default_act = True

        url = client.get_payment_menu_url(
            order_key=self.payment.payment_cluster_key,
            order_id=self.order_payment.order_id,
            credentials=self.credentials,
            return_url=return_url_base,
            client_language=client_language,
        )

        default_act = False
        if self.payment.ideal_issuer_id:
            default_act = True

        params = {
            'default_pm': self.payment.default_pm,
            'ideal_issuer_id': self.payment.ideal_issuer_id,
            'default_act': default_act
        }
        url += '&' + urlencode(params)
        return {'type': 'redirect', 'method': 'get', 'url': url}
Beispiel #4
0
    def test_check_payment_status(self):
        request = self.request_factory.post('/')
        request.user = MockUser()

        with mock.patch.object(DocdataPaymentAdapter,
                               'check_payment_status') as check_payment_status:
            response = self.order_payment_admin.check_status(
                request, self.order_payment.pk)
            self.assertEqual(response.status_code, 302)
            check_payment_status.assert_called()
            # Pretend the adapter changed payment status to 'settled'
            self.payment.status = 'settled'
            self.payment.save()
            self.assertEqual(self.order_payment.order.status, 'success')

        with mock.patch.object(self.order_payment_admin,
                               'message_user') as message_mock:
            with mock.patch.object(
                    DocdataPaymentAdapter,
                    'check_payment_status') as check_payment_status:
                check_payment_status.side_effect = PaymentException(
                    'Docdata just exploded!')
                response = self.order_payment_admin.check_status(
                    request, self.order_payment.pk)
                self.assertEqual(response.status_code, 302)
                message_mock.assert_called_with(
                    request,
                    'Error checking status Docdata just exploded!',
                    level='WARNING')
                check_payment_status.assert_called()
Beispiel #5
0
    def _get_adapter(self):
        # FIXME: Check if payment_method is set.
        provider_name = re.sub('([a-z]+)([A-Z][a-z]+)', r'\1',
                               self.order_payment.payment_method)
        method_name = re.sub('([a-z]+)([A-Z][a-z]+)', r'\2',
                             self.order_payment.payment_method)
        app_name = 'payments_' + provider_name

        # First try to load the specific profile adapter
        class_name = provider_name.title() + method_name + 'PaymentAdapter'
        class_path = 'bluebottle.' + app_name + '.adapters.' + class_name
        try:
            adapter_class = get_class(class_path)
        except GetClassError:
            # Now try to load the generic provider adapter
            class_name = provider_name.title() + 'PaymentAdapter'
            class_path = 'bluebottle.' + app_name + '.adapters.' + class_name
            try:
                adapter_class = get_class(class_path)
            except GetClassError:
                raise PaymentException(
                    "Couldn't find an adapter for payment method '{0}'".format(
                        self.order_payment.payment_method))

        adapter = adapter_class(self.order_payment)
        return adapter
Beispiel #6
0
 def create_payment(self):
     """
     Create a new payment
     """
     payment = self.MODEL_CLASSES[0](order_payment=self.order_payment)
     payment.product_id = self.credentials['product_id']
     payment.pay_item_id = self.credentials['item_id']
     # Amount on the payment should be in kobo/cents
     payment.amount = int(self.order_payment.amount.amount * 100)
     if self.order_payment.amount.currency != NGN:
         raise PaymentException(
             "Can only do Interswitch payments in Nigerian Naira (NGN).")
     payment.site_redirect_url = '{0}/payments_interswitch/payment_response/{1}'.format(
         get_current_host(), self.order_payment.id)
     tenant = connection.tenant
     payment.site_name = str(tenant.domain_url)
     try:
         payment.cust_id = self.order_payment.user.id
         payment.cust_name = unicode(self.order_payment.user.full_name)
     except AttributeError:
         # Anonymous order
         pass
     payment.txn_ref = '{0}-{1}'.format(tenant.name, self.order_payment.id)
     payment.save()
     return payment
Beispiel #7
0
 def start_payment(self):
     # Throw some errors
     op = self.order_payment
     if op.id % 2:
         raise PaymentException('The horror, the horror')
     else:
         op.started()
         op.settled()
         op.save()
     return True
Beispiel #8
0
 def status_update(self, authenticity, success, failure):
     """
     Check the received status update and update payment status accordingly.
     Note: We can't check status from our site. We have to rely on VitePay sending
     us an update.
     """
     if authenticity != self._create_update_hash():
         raise PaymentException('Authenticity incorrect.')
     elif success and failure:
         raise PaymentException(
             'Both failure and succes are set. Not sure what to do.')
     elif not success and not failure:
         raise PaymentException(
             'Both failure and succes are unset. Not sure what to do.')
     elif failure:
         self.payment.status = StatusDefinition.FAILED
     else:
         self.payment.status = StatusDefinition.SETTLED
     self.payment.save()
     return True
Beispiel #9
0
    def create_payment(self):
        try:
            can_pledge = self.order_payment.user.can_pledge
        except AttributeError:
            can_pledge = False

        if not can_pledge:
            raise PaymentException('User does not have permission to pledge')
        # A little hacky but we can set the status to pledged here
        if self.order_payment.status == StatusDefinition.CREATED:
            self.order_payment.pledged()
            self.order_payment.save()
Beispiel #10
0
    def create_payment(self):
        """
        Create a new payment
        """
        self.card_data = self.order_payment.card_data

        if 'mobile' not in self.card_data:
            raise PaymentException('Mobile is required')

        payment = self.MODEL_CLASSES[0](order_payment=self.order_payment,
                                        mobile=self.card_data['mobile'])
        payment.amount = int(self.order_payment.amount.amount)
        if str(self.order_payment.amount.currency) != 'USD':
            raise PaymentException(
                'You should pick USD as a currency to use Telesom/Zaad')

        payment.currency = str(self.order_payment.amount.currency)
        payment.narration = "Donation {0}".format(self.order_payment.id)

        gateway = TelesomClient(merchant_id=self.credentials['merchant_id'],
                                merchant_key=self.credentials['merchant_key'],
                                username=self.credentials['username'],
                                password=self.credentials['password'],
                                api_domain=self.credentials['api_domain'])
        tenant = connection.tenant
        payment.description = '{0}-{1}'.format(tenant.name,
                                               self.order_payment.id)

        response = gateway.create(mobile=payment.mobile,
                                  amount=payment.amount,
                                  description=payment.description)
        payment.transaction_reference = response['payment_id']
        payment.status = response['status']
        payment.response = response['response']
        payment.save()

        self.payment = payment
        # Check status right away so the payment gets processed
        self.check_payment_status()
        return payment
Beispiel #11
0
    def create_payment(self):
        """
        Have some basic criteria that might fail so we can check our error parsing.
        """
        if self.order_payment.amount.amount < 10:
            raise PaymentException(
                "Amount for Mock payments should be greater then 10")

        user_data = self.get_user_data()
        pattern = re.compile(r'\W')
        if pattern.findall(user_data['first_name']):
            raise PaymentException(
                "First name '{0}' has got illegal characters.".format(
                    user_data['first_name']))

        if len(user_data['last_name']) > 30:
            raise PaymentException("Last name too long: '{0}'".format(
                user_data["last_name"]))

        # Now just create the payment.
        payment = self.MODEL_CLASSES[0](order_payment=self.order_payment)
        payment.save()
        return payment
Beispiel #12
0
    def get_authorization_action(self):

        if self.payment.status == 'settled':
            return {'type': 'success'}
        if self.payment.status == 'started':
            return {
                'type': 'process',
                'payload': {
                    'account_number': self.payment.account_number,
                    'business_number': self.payment.business_number,
                    'amount': int(float(self.payment.amount))
                }
            }
        raise PaymentException('Payment could not be verified yet.')
Beispiel #13
0
    def create_payment(self):
        """
        Create a new payment
        """
        self.card_data = self.order_payment.card_data

        if 'mobile' not in self.card_data:
            raise PaymentException('Mobile is required')

        mobile = self.card_data['mobile']
        if mobile[0:2] == '07':
            mobile = '+256' + mobile[1:]

        payment = BeyonicPayment(order_payment=self.order_payment,
                                 mobile=mobile)
        payment.amount = int(self.order_payment.amount.amount)
        payment.currency = str(self.order_payment.amount.currency)

        payment.metadata = {'order_id': self.order_payment.id}

        if not self.credentials['live']:
            # Testing currency
            payment.currency = 'BXC'

        tenant = connection.tenant
        payment.description = '{0}-{1}'.format(tenant.name,
                                               self.order_payment.id)

        beyonic.api_key = self.credentials['merchant_key']
        callback_url = '{0}/payments_beyonic/update/'.format(
            get_current_host())
        response = beyonic.CollectionRequest.create(
            phonenumber=payment.mobile,
            amount=payment.amount,
            currency=payment.currency,
            description=payment.description,
            callback_url=callback_url,
            metadata=payment.metadata,
            send_instructions=True)

        payment.transaction_reference = response['id']
        payment.status = self.status_mapping[response['status']]
        payment.response = response
        payment.save()

        self.payment = payment
        # Check status right away so the payment gets processed
        self.check_payment_status()
        return payment
Beispiel #14
0
    def create_payment(self):
        self.card_data = self.order_payment.card_data

        if not {'card_number', 'expiry_month', 'expiry_year', 'cvv'}.issubset(
                self.card_data):
            logger.warn('payment_tracer: {}, '
                        'event: payment.flutterwave.invalid_credentials,'
                        'card_number: {}, '
                        'expiry_month: {}, '
                        'expiry_year: {}, '
                        'cvv: {}'.format(
                            self.payment_tracer,
                            getattr(self.card_data, 'card_number', None),
                            getattr(self.card_data, 'expiry_month', None),
                            getattr(self.card_data, 'expiry_year', None),
                            getattr(self.card_data, 'cvv', None)))
            raise PaymentException(
                'Card number, expiry month/year and cvv is required')

        payment = FlutterwavePayment(order_payment=self.order_payment,
                                     card_number="**** **** **** " +
                                     self.card_data['card_number'][-4:])
        if 'pin' in self.card_data and self.card_data['pin']:
            payment.auth_model = 'PIN'
        else:
            payment.auth_model = 'VBVSECURECODE'
        payment.amount = str(self.order_payment.amount.amount)
        payment.currency = str(self.order_payment.amount.currency)
        payment.customer_id = str(self.order_payment.user or 1)
        payment.narration = "Donation {0}".format(self.order_payment.id)
        payment.response_url = '{0}/payments_flutterwave/payment_response/{1}'.format(
            get_current_host(), self.order_payment.id)
        tenant = connection.tenant
        payment.site_name = str(tenant.domain_url)
        try:
            payment.cust_id = self.order_payment.user.id
            payment.cust_name = unicode(self.order_payment.user.full_name)
        except AttributeError:
            # Anonymous order
            pass
        payment.txn_ref = '{0}-{1}'.format(tenant.name, self.order_payment.id)
        payment.save()
        self.payment_logger.log(
            payment, 'info', 'payment_tracer: {}, '
            'event: payment.flutterwave.create_payment.success'.format(
                self.payment_tracer))
        return payment
Beispiel #15
0
    def create_account_number(self, project):
        client = self._get_client()

        response = client.create_payment_account(
            transaction_account_type=1,
            transaction_account_name=project.slug,
            transaction_account_manager=self.credentials['channel_manager']
        )

        try:
            account_number = response['content']['transaction_account_number']

            LipishaProject.objects.create(
                project=project,
                account_number=account_number
            )
        except KeyError:
            raise PaymentException("Could not create an account number at Lipisha")
Beispiel #16
0
    def get_authorization_action(self):
        """
        Handle payment
        """

        if self.payment.status == 'settled':
            return {'type': 'success'}
        elif self.payment.status == 'started':
            return {
                'type': 'step2',
                'payload': {
                    'method': 'telesom-sms',
                    'text': 'Confirm the payment by SMS'
                }
            }
        else:
            reply = self.payment.update_response
            raise PaymentException(
                "Error processing Telesom/Zaad transaction. {0}".format(reply))
Beispiel #17
0
    def check_payment_status(self):
        transaction_reference = self.payment.transaction_reference
        card_data = self.order_payment.card_data or {}
        if 'otp' in card_data:
            otp = card_data['otp']
            data = {
                "otp": otp,
                "otpTransactionIdentifier": self.payment.transaction_reference,
                "country": "NG"
            }
            logger.info(
                'payment_tracer: {}, '
                'event: payment.flutterwave.payment_status.otp_validate.request, '
                'flutterwave_request: {}'.format(self.payment_tracer, data))
            r = self.flw.card.validate(data)
            response = json.loads(r.text)
            if response['data']['responsecode'] in SUCCESS_RESPONSECODES:
                self.order_payment.set_authorization_action(
                    {'type': 'success'})
                self.payment.status = 'settled'
            else:
                self.payment.status = 'failed'
        else:
            r = self.flw.card.verifyCharge(
                transactionRef=transaction_reference, country='NG')
            response = json.loads(r.text)
            if response['data']['responsecode'] in SUCCESS_RESPONSECODES:
                self.payment.status = 'settled'
            else:
                self.payment.status = 'failed'

        logger.info('payment_tracer: {}, '
                    'transaction_reference: {}, '
                    'event: payment.flutterwave.payment_status, '
                    'flutterwave_response: {}'.format(self.payment_tracer,
                                                      transaction_reference,
                                                      response['data']))
        self.payment.update_response = response
        self.payment.save()

        if self.payment.status == 'failed':
            raise PaymentException(response['data']['responsemessage'])
Beispiel #18
0
    def check_payment_status(self):
        # If we have a transaction reference, then use that
        if self.payment.transaction_reference and self.payment.transaction_reference != '4':
            response = self.client.get_transactions(
                transaction_type='Payment',
                transaction=self.payment.transaction_reference
            )
        else:
            response = self.client.get_transactions(
                transaction_type='Payment',
                transaction_reference=self.order_payment.id
            )

        self.payment.update_response = json.dumps(response)
        data = response['content']

        if len(data) == 0:
            self.payment.status = StatusDefinition.FAILED
            self.payment.save()
            raise PaymentException('Payment could not be verified yet. Payment not found.')
        else:
            payment = data[0]
            # Make sure we set the right properties
            payment['transaction_reference'] = payment['transaction']
            for k, v in payment.iteritems():
                setattr(self.payment, k, v)
            if self.payment.transaction_amount != self.payment.order_payment.amount.amount:
                # Update donation amount based on the amount registered at Lipisha
                amount = Money(self.payment.transaction_amount, 'KES')
                donation = self.payment.order_payment.order.donations.all()[0]
                self.payment.order_payment.amount = amount
                donation.amount = amount
                donation.save()
                self.payment.order_payment.save()

        self.payment.status = self._get_mapped_status(self.payment.transaction_status)

        if self.payment.status in ['settled', 'authorized']:
            self.order_payment.set_authorization_action({'type': 'success'})

        self.payment.save()
Beispiel #19
0
    def get_authorization_action(self):
        """
        Handle payment
        """

        if self.payment.status == 'settled':
            return {'type': 'success'}
        elif self.payment.status == 'started':
            return {
                'type': 'step2',
                'payload': {
                    'method': 'beyonic-sms',
                    'text': 'Confirm the payment on your mobile'
                }
            }
        else:
            try:
                reply = self.payment.update_response['error_message']
            except KeyError:
                reply = self.payment.update_response
            raise PaymentException(
                "Error processing AirTel/MTN transaction. {0}".format(reply))
Beispiel #20
0
 def _get_payment_url(self):
     """
     Get payment url from VitePay to redirect the user to.
     """
     data = {
         "payment": {
             "language_code": "fr",
             "currency_code": "XOF",
             "country_code": "ML",
             "order_id": self.payment.order_id,
             "description": self.payment.description,
             "amount_100": self.payment.amount_100,
             "return_url": self.payment.return_url,
             "decline_url": self.payment.decline_url,
             "cancel_url": self.payment.cancel_url,
             "callback_url": self.payment.callback_url,
             "p_type": "orange_money",
         },
         "redirect": 0,
         "api_key": self.credentials['api_key'],
         "hash": self._create_payment_hash()
     }
     url = self.credentials['api_url']
     headers = {'Content-Type': 'application/json'}
     response = requests.post(url,
                              data=json.dumps(data),
                              headers=headers,
                              verify=False)
     if response.status_code == 200:
         self.payment.payment_url = response.content
     else:
         raise PaymentException('Error creating payment: {0}'.format(
             response.content))
     self.payment.status = StatusDefinition.STARTED
     self.payment.save()
     return response.content
Beispiel #21
0
    def create(self, mobile='', amount=0, description=''):
        """
        Create the payment in Telesom.
        """
        # We should not use actual IP address.
        ip = '::1'
        date = timezone.now().strftime('%d/%m/%Y')
        username = self.username
        password = self.password
        account = self.merchant_id
        unique_key = self.merchant_key

        # From PHP:
        # $msg = $username.$password."::1".$merchant.$uniquekey. $dates.$mobile.$amount.$description;
        hash = "{0}{1}{2}{3}{4}{5}{6}{7}{8}".format(username, password, ip,
                                                    account, unique_key, date,
                                                    mobile, amount,
                                                    description)
        key = hashlib.md5(hash).hexdigest()

        if self.testing:
            reply = self.client.service.PaymentRequest(
                pMsisdn=mobile,
                pAmount=amount,
                Category=description,
                MerchantID=self.merchant_id,
                hashkey=key)
        else:
            reply = self.client.service.PaymentRequest(
                Subscriber=mobile,
                Amount=amount,
                Account=self.merchant_id,
                Description=description,
                Key=key)

        # Requests (including typos, please leave as is)
        # ------------------
        # 2001! Success, Waiting Confirmation !100
        # 400!Error: connect ECONNREFUSED!
        # 400!Error: connect Unknown system errno 10056!
        # 4005! Insufficient Payer Account funds.!
        # 4005! Invalid Payee Account Info. !
        # 4005! Invalid Payee Account relation. !
        # 4005! OOPS ! , Sorry your request could not be complete this time !!
        # 4005! There is somthing got wrong, please try again !
        # 4005!!
        # 4005!Payer Account Does not Exist.!
        # 5000!Account Locked, You can Try again after 24 Hours!-1
        # 5001! Invalid Username/Password/Hashkey Try Again!-1
        # 5002!Error Occured Cannot Proccess Payment!-1
        # 5004!Authentication Error!-1

        res = reply.split('!')
        if res[0] == '2001':
            return {
                'response': reply,
                'status': 'created',
                'payment_id': res[2]
            }
        else:
            raise PaymentException(
                "Could not start Telesom/Zaad transaction. {0}".format(reply))
Beispiel #22
0
 def get_fee(self):
     if not isinstance(self, Payment):
         raise PaymentException("get_fee() not implemented for "
                                "{0}".format(self.__class__.__name__))
Beispiel #23
0
    def get_authorization_action(self):
        pin = ''
        cvv = ''
        if 'pin' in self.card_data:
            pin = self.card_data['pin']
        if 'cvv' in self.card_data:
            cvv = self.card_data['cvv']

        if not {'card_number', 'expiry_month', 'expiry_year', 'cvv'}.issubset(
                self.card_data):
            logger.warn('payment_tracer: {}, '
                        'event: payment.flutterwave.invalid_credentials,'
                        'card_number: {}, '
                        'expiry_month: {}, '
                        'expiry_year: {}, '
                        'cvv: {}'.format(
                            self.payment_tracer,
                            getattr(self.card_data, 'card_number', None),
                            getattr(self.card_data, 'expiry_month', None),
                            getattr(self.card_data, 'expiry_year', None),
                            getattr(self.card_data, 'cvv', None)))
            raise PaymentException(
                'Card number, expiry month/year and cvv is required')

        data = {
            "amount": self.payment.amount,
            "currency": self.payment.currency,
            "authModel": self.payment.auth_model,
            "cardNumber": self.card_data['card_number'],
            "cvv": cvv,
            "expiryMonth": self.card_data['expiry_month'],
            "expiryYear": self.card_data['expiry_year'],
            "pin": pin,
            "customerID": self.payment.customer_id,
            "narration": self.payment.narration,
            "responseUrl": self.payment.response_url,
            "country": self.payment.country
        }

        logger.info(
            'payment_tracer: {}, '
            'event: payment.flutterwave.get_authorization_action.request'
            'amount: {}, '
            'currency: {}, '
            'authModel: {}, '
            'cardNumber: {}, '
            'cvv: {}, '
            'expiryMonth: {}, '
            'expiryYear: {}, '
            'pin: {}, '
            'customerId: {}, '
            'narration: {}, '
            'responseUrl: {}, '
            'country: {}'.format(
                self.payment_tracer, self.payment.amount,
                self.payment.currency, self.payment.auth_model,
                self.card_data['card_number'][-4:], cvv,
                self.card_data['expiry_month'], self.card_data['expiry_year'],
                pin, self.payment.customer_id, self.payment.narration,
                self.payment.response_url, self.payment.country))
        r = self.flw.card.charge(data)
        if r.status_code == 500:
            logger.warn('payment_tracer: {}, '
                        'event: payment.flutterwave.error.500, '
                        'flutterwave_response: {}'.format(
                            self.payment_tracer, r.text))
            raise PaymentException(
                'Flutterwave could not confirm your card details, please try again.'
            )
        response = json.loads(r.text)

        self.payment.response = "{}".format(r.text)
        self.payment.save()

        logger.info(
            'payment_tracer: {}, '
            'event: payment.flutterwave.get_authorization_action.response, '
            'flutterwave_response: {}'.format(self.payment_tracer, r.text))

        if response['status'] == u'error':
            logger.warn(
                'payment_tracer: {}, '
                'event: payment.flutterwave.get_authorization_action.error, '
                'flutterwave_response: {}'.format(self.payment_tracer,
                                                  response['data']))
            raise PaymentException('Flutterwave error: {0}'.format(
                response['data']))

        if response['data']['responsecode'] in SUCCESS_RESPONSECODES:
            self.payment.status = 'authorized'
            self.payment.save()
            logger.info(
                'payment_tracer: {}, '
                'event: payment.flutterwave.get_authorization_action.authorized, '
                'response: {}'.format(self.payment_tracer, response['data']))
            return {'type': 'success'}

        if response['data']['responsecode'] == '02':
            if 'authurl' in response['data'] and response['data']['authurl']:
                return {
                    'method': 'get',
                    'url': response['data']['authurl'],
                    'type': 'redirect',
                    'payload': {
                        'method': 'flutterwave-otp',
                        'text': response['data']['responsemessage'],
                    }
                }
            else:
                return {
                    'type': 'step2',
                    'payload': {
                        'method': 'flutterwave-otp',
                        'text': response['data']['responsemessage']
                    }
                }

        logger.warn(
            'payment_tracer: {}, '
            'event: payment.flutterwave.get_authorization_action.error.start_payment '
            'flutterwave_response: {}'.format(self.payment_tracer,
                                              response['data']))
        raise PaymentException('Error starting payment: {0}'.format(
            response['data']['responsemessage']))