Skip to content

Commit

Permalink
Fixed #2, handling payments made on iMessage and pending payments.
Browse files Browse the repository at this point in the history
  • Loading branch information
mmohades committed May 28, 2020
1 parent 9ae0a3a commit 01c66c7
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 52 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def requirements():

setup(
name='venmo-api',
version='0.1.4',
version='0.1.5',
author="Mark Mohades",
license="GNU General Public License v3",
url='https://github.com/mmohades/venmo',
Expand Down
24 changes: 12 additions & 12 deletions venmo_api/apis/payment_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ def send_money(self, amount: float,
target_user_id: int = None,
funding_source_id: str = None,
target_user: User = None,
privacy_setting: str = PaymentPrivacy.private.value,
privacy_setting: PaymentPrivacy = PaymentPrivacy.PRIVATE,
callback=None) -> Union[bool, None]:
"""
send [amount] money with [note] to the ([target_user_id] or [target_user]) from the [funding_source_id]
If no [funding_source_id] is provided, it will find the default source_id and uses that.
:param amount: <float>
:param note: <str>
:param funding_source_id: <str> Your payment_method id for this payment
:param privacy_setting: <str> private/friends/public
:param privacy_setting: <PaymentPrivacy> PRIVATE/FRIENDS/PUBLIC (enum)
:param target_user_id: <str>
:param target_user: <User>
:param callback: <function> Passing callback will run it in a distinct thread, and returns Thread
Expand All @@ -55,22 +55,22 @@ def send_money(self, amount: float,
note=note,
is_send_money=True,
funding_source_id=funding_source_id,
privacy_setting=privacy_setting,
privacy_setting=privacy_setting.value,
target_user_id=target_user_id,
target_user=target_user,
callback=callback)

def request_money(self, amount: float,
note: str,
target_user_id: int = None,
privacy_setting: str = PaymentPrivacy.private.value,
privacy_setting: PaymentPrivacy = PaymentPrivacy.PRIVATE,
target_user: User = None,
callback=None) -> Union[bool, None]:
"""
Request [amount] money with [note] from the ([target_user_id] or [target_user])
:param amount: <float> amount of money to be requested
:param note: <str> message/note of the transaction
:param privacy_setting: <str> private/friends/public (enum)
:param privacy_setting: <PaymentPrivacy> PRIVATE/FRIENDS/PUBLIC (enum)
:param target_user_id: <str> the user id of the person you are asking the money from
:param target_user: <User> The user object or user_id is required
:param callback: callback function
Expand All @@ -80,7 +80,7 @@ def request_money(self, amount: float,
note=note,
is_send_money=False,
funding_source_id=None,
privacy_setting=privacy_setting,
privacy_setting=privacy_setting.value,
target_user_id=target_user_id,
target_user=target_user,
callback=callback)
Expand All @@ -89,7 +89,7 @@ def __send_or_request_money(self, amount: float,
note: str,
is_send_money,
funding_source_id: str = None,
privacy_setting: str = PaymentPrivacy.private.value,
privacy_setting: str = PaymentPrivacy.PRIVATE.value,
target_user_id: int = None, target_user: User = None,
callback=None) -> Union[bool, None]:
"""
Expand Down Expand Up @@ -127,10 +127,10 @@ def __send_or_request_money(self, amount: float,
wrapped_callback = wrap_callback(callback=callback,
data_type=None)

threaded = self.__api_client.call_api(resource_path=resource_path,
method='POST',
body=body,
callback=wrapped_callback)
self.__api_client.call_api(resource_path=resource_path,
method='POST',
body=body,
callback=wrapped_callback)
if callback:
return
# if no exception raises, then it was successful
Expand All @@ -144,7 +144,7 @@ def get_default_payment_method(self) -> PaymentMethod:
payment_methods = self.get_payment_methods()

for p_method in payment_methods:
if p_method.role == PaymentRole.default:
if p_method.role == PaymentRole.DEFAULT:
return p_method

raise NoPaymentMethodFoundError()
65 changes: 38 additions & 27 deletions venmo_api/models/json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,56 @@ def payment_method(json):
class TransactionParser:

def __init__(self, json):
if not json:
return

self.json = json
self.payment = json[transaction_json_format['payment']]
self.payment = json.get(transaction_json_format['payment'])

def get_story_id(self):
return self.json[transaction_json_format['story_id']]
return self.json.get(transaction_json_format['story_id'])

def get_date_created(self):
return self.json[transaction_json_format['date_created']]
return self.json.get(transaction_json_format['date_created'])

def get_date_updated(self):
return self.json[transaction_json_format['date_updated']]
return self.json.get(transaction_json_format['date_updated'])

def get_actor_app(self):
return self.json[transaction_json_format['app']]
return self.json.get(transaction_json_format['app'])

def get_audience(self):
return self.json[transaction_json_format['aud']]
return self.json.get(transaction_json_format['aud'])

def get_likes(self):
return self.json[transaction_json_format['likes']]
return self.json.get(transaction_json_format['likes'])

def get_comments(self):
return self.json[transaction_json_format['comments']]
return self.json.get(transaction_json_format['comments'])

def get_transaction_type(self):
return self.json.get(transaction_json_format['transaction_type'])

def get_payment_id(self):
return self.payment[payment_json_format['payment_id']]
return self.payment.get(payment_json_format['payment_id'])

def get_type(self):
return self.payment[payment_json_format['type']]
return self.payment.get(payment_json_format['type'])

def get_date_completed(self):
return self.payment[payment_json_format['date_completed']]
return self.payment.get(payment_json_format['date_completed'])

def get_story_note(self):
return self.payment[payment_json_format['note']]
return self.payment.get(payment_json_format['note'])

def get_actor(self):
return self.payment[payment_json_format['actor']]
return self.payment.get(payment_json_format['actor'])

def get_target(self):
return self.payment[payment_json_format['target']]['user']
return self.payment.get(payment_json_format['target']).get('user')

def get_status(self):
return self.payment[payment_json_format['status']]
return self.payment.get(payment_json_format['status'])


transaction_json_format = {
Expand All @@ -72,7 +78,8 @@ def get_status(self):
"app": "app",
"payment": "payment",
"comments": "comments",
"likes": "likes"
"likes": "likes",
"transaction_type": "type"
}
payment_json_format = {
"status": "status",
Expand All @@ -81,13 +88,17 @@ def get_status(self):
"target": "target",
"actor": "actor",
"note": "note",
'type': 'action'
"type": "action"
}


class UserParser:

def __init__(self, json, is_profile=False):

if not json:
return

self.json = json
self.is_profile = is_profile

Expand All @@ -97,38 +108,38 @@ def __init__(self, json, is_profile=False):
self.parser = user_json_format

def get_user_id(self):
return self.json[self.parser.get('user_id')]
return self.json.get(self.parser.get('user_id'))

def get_username(self):
return self.json[self.parser.get('username')]
return self.json.get(self.parser.get('username'))

def get_first_name(self):
return self.json[self.parser.get('first_name')]
return self.json.get(self.parser.get('first_name'))

def get_last_name(self):
return self.json[self.parser.get('last_name')]
return self.json.get(self.parser.get('last_name'))

def get_full_name(self):
return self.json[self.parser.get('full_name')]
return self.json.get(self.parser.get('full_name'))

def get_picture_url(self):
return self.json[self.parser.get('picture_url')]
return self.json.get(self.parser.get('picture_url'))

def get_about(self):
return self.json[self.parser.get('about')]
return self.json.get(self.parser.get('about'))

def get_date_created(self):
return self.json[self.parser.get('date_created')]
return self.json.get(self.parser.get('date_created'))

def get_is_group(self):
if self.is_profile:
return False
return self.json[self.parser.get('is_group')]
return self.json.get(self.parser.get('is_group'))

def get_is_active(self):
if self.is_profile:
return False
return self.json[self.parser.get('is_active')]
return self.json.get(self.parser.get('is_active'))


user_json_format = {
Expand Down
13 changes: 6 additions & 7 deletions venmo_api/models/payment_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,15 @@ def __init__(self, pid, p_role, p_name, p_type):


class PaymentRole(Enum):
default = 'default'
backup = 'backup'
none = 'none'
DEFAULT = 'default'
BACKUP = 'backup'
NONE = 'none'


class PaymentPrivacy(Enum):

private = 'private'
public = 'public'
friends = 'friends'
PRIVATE = 'private'
PUBLIC = 'public'
FRIENDS = 'friends'


payment_type = {'bank': BankAccount, 'balance': VenmoBalance}
27 changes: 22 additions & 5 deletions venmo_api/models/transaction.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from enum import Enum
from venmo_api import string_to_timestamp
from venmo_api import User
from venmo_api import get_phone_model_from_json
Expand Down Expand Up @@ -31,16 +32,26 @@ def __init__(self, story_id, payment_id, date_completed, date_created,

@classmethod
def from_json(cls, json):
"""
Create a new Transaction from the given json.
This only works for transactions, skipping refunds and bank transfers.
:param json:
:return:
"""

# Skip money transfers to/from bank accounts
if json.get("transfer"):
return None
if not json:
return

parser = JSONSchema.transaction(json)
transaction_type = TransactionType(parser.get_transaction_type())

# Skip money transfers to/from bank accounts and refunds
if transaction_type == TransactionType.REFUND or transaction_type == TransactionType.TRANSFER:
return

date_created = string_to_timestamp(parser.get_date_created())
date_updated = string_to_timestamp(parser.get_date_updated())
date_completed = string_to_timestamp(parser.get_date_completed())

target = User.from_json(json=parser.get_target())
actor = User.from_json(json=parser.get_actor())
device_used = get_phone_model_from_json(parser.get_actor_app())
Expand All @@ -52,8 +63,8 @@ def from_json(cls, json):
date_updated=date_updated,
payment_type=parser.get_type(),
audience=parser.get_audience(),
status=parser.get_status(),
note=parser.get_story_note(),
status=parser.get_status(),
device_used=device_used,
actor=actor,
target=target)
Expand All @@ -66,3 +77,9 @@ def __str__(self):
f'audience: {self.audience}, status: {self.status}, note: {self.note}, device_used: {self.device_used},\n' \
f'actor_user: {self.actor},\n' \
f'target_user: {self.target}\n'


class TransactionType(Enum):
PAYMENT = 'payment'
REFUND = 'refund'
TRANSFER = 'transfer'
3 changes: 3 additions & 0 deletions venmo_api/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ def from_json(cls, json, is_profile=False):
:param is_profile:
:return:
"""
if not json:
return

parser = JSONSchema.user(json, is_profile=is_profile)

date_joined_timestamp = string_to_timestamp(parser.get_date_created())
Expand Down

0 comments on commit 01c66c7

Please sign in to comment.