Exemple #1
0
    def retrieve(self, auth_details, charge_type=None, gateway_ref=None,
        merchant_ref=None, use_merchant_ref=False, ping_url=None,
        source_type=None):
        """
        Performs the same actions as it's base class but automatically creates
        the right type of charge instance based on the source_type param.
        Kwargs:
            source_type: The type of charge to instantiate. Default is CARD.
        """
        print('source_type')
        print(source_type)
        if source_type == CARD:
            charge = CardCharge.retrieve(auth_details, charge_type,
                gateway_ref, merchant_ref, use_merchant_ref, ping_url)
        elif source_type == ACCOUNT:
            charge = AccountCharge.retrieve(auth_details, charge_type,
                gateway_ref, merchant_ref, use_merchant_ref, ping_url)
        else:
            raise RaveChargeError('Invalid source type. Must be {} or {} not {}'\
                .format(CARD, ACCOUNT, source_type))

        charge._headers = {
            'content-type': 'application/json',
            'Authorization': 'Bearer ' + auth_details.secret_key
        }
        return charge
Exemple #2
0
    def retrieve(cls, auth_details, charge_type=None, gateway_ref=None,
        merchant_ref=None, use_merchant_ref=False, ping_url=None):
        if not charge_type:
            raise RaveChargeError('Charge type should be specified. Options '\
                'are {} or {}.'.format(DIRECT_CHARGE, PREAUTH_CHARGE))
        if charge_type != PREAUTH_CHARGE and\
            ((gateway_ref or merchant_ref) == False):
            raise RaveChargeError('The gateway_ref (flwRef), or the '\
                'merchant_ref you used must be provided except when using '\
                'preauth flow')

        charge = CardCharge._call_verification_endpoint(
            auth_details, gateway_ref=gateway_ref, merchant_ref=merchant_ref,
            use_merchant_ref=use_merchant_ref, ping_url=ping_url)

        return charge
Exemple #3
0
    def validate(self, otp, ping_url=None):
        """
        After a direct charge is made, the transaction will be in a pending
        state. Calling this method makes the actual charge. Calling this
        method for the preauth flow raises a RaveChargeError.

        Args:
            otp: the one time password that was sent to the paying user

        Kwargs:
            ping_url: If present, this is the url that will be used for polling
                the validate request if a timeout response was initially
                received.

        Raises:
            RaveGracefullTimeoutError: if a timeout response is sent from
                the server. Read the docs for RaveGracefullTimeoutError for
                info on how to handle this exception gracefully.
        """
        if self._charge_type==PREAUTH_CHARGE or self._preauth_resp_data:
            raise RaveChargeError('Cannot call the calidate response for '\
                'a preauth flow. Call capture instead')

        if ping_url:
            resp_data = self._send_request_by_polling(ping_url)
        else:
            req_data = self._get_validate_request_data(otp)
            resp_data = self._send_request_no_poll(
                self._auth_details.urls.VALIDATE_CARD_CHARGE_URL, req_data)

        self._original_request_data = req_data
        self._validation_resp_data_dict = resp_data
        self._raw_resp_data = resp_data
Exemple #4
0
    def charge(self, redirect_url=None, ping_url=None, pin=None,
        charge_type=DIRECT_CHARGE, *args, **kwargs):
        """
        Makes an API request to make the charge. This method encrypts the
        request data for you before sending the request to the server.
        A card that was reconstructed by either calling retrieve or consume
        cannot be charged a second time. More concretely, if was_retrieved
        is set to True, this method will raise a RaveChargeError.
        """
        if self.was_retrieved:
            raise RaveChargeError(
                'Cannot charge a card that was reconstructed. Use create.')
        req_data = self._get_charge_request_data()

        if not ping_url:
            try:
                if charge_type == DIRECT_CHARGE:
                    charge_url = self._auth_details.urls.DIRECT_CHARGE_URL
                    req_data, resp_data = self._direct_charge(req_data, pin)
                elif charge_type == PREAUTH_CHARGE:
                    charge_url = self._auth_details.urls.PREAUTH_CHARGE_URL
                    req_data, resp_data = self._preauth_charge(req_data)
                else:
                    raise RaveChargeError("Invalid charge_type '{}'. Please "\
                        "provide keyword arg charge_type to be {} or {}".\
                        format(charge_type, 'constants.DIRECT_CHARGE',
                            'constants.PREAUTH_CHARGE.'))
            except RaveGracefullTimeoutError as e:
                resp_data = self._handle_gracefull_timeout(e, req_data,
                    charge_url)
        else:
            resp_data = self._send_request_by_polling(ping_url)

        if resp_data['status'] != 'success':
            e = RaveChargeError('Charge request failed. See e.error_resp')
            e.error_resp = resp_data
            raise e

        self._original_request_data = req_data
        self._charge_res_data_dict = resp_data
        self._raw_resp_data = resp_data
        self._gateway_ref = resp_data['data']['flwRef']
        self._merchant_ref = resp_data['data']['txRef']

        return resp_data
Exemple #5
0
    def verify(self, amount, currency, status='successful', charge_code='00',
        *args, **kwargs):
        """
        Performs basic sanity checks on the charge. The charge should have
        been initiated on the payment gateway before calling this method. More
        concretely, it should have a transaction reference assigned to it at
        the point where this method will be called. Either the
        self.verification_response_data or self.capture_response_data should be
        available by the time this method is called.
        """
        if not self.verification_response_data:
            ch = self.__class__._call_verification_endpoint(
            auth_details=self._auth_details, gateway_ref=self._gateway_ref,
            use_merchant_ref=False)

            self._verification_resp_data_dict = ch._verification_resp_data_dict
            self._raw_resp_data = ch._raw_resp_data

        resp_data = self.verification_response_data

        if resp_data['data']['amount'] < amount:
            raise RaveChargeError("Transaction amount '{}' is less than "\
                "requested amount '{}'".format(resp_data['data']['amount'],
                amount))
        if resp_data['data']['transaction_currency'] != currency:
            raise RaveChargeError("Invalid currenty. {} was desired, but the "\
                "transaction was made with {}".format(
                    currency, resp_data['data']["currency"]))
        if resp_data['data']['flwMeta']['chargeResponse'] != charge_code:
            raise RaveChargeError('Undesired charge response code. {} '\
                'returned but {} was expected'.\
                    format(resp_data['data']['flwMeta']['chargeResponse'],
                    charge_code))
        if resp_data['data']['status'] != status:
            raise RaveChargeError('Undesired status. {} returned but {} was expected'\
                .format(resp_data['data']['status'], status))
Exemple #6
0
    def _direct_charge(self, req_data, pin):
        resp_data = self._send_request_no_poll(
            self._auth_details.urls.DIRECT_CHARGE_URL ,req_data)
        if resp_data['data'].get('suggested_auth') == 'PIN':
            pin = pin if pin else req_data.get('pin')
            if not pin:
                raise RaveChargeError('Pin required for this transaction')
            else:
                self._original_charge_data.update({'suggested_auth': 'PIN',
                    'pin': pin})
                self._build_charge_request_data()
                req_data = self._get_charge_request_data()
                resp_data = self._send_request_no_poll(
                    self._auth_details.urls.DIRECT_CHARGE_URL, req_data)

        return req_data, resp_data
Exemple #7
0
    def create(self, source_type=CARD, *args, **kwargs):
        self._source_type = source_type
        if source_type == CARD:
            charge = CardCharge(self._auth_details, *self._args,
                **self._kwargs)
        elif source_type == ACCOUNT:
            charge = AccountCharge(self._auth_details, *self._args,
                **self._kwargs)
        else:
            raise RaveChargeError('Invalid source type. Must be {} or {} not {}'\
                .format(CARD, ACCOUNT, source_type))

        charge.create(*args, **kwargs)
        charge._headers = {
            'content-type': 'application/json',
            'Authorization': 'Bearer ' + self._auth_details.secret_key
        }
        return charge
Exemple #8
0
    def retrieve_from_webhook(self, source_type=CARD, *args, **kwargs):
        """
        Performs the same actions as it's base class but automatically creates
        the right type of charge instance based on the source_type param.
        Kwargs:
            source_type: The type of charge to instantiate. Default is CARD.
        """
        if source_type == CARD:
            charge = CardCharge.retrieve_from_webhook(*args,
                **kwargs)
        elif source_type == ACCOUNT:
            charge = AccountCharge.retrieve_from_webhook(*args,
                **kwargs)
        else:
            raise RaveChargeError('Invalid source type. Must be {} or {}'\
                .format(CARD, ACCOUNT))

        charge._headers = {
            'content-type': 'application/json',
            'Authorization': 'Bearer ' + self._auth_details.secret_key
        }
        return charge
Exemple #9
0
    def _send_request_no_poll(self, url, req_data, switch_to_polling=False):
        if switch_to_polling:
            resp_data = post(url + '?use_polling=1', req_data,
                headers=self._headers)
            if resp_data['status'] == 'success':
                ping_url = resp_data['data']['ping_url']
                e = RaveGracefullTimeoutError("Poll for response on url {}"\
                    .format(ping_url))
                e.ping_url = ping_url
            else:
                raise RaveChargeError('Could not switch to polling')
        else:
            resp_data = post(url, req_data, headers=self._headers)
            if resp_data['status'] == 'error' and\
                resp_data['data'].get('status') == 'failed':
                e = RaveGracefullTimeoutError(
                    "Timeout while sending charge request. Please switch to"\
                    " polling.")
                e.start_polling = True
                raise e

        return resp_data