Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions venmo_api/apis/payment_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
User, PaymentMethod, PaymentRole, PaymentPrivacy, deserialize, wrap_callback, get_user_id
from typing import List, Union

from venmo_api.models.eligibility_token import EligibilityToken


class PaymentApi(object):

Expand Down Expand Up @@ -155,6 +157,38 @@ def request_money(self, amount: float,
target_user=target_user,
callback=callback)

def __get_eligibility_token(self, amount: float, note: str, target_id: int = None, funding_source_id: str = None,
action: str = "pay",
country_code: str = "1", target_type: str = "user_id", callback=None):
"""
Generate eligibility token which is needed in payment requests
:param amount: <float> amount of money to be requested
:param note: <str> message/note of the transaction
:param target_id: <int> the user id of the person you are sending money to
:param funding_source_id: <str> Your payment_method id for this payment
:param action: <str> action that eligibility token is used for
:param country_code: <str> country code, not sure what this is for
:param target_type: <str> set by default to user_id, but there are probably other target types
"""
resource_path = '/protection/eligibility'
body = {
"funding_source_id": self.get_default_payment_method().id if not funding_source_id else funding_source_id,
"action": action,
"country_code": country_code,
"target_type": target_type,
"note": note,
"target_id": get_user_id(user=None, user_id=target_id),
"amount": amount,
}

response = self.__api_client.call_api(resource_path=resource_path,
body=body,
method='POST')
if callback:
return

return deserialize(response=response, data_type=EligibilityToken)

def __update_payment(self, action, payment_id):

if not payment_id:
Expand Down Expand Up @@ -198,6 +232,7 @@ def __send_or_request_money(self, amount: float,
funding_source_id: str = None,
privacy_setting: str = PaymentPrivacy.PRIVATE.value,
target_user_id: int = None, target_user: User = None,
eligibility_token: str = None,
callback=None) -> Union[bool, None]:
"""
Generic method for sending and requesting money
Expand All @@ -208,6 +243,7 @@ def __send_or_request_money(self, amount: float,
:param privacy_setting:
:param target_user_id:
:param target_user:
:param eligibility_token:
:param callback:
:return:
"""
Expand All @@ -227,6 +263,10 @@ def __send_or_request_money(self, amount: float,
if is_send_money:
if not funding_source_id:
funding_source_id = self.get_default_payment_method().id
if not eligibility_token:
eligibility_token = self.__get_eligibility_token(amount, note, int(target_user_id)).eligibility_token

body.update({"eligibility_token": eligibility_token})
body.update({"funding_source_id": funding_source_id})

resource_path = '/payments'
Expand Down
36 changes: 36 additions & 0 deletions venmo_api/models/eligibility_token.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from venmo_api import BaseModel, JSONSchema
from venmo_api.models.fee import Fee


class EligibilityToken(BaseModel):
def __init__(self, eligibility_token, eligible, fees, fee_disclaimer, json=None):
super().__init__()

self.eligibility_token = eligibility_token
self.eligible = eligible
self.fees = fees
self.fee_disclaimer = fee_disclaimer
self._json = json

@classmethod
def from_json(cls, json):
"""
Initialize a new eligibility token object from JSON.
:param json: JSON data to parse.
:return: EligibilityToken object.
"""
if not json:
return None

parser = JSONSchema.eligibility_token(json)

fees = parser.get_fees()
fee_objects = [Fee.from_json(fee) for fee in fees] if fees else []

return cls(
eligibility_token=parser.get_eligibility_token(),
eligible=parser.get_eligible(),
fees=fee_objects,
fee_disclaimer=parser.get_fee_disclaimer(),
json=json
)
37 changes: 37 additions & 0 deletions venmo_api/models/fee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from venmo_api import BaseModel, JSONSchema


class Fee(BaseModel):
def __init__(self, product_uri, applied_to, base_fee_amount, fee_percentage, calculated_fee_amount_in_cents,
fee_token, json=None):
super().__init__()

self.product_uri = product_uri
self.applied_to = applied_to
self.base_fee_amount = base_fee_amount
self.fee_percentage = fee_percentage
self.calculated_fee_amount_in_cents = calculated_fee_amount_in_cents
self.fee_token = fee_token
self._json = json

@classmethod
def from_json(cls, json):
"""
Initialize a new Fee object from JSON using the FeeParser.
:param json: JSON data to parse.
:return: Fee object.
"""
if not json:
return None

parser = JSONSchema.fee(json)

return cls(
product_uri=parser.get_product_uri(),
applied_to=parser.get_applied_to(),
base_fee_amount=parser.get_base_fee_amount(),
fee_percentage=parser.get_fee_percentage(),
calculated_fee_amount_in_cents=parser.get_calculated_fee_amount_in_cents(),
fee_token=parser.get_fee_token(),
json=json
)
62 changes: 62 additions & 0 deletions venmo_api/models/json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ def comment(json):
def mention(json):
return MentionParser(json)

@staticmethod
def eligibility_token(json):
return EligibilityTokenParser(json)

@staticmethod
def fee(json):
return FeeParser(json)


class TransactionParser:

Expand Down Expand Up @@ -324,3 +332,57 @@ def get_user(self):
"username": "username",
"user": "user"
}

class EligibilityTokenParser:
def __init__(self, json):
self.json = json

def get_eligibility_token(self):
return self.json.get(eligibility_token_json_format['eligibility_token'])

def get_eligible(self):
return self.json.get(eligibility_token_json_format['eligible'])

def get_fees(self):
return self.json.get(eligibility_token_json_format['fees'])

def get_fee_disclaimer(self):
return self.json.get(eligibility_token_json_format['fee_disclaimer'])

eligibility_token_json_format = {
'eligibility_token': 'eligibility_token',
'eligible': 'eligible',
'fees': 'fees',
'fee_disclaimer': 'fee_disclaimer'
}

class FeeParser:
def __init__(self, json):
self.json = json

def get_product_uri(self):
return self.json.get(fee_json_format['product_uri'])

def get_applied_to(self):
return self.json.get(fee_json_format['applied_to'])

def get_base_fee_amount(self):
return self.json.get(fee_json_format['base_fee_amount'])

def get_fee_percentage(self):
return self.json.get(fee_json_format['fee_percentage'])

def get_calculated_fee_amount_in_cents(self):
return self.json.get(fee_json_format['calculated_fee_amount_in_cents'])

def get_fee_token(self):
return self.json.get(fee_json_format['fee_token'])

fee_json_format = {
'product_uri': 'product_uri',
'applied_to': 'applied_to',
'base_fee_amount': 'base_fee_amount',
'fee_percentage': 'fee_percentage',
'calculated_fee_amount_in_cents': 'calculated_fee_amount_in_cents',
'fee_token': 'fee_token'
}
2 changes: 1 addition & 1 deletion venmo_api/utils/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, access_token=None):
self.access_token = access_token
self.configuration = {"host": "https://api.venmo.com/v1"}

self.default_headers = {"User-Agent": "Venmo/7.44.0 (iPhone; iOS 13.0; Scale/2.0)"}
self.default_headers = {"User-Agent": "Venmo/10.50.0 (iPhone; iOS 18.0; Scale/3.0)"}
if self.access_token:
self.default_headers.update({"Authorization": self.access_token})

Expand Down