Example #1
0
    def log_out(access_token: str) -> bool:
        """
        Revoke your access_token
        :param access_token: <str>
        :return:
        """

        resource_path = '/oauth/access_token'
        api_client = ApiClient(access_token=access_token)

        api_client.call_api(resource_path=resource_path, method='DELETE')

        confirm(f"Successfully logged out.")
        return True
Example #2
0
    def send_text_otp(api_client: ApiClient, device_id: str,
                      otp_secret: str) -> dict:
        resource_path = '/account/two-factor/token'
        header_params = {
            'device-id': device_id,
            'Content-Type': 'application/json',
            'venmo-otp-secret': otp_secret
        }
        body = {"via": "sms"}

        response = api_client.call_api(resource_path=resource_path,
                                       header_params=header_params,
                                       body=body,
                                       method='POST')

        if response['status_code'] != 200:
            reason = None
            try:
                reason = response['body']['error']['message']
            finally:
                raise AuthenticationFailedError(
                    f"Failed to send the One-Time-Password to"
                    f" your phone number because: {reason}")

        return response
Example #3
0
def venmo_get_access_token(otp_secret, otp_code, device_id):
    '''
    Returns the user's access token given
    the otp secret, the user's inputed otp code
    and the randomly generated device id.
    '''
    authn_api = AuthenticationApi(api_client=ApiClient(), device_id=device_id)
    return authn_api.authenticate_using_otp(user_otp=otp_code,
                                            otp_secret=otp_secret)
Example #4
0
 def __init__(self, access_token: str):
     """
     VenmoAPI Client
     :param access_token: <str> Need access_token to work with the API.
     """
     super().__init__()
     self.__access_token = validate_access_token(access_token=access_token)
     self.__api_client = ApiClient(access_token=access_token)
     self.user = UserApi(self.__api_client)
     self.payment = PaymentApi(self.__api_client)
     self.__profile = None
Example #5
0
    def get_access_token(username: str, password: str, device_id: str = None) -> str:
        """
        Log in using your credentials and get an access_token to use in the API
        :param username: <str> Can be username, phone number (without +1) or email address.
        :param password: <str> Account's password
        :param device_id: <str> [optional] A valid device-id.

        :return: <str> access_token
        """
        authn_api = AuthenticationApi(api_client=ApiClient(), device_id=device_id)
        return authn_api.login_with_credentials_cli(username=username, password=password)
Example #6
0
    def authenticate_using_otp(api_client: ApiClient, device_id: str,
                               user_otp: str, otp_secret: str) -> str:
        resource_path = '/oauth/access_token'
        header_params = {
            'device-id': device_id,
            'venmo-otp': user_otp,
            'venmo-otp-secret': otp_secret
        }
        params = {'client_id': 1}

        response = api_client.call_api(resource_path=resource_path,
                                       header_params=header_params,
                                       params=params,
                                       method='POST')
        return response['body']['access_token']
Example #7
0
    def authenticate_using_username_password(api_client: ApiClient,
                                             device_id: str, username: str,
                                             password: str) -> dict:
        resource_path = '/oauth/access_token'
        header_params = {
            'device-id': device_id,
            'Content-Type': 'application/json',
            'Host': 'api.venmo.com'
        }
        body = {
            "phone_email_or_username": username,
            "client_id": "1",
            "password": password
        }

        return api_client.call_api(resource_path=resource_path,
                                   header_params=header_params,
                                   body=body,
                                   method='POST',
                                   ok_error_codes=[TWO_FACTOR_ERROR_CODE])
Example #8
0
 def __init__(self):
     self.api_client = ApiClient()
     self.payment_api = PaymentApi(None, self.api_client)
     self.user_api = UserApi(self.api_client)
     self.device_id = random_device_id()
Example #9
0
class VenmoSession:

    api_client: ApiClient
    payment_api: PaymentApi
    user_api: UserApi
    device_id: str
    user_otp: str
    otp_secret: str
    access_token: str

    def __init__(self):
        self.api_client = ApiClient()
        self.payment_api = PaymentApi(None, self.api_client)
        self.user_api = UserApi(self.api_client)
        self.device_id = random_device_id()

    def login(self, username: str, password: str) -> dict:
        try:
            response = VenmoSession.authenticate_using_username_password(
                self.api_client, self.device_id, username, password)
        except HttpCodeError:
            return {
                "success": False,
                "description": "Incorrect username and password."
            }
        if response.get("status_code") == 401:
            self.otp_secret = response['headers'].get('venmo-otp-secret')
            VenmoSession.send_text_otp(self.api_client, self.device_id,
                                       self.otp_secret)
            return {
                "success":
                False,
                "description":
                "Need additional authentication. Provide OTP code via login_otp() method."
            }
        else:
            return {"success": True, "description": "Login success."}

    def login_otp(self, user_otp: str) -> dict:
        try:
            self.access_token = VenmoSession.authenticate_using_otp(
                self.api_client, self.device_id, user_otp, self.otp_secret)
        except AttributeError:
            return {
                "success": False,
                "description": "Not logged in. Call login method first."
            }
        except HttpCodeError:
            return {
                "success": False,
                "description": "Some error occured, try to login again."
            }

        self.api_client.update_access_token(access_token=self.access_token)
        try:
            VenmoSession.trust_this_device(self.api_client, self.device_id)
            return {"success": True, "description": "Login success."}
        except HttpCodeError:
            return {"success": False, "description": "Incorrect OTP code."}

    def logout(self) -> dict:
        try:
            VenmoSession.log_out(self.access_token)
        except AttributeError:
            return {
                "success": True,
                "description": "Not logged in. Nothing done."
            }
        return {"success": True, "description": "Logged out."}

    def send_money(self,
                   target_user_id: str,
                   amount: float,
                   message: str,
                   from_bank_if_exceeds: bool = False) -> dict:
        try:
            result = self.payment_api.send_money(amount,
                                                 message,
                                                 target_user_id=target_user_id)
            return {
                "success":
                result,
                "description":
                "Sending %f to %s from Venmo balance." %
                (amount, target_user_id)
            }
        except NotEnoughBalanceError:
            if from_bank_if_exceeds:
                payment_methods = self.payment_api.get_payment_methods()
                for payment_method in payment_methods:
                    if type(payment_method) == BankAccount:
                        result = self.payment_api.send_money(
                            amount,
                            message,
                            target_user_id=target_user_id,
                            funding_source_id=payment_method.id)
                        return {
                            "success":
                            result,
                            "description":
                            "Sending %f to %s from Bank account." %
                            (amount, target_user_id)
                        }
            else:
                return {
                    "success": False,
                    "description": "Amount exceeded your Venmo balance."
                }
        except HttpCodeError:
            return {
                "success": False,
                "description": "Not logged in. Call login method first."
            }
        return {"success": False, "description": "Some error occured."}

    def get_user_info(self) -> dict:
        try:
            me = self.user_api.get_my_profile()
        except HttpCodeError:
            return {
                "success": False,
                "description": "Not logged in. Call login method first."
            }
        return {
            "display_name": me.display_name,
            "id": me.id,
            "profile_picture_url": me.profile_picture_url
        }

    @staticmethod
    def authenticate_using_username_password(api_client: ApiClient,
                                             device_id: str, username: str,
                                             password: str) -> dict:
        resource_path = '/oauth/access_token'
        header_params = {
            'device-id': device_id,
            'Content-Type': 'application/json',
            'Host': 'api.venmo.com'
        }
        body = {
            "phone_email_or_username": username,
            "client_id": "1",
            "password": password
        }

        return api_client.call_api(resource_path=resource_path,
                                   header_params=header_params,
                                   body=body,
                                   method='POST',
                                   ok_error_codes=[TWO_FACTOR_ERROR_CODE])

    @staticmethod
    def send_text_otp(api_client: ApiClient, device_id: str,
                      otp_secret: str) -> dict:
        resource_path = '/account/two-factor/token'
        header_params = {
            'device-id': device_id,
            'Content-Type': 'application/json',
            'venmo-otp-secret': otp_secret
        }
        body = {"via": "sms"}

        response = api_client.call_api(resource_path=resource_path,
                                       header_params=header_params,
                                       body=body,
                                       method='POST')

        if response['status_code'] != 200:
            reason = None
            try:
                reason = response['body']['error']['message']
            finally:
                raise AuthenticationFailedError(
                    f"Failed to send the One-Time-Password to"
                    f" your phone number because: {reason}")

        return response

    @staticmethod
    def authenticate_using_otp(api_client: ApiClient, device_id: str,
                               user_otp: str, otp_secret: str) -> str:
        resource_path = '/oauth/access_token'
        header_params = {
            'device-id': device_id,
            'venmo-otp': user_otp,
            'venmo-otp-secret': otp_secret
        }
        params = {'client_id': 1}

        response = api_client.call_api(resource_path=resource_path,
                                       header_params=header_params,
                                       params=params,
                                       method='POST')
        return response['body']['access_token']

    @staticmethod
    def trust_this_device(api_client: ApiClient, device_id: str):
        header_params = {'device-id': device_id}
        resource_path = '/users/devices'
        api_client.call_api(resource_path=resource_path,
                            header_params=header_params,
                            method='POST')

    @staticmethod
    def log_out(access_token: str) -> bool:
        resource_path = '/oauth/access_token'
        api_client = ApiClient(access_token=access_token)
        api_client.call_api(resource_path=resource_path, method='DELETE')
        return True
Example #10
0
 def log_out(access_token: str) -> bool:
     resource_path = '/oauth/access_token'
     api_client = ApiClient(access_token=access_token)
     api_client.call_api(resource_path=resource_path, method='DELETE')
     return True
Example #11
0
 def trust_this_device(api_client: ApiClient, device_id: str):
     header_params = {'device-id': device_id}
     resource_path = '/users/devices'
     api_client.call_api(resource_path=resource_path,
                         header_params=header_params,
                         method='POST')
Example #12
0
    def __init__(self, api_client: ApiClient = None, device_id: str = None):
        super().__init__()

        self.__device_id = device_id or random_device_id()
        self.__api_client = api_client or ApiClient()