def handle_transfer_to_blockchain_address(transfer_amount, sender_transfer_account, recipient_blockchain_address, transfer_use, transfer_mode, uuid=None): if transfer_amount > sender_transfer_account.balance: response_object = { 'message': 'Insufficient funds', 'feedback': True, } return make_response(jsonify(response_object)), 400 try: transfer = make_blockchain_transfer( transfer_amount, sender_transfer_account.token, sender_transfer_account.blockchain_address, recipient_blockchain_address, transfer_use, transfer_mode, uuid=None) # This is the top-level commit for this flow db.session.commit() except AccountNotApprovedError as e: response_object = { 'message': "Sender is not approved", 'feedback': True, } return make_response(jsonify(response_object)), 400 except InsufficientBalanceError as e: response_object = { 'message': "Insufficient balance", 'feedback': True, } return make_response(jsonify(response_object)), 400 response_object = { 'message': 'Payment Successful', 'feedback': True, 'data': { 'credit_transfer': me_credit_transfer_schema.dump(transfer).data } } return make_response(jsonify(response_object)), 201
def post(self): post_data = request.get_json() uuid = post_data.get('uuid') created = post_data.get('created') transfer_use = post_data.get('transfer_use') transfer_amount = round(float(post_data.get('transfer_amount', 0)), 6) transfer_random_key = post_data.get('transfer_random_key') pin = post_data.get('pin') nfc_serial_number = post_data.get('nfc_id') user_id = post_data.get('user_id') public_identifier = post_data.get('public_identifier') transfer_account_id = post_data.get('transfer_account_id') qr_data = post_data.get('qr_data') if qr_data is not None: qr_data = str(qr_data).strip(" ").strip("\t") is_sending = post_data.get('is_sending', False) authorised = False if uuid: existing_transfer = CreditTransfer.query.filter_by( uuid=uuid).first() if existing_transfer: # We return a 201 here so that the client removes the uuid from the cache response_object = { 'message': 'Transfer already in cache', 'data': { 'credit_transfer': me_credit_transfer_schema.dump(existing_transfer).data, } } return make_response(jsonify(response_object)), 201 if qr_data: split_qr_data = qr_data.split('-') if len(split_qr_data) == 1: # No hyphen, so assume qr code encode the public serial number counterparty_user = User.query.filter( func.lower(User.public_serial_number) == func.lower( qr_data)).first() else: user_id = int(split_qr_data[1]) counterparty_user = User.query.get(user_id) if not counterparty_user: response_object = { 'message': 'No such user for ID {}'.format(user_id), 'feedback': True, } return make_response(jsonify(response_object)), 400 if not is_sending: transfer_amount = int(split_qr_data[0]) qr_hash = split_qr_data[2] user_secret = counterparty_user.secret if not check_for_any_valid_hash(transfer_amount, user_secret, qr_hash): response_object = { 'message': 'Invalid QR Code', 'feedback': True, } return make_response(jsonify(response_object)), 401 authorised = True elif nfc_serial_number: # We treat NFC serials differently because they're automatically authorised under the current version counterparty_user = User.query.filter_by( nfc_serial_number=nfc_serial_number).first() authorised = True if not counterparty_user: response_object = { 'message': 'No such user for NFC serial number {}'.format( nfc_serial_number), 'feedback': True } return make_response(jsonify(response_object)), 400 else: try: counterparty_user = find_user_with_transfer_account_from_identifiers( user_id, public_identifier, transfer_account_id) except (NoTransferAccountError, UserNotFoundError) as e: if not Web3.isAddress(public_identifier.strip( 'ethereum:')) or not is_sending: response_object = {'message': str(e), 'feedback': True} return make_response(jsonify(response_object)), 400 #We're sending directly to a blockchain address return handle_transfer_to_blockchain_address( transfer_amount, g.user, public_identifier.strip('ethereum:'), transfer_use, uuid=uuid) if not counterparty_user: response_object = { 'message': 'User not found', 'feedback': True } return make_response(jsonify(response_object)), 400 authorised = counterparty_user.verify_password(str(pin)) if is_sending: authorised = True if not authorised: responseObject = { 'message': 'Not Authorised', 'feedback': True, } return make_response(jsonify(responseObject)), 401 if is_sending: send_user = g.user receive_user = counterparty_user else: send_user = counterparty_user receive_user = g.user if transfer_amount == 0 or transfer_amount > send_user.transfer_account.balance: db.session.commit() responseObject = { 'message': 'Insufficient funds', 'feedback': True, } return make_response(jsonify(responseObject)), 400 try: transfer = make_payment_transfer(transfer_amount, send_user, receive_user, transfer_use, uuid=uuid) except AccountNotApprovedError as e: db.session.commit() if e.is_sender is True: responseObject = { 'message': "Sender is not approved", 'feedback': True, } return make_response(jsonify(responseObject)), 400 elif e.is_sender is False: responseObject = { 'message': "Recipient is not approved", 'feedback': True, } return make_response(jsonify(responseObject)), 400 else: responseObject = { 'message': "Account is not approved", 'feedback': True, } return make_response(jsonify(responseObject)), 400 except InsufficientBalanceError as e: db.session.commit() responseObject = { 'message': "Insufficient balance", 'feedback': True, } return make_response(jsonify(responseObject)), 400 if created: try: transfer.created = datetime.datetime.strptime( created, "%Y-%m-%dT%H:%M:%S.%fz") except ValueError as e: pass if is_sending: push_user_transfer_confirmation(receive_user, transfer_random_key) db.session.commit() responseObject = { 'message': 'Payment Successful', 'first_name': counterparty_user.first_name, 'last_name': counterparty_user.last_name, 'feedback': True, 'data': { 'credit_transfer': me_credit_transfer_schema.dump(transfer).data } } return make_response(jsonify(responseObject)), 201
def post(self): post_data = request.get_json() uuid = post_data.get('uuid') created = post_data.get('created') transfer_use = post_data.get('transfer_use') try: use_ids = transfer_use.split(',') # passed as '3,4' etc. except AttributeError: use_ids = transfer_use transfer_mode = post_data.get('transfer_mode') transfer_amount = round(Decimal(post_data.get('transfer_amount', 0)), 6) transfer_random_key = post_data.get('transfer_random_key') pin = post_data.get('pin') nfc_serial_number = post_data.get('nfc_id') user_id = post_data.get('user_id') public_identifier = post_data.get('public_identifier') transfer_account_id = post_data.get('transfer_account_id') qr_data = post_data.get('qr_data') if qr_data is not None: qr_data = str(qr_data).strip(" ").strip("\t") my_transfer_account_id = post_data.get("my_transfer_account_id") is_sending = post_data.get('is_sending', False) transfer_card = None my_transfer_account = None authorised = False if transfer_account_id: counterparty_transfer_account = TransferAccount.query.get(transfer_account_id) else: counterparty_transfer_account = None if uuid: existing_transfer = CreditTransfer.query.filter_by(uuid=uuid).first() if existing_transfer: # We return a 201 here so that the client removes the uuid from the cache response_object = { 'message': 'Transfer already in cache', 'data': { 'credit_transfer': me_credit_transfer_schema.dump(existing_transfer).data, } } return make_response(jsonify(response_object)), 201 if qr_data: split_qr_data = qr_data.split('-') transfer_amount = int(split_qr_data[0]) transfer_account_id = int(split_qr_data[1]) user_id = int(split_qr_data[2]) qr_hash = split_qr_data[3] counterparty_user = User.query.get(user_id) if not counterparty_user: response_object = { 'message': 'No such user for ID {}'.format(user_id), 'feedback': True, } return make_response(jsonify(response_object)), 404 counterparty_transfer_account = TransferAccount.query.get(transfer_account_id) if not counterparty_transfer_account: response_object = { 'message': 'No such Transfer Account for ID {}'.format(transfer_account_id), 'feedback': True, } return make_response(jsonify(response_object)), 404 if counterparty_transfer_account not in counterparty_user.transfer_accounts: if not counterparty_transfer_account: response_object = { 'message': 'User {} not authorised for Transfer Account {}.' .format(user_id, transfer_account_id), 'feedback': True, } return make_response(jsonify(response_object)), 401 my_transfer_account = find_transfer_accounts_with_matching_token( g.user, counterparty_transfer_account.token ) user_secret = counterparty_user.secret if not check_for_any_valid_hash(transfer_amount, transfer_account_id, user_secret, qr_hash): response_object = { 'message': 'Invalid QR Code', 'feedback': True, } return make_response(jsonify(response_object)), 401 authorised = True elif nfc_serial_number: # We treat NFC serials differently because they're automatically authorised under the current version transfer_card = TransferCard.query.filter_by(nfc_serial_number=nfc_serial_number).first() if transfer_card: counterparty_user = transfer_card.user counterparty_transfer_account = transfer_card.transfer_account if not transfer_card or not counterparty_user or not counterparty_transfer_account: response_object = { 'message': 'Card not found', 'feedback': True } return make_response(jsonify(response_object)), 404 authorised = True else: try: counterparty_user, _ = find_user_with_transfer_account_from_identifiers( user_id, public_identifier, transfer_account_id) except (NoTransferAccountError, UserNotFoundError) as e: if not Web3.isAddress(public_identifier.strip('ethereum:')) or not is_sending: response_object = { 'message': str(e), 'feedback': True } return make_response(jsonify(response_object)), 400 my_transfer_account = TransferAccount.query.get(my_transfer_account_id) if not my_transfer_account: response_object = { 'message': 'Transfer Account not found for my_transfer_account_id {}'.format( my_transfer_account_id) } return make_response(jsonify(response_object)), 400 #We're sending directly to a blockchain address return handle_transfer_to_blockchain_address(transfer_amount, my_transfer_account, public_identifier.strip('ethereum:'), transfer_use, transfer_mode=TransferModeEnum.EXTERNAL, uuid=uuid) if not counterparty_user: response_object = { 'message': 'User not found', 'feedback': True } return make_response(jsonify(response_object)), 400 authorised = counterparty_user.verify_password(str(pin)) if is_sending: authorised = True if not authorised: response_object = { 'message': 'Not Authorised', 'feedback': True, } return make_response(jsonify(response_object)), 401 if not my_transfer_account: if not my_transfer_account_id: response_object = { 'message': 'You must provide your Transfer Account ID', } return make_response(jsonify(response_object)), 400 my_transfer_account = TransferAccount.query.get(my_transfer_account_id) if not my_transfer_account: response_object = { 'message': 'Transfer Account not found for my_transfer_account_id {}'.format(my_transfer_account_id) } return make_response(jsonify(response_object)), 400 if my_transfer_account not in g.user.transfer_accounts: response_object = { 'message': 'Transfer account provided does not belong to user', } return make_response(jsonify(response_object)), 401 if is_sending: send_user = g.user send_transfer_account = my_transfer_account receive_user = counterparty_user receive_transfer_account = counterparty_transfer_account else: if counterparty_transfer_account is None: response_object = { 'message': 'Counterparty Transfer Account not specified' } return make_response(jsonify(response_object)), 400 send_user = counterparty_user send_transfer_account = counterparty_transfer_account receive_user = g.user receive_transfer_account = my_transfer_account if transfer_amount == 0 or transfer_amount > send_transfer_account.balance: db.session.commit() response_object = { 'message': 'Insufficient funds', 'feedback': True, } return make_response(jsonify(response_object)), 400 try: transfer = make_payment_transfer(transfer_amount=transfer_amount, send_user=send_user, send_transfer_account=send_transfer_account, receive_user=receive_user, receive_transfer_account=receive_transfer_account, transfer_use=transfer_use, transfer_mode=transfer_mode, uuid=uuid, transfer_card=transfer_card) except AccountNotApprovedError as e: db.session.commit() if e.is_sender is True: response_object = { 'message': "Sender is not approved", 'feedback': True, } return make_response(jsonify(response_object)), 400 elif e.is_sender is False: response_object = { 'message': "Recipient is not approved", 'feedback': True, } return make_response(jsonify(response_object)), 400 else: response_object = { 'message': "Account is not approved", 'feedback': True, } return make_response(jsonify(response_object)), 400 except InsufficientBalanceError as e: db.session.commit() response_object = { 'message': "Insufficient balance", 'feedback': True, } return make_response(jsonify(response_object)), 400 if created: try: transfer.created = datetime.datetime.strptime(created, "%Y-%m-%dT%H:%M:%S.%fz") except ValueError as e: pass if is_sending: push_user_transfer_confirmation(receive_user, transfer_random_key) db.session.commit() response_object = { 'message': 'Payment Successful', 'first_name': counterparty_user.first_name, 'last_name': counterparty_user.last_name, 'feedback': True, 'data': { 'credit_transfer': me_credit_transfer_schema.dump(transfer).data } } return make_response(jsonify(response_object)), 201