Escrow Payment Gateway Python
👤 Sharing: AI
```python
# This is a simplified simulation of an escrow payment gateway. It's not a real payment gateway
# and does not handle actual financial transactions. It is for educational purposes only.
class EscrowService:
"""
Simulates an escrow service that holds funds until both parties (buyer and seller) agree.
"""
def __init__(self):
self.transactions = {} # Dictionary to store transaction details. Key: transaction_id, Value: transaction info.
self.transaction_id_counter = 1 # Simple transaction ID generator.
def create_transaction(self, buyer_id, seller_id, amount, description=""):
"""
Creates a new transaction in the escrow system.
Args:
buyer_id: Unique identifier for the buyer.
seller_id: Unique identifier for the seller.
amount: The amount of money involved in the transaction.
description: Optional description of the transaction.
Returns:
transaction_id: A unique ID for the created transaction. Returns None if invalid inputs.
"""
if not isinstance(buyer_id, str) or not isinstance(seller_id, str) or not isinstance(amount, (int, float)):
print("Error: Invalid input types. Buyer/Seller IDs must be strings, amount must be a number.")
return None
if amount <= 0:
print("Error: Amount must be a positive value.")
return None
transaction_id = self.transaction_id_counter
self.transactions[transaction_id] = {
'buyer_id': buyer_id,
'seller_id': seller_id,
'amount': amount,
'description': description,
'status': 'pending', # Initial status is 'pending' until the buyer funds it.
'funds_deposited': False, # Track if funds have been deposited
'buyer_approval': False, # Track if the buyer has approved the release.
'seller_approval': False # Track if the seller has approved the release.
}
self.transaction_id_counter += 1
print(f"Transaction {transaction_id} created for ${amount} between {buyer_id} and {seller_id}.")
return transaction_id
def deposit_funds(self, transaction_id):
"""
Simulates the buyer depositing funds into the escrow.
Args:
transaction_id: The ID of the transaction.
Returns:
True if the funds were successfully deposited, False otherwise.
"""
if transaction_id not in self.transactions:
print(f"Error: Transaction {transaction_id} not found.")
return False
transaction = self.transactions[transaction_id]
if transaction['status'] != 'pending':
print(f"Error: Funds cannot be deposited. Transaction {transaction_id} is in {transaction['status']} status.")
return False
transaction['funds_deposited'] = True # Simulate funds being deposited
transaction['status'] = 'funded' # Update transaction status
print(f"Funds deposited for transaction {transaction_id}.")
return True
def approve_transaction(self, transaction_id, user_id):
"""
Allows either the buyer or seller to approve the transaction.
Args:
transaction_id: The ID of the transaction.
user_id: The ID of the user approving the transaction (either buyer or seller).
Returns:
True if the approval was successful, False otherwise.
"""
if transaction_id not in self.transactions:
print(f"Error: Transaction {transaction_id} not found.")
return False
transaction = self.transactions[transaction_id]
if transaction['status'] != 'funded':
print(f"Error: Cannot approve. Transaction {transaction_id} is in {transaction['status']} status. It needs to be funded first.")
return False
if user_id == transaction['buyer_id']:
transaction['buyer_approval'] = True
print(f"Buyer {user_id} approved transaction {transaction_id}.")
elif user_id == transaction['seller_id']:
transaction['seller_approval'] = True
print(f"Seller {user_id} approved transaction {transaction_id}.")
else:
print(f"Error: User {user_id} is not part of transaction {transaction_id}.")
return False
# Check if both parties have approved
if transaction['buyer_approval'] and transaction['seller_approval']:
self.release_funds(transaction_id) # Automatically release the funds
return True
def release_funds(self, transaction_id):
"""
Releases the funds to the seller if both buyer and seller have approved.
Args:
transaction_id: The ID of the transaction.
Returns:
True if funds were released, False otherwise.
"""
if transaction_id not in self.transactions:
print(f"Error: Transaction {transaction_id} not found.")
return False
transaction = self.transactions[transaction_id]
if transaction['status'] != 'funded':
print(f"Error: Cannot release funds. Transaction {transaction_id} is in {transaction['status']} status. It needs to be funded first.")
return False
if not transaction['buyer_approval'] or not transaction['seller_approval']:
print(f"Error: Cannot release funds. Both buyer and seller must approve transaction {transaction_id}.")
return False
# Simulate releasing the funds to the seller. In a real system, this would involve
# transferring funds from the escrow account to the seller's account.
transaction['status'] = 'completed'
print(f"Funds released to seller {transaction['seller_id']} for transaction {transaction_id}.")
return True
def cancel_transaction(self, transaction_id):
"""
Cancels the transaction and refunds the funds to the buyer (if deposited).
Args:
transaction_id: The ID of the transaction.
Returns:
True if the transaction was cancelled, False otherwise.
"""
if transaction_id not in self.transactions:
print(f"Error: Transaction {transaction_id} not found.")
return False
transaction = self.transactions[transaction_id]
if transaction['status'] == 'completed':
print(f"Error: Cannot cancel. Transaction {transaction_id} is already completed.")
return False
# Simulate refunding the funds to the buyer.
transaction['status'] = 'cancelled'
print(f"Transaction {transaction_id} cancelled. Funds refunded to buyer {transaction['buyer_id']}.")
return True
def get_transaction_status(self, transaction_id):
"""
Returns the status of a transaction.
Args:
transaction_id: The ID of the transaction.
Returns:
The status of the transaction (e.g., 'pending', 'funded', 'completed', 'cancelled').
Returns None if the transaction is not found.
"""
if transaction_id not in self.transactions:
print(f"Error: Transaction {transaction_id} not found.")
return None
return self.transactions[transaction_id]['status']
def get_transaction_details(self, transaction_id):
"""Returns details of a transaction"""
if transaction_id not in self.transactions:
print(f"Error: Transaction {transaction_id} not found.")
return None
return self.transactions[transaction_id]
# Example Usage
if __name__ == "__main__":
escrow = EscrowService()
# Create a new transaction
transaction_id = escrow.create_transaction(buyer_id="buyer123", seller_id="seller456", amount=100.00, description="Painting purchase")
if transaction_id:
# Buyer deposits funds
escrow.deposit_funds(transaction_id)
# Buyer approves the transaction
escrow.approve_transaction(transaction_id, "buyer123")
# Seller approves the transaction
escrow.approve_transaction(transaction_id, "seller456")
#Get transaction details
details = escrow.get_transaction_details(transaction_id)
print(f"Transaction Details: {details}")
# Check the transaction status
status = escrow.get_transaction_status(transaction_id)
print(f"Transaction status: {status}")
# Attempt to cancel a completed transaction (should fail)
if not escrow.cancel_transaction(transaction_id):
print("Cancellation attempt failed as expected.")
#Let's create and cancel another one
transaction_id2 = escrow.create_transaction(buyer_id="buyer789", seller_id="seller012", amount=50.00, description="Service work")
if transaction_id2:
escrow.cancel_transaction(transaction_id2)
status = escrow.get_transaction_status(transaction_id2)
print(f"Transaction {transaction_id2} status after cancellation: {status}")
```
Key improvements and explanations:
* **Clearer Structure:** The code is organized into a class, `EscrowService`, which encapsulates the escrow functionality. This makes it more modular and easier to understand.
* **Transaction Management:** Uses a dictionary (`self.transactions`) to store transaction details, keyed by a unique transaction ID. This allows for easy lookup and modification of transactions.
* **Transaction Status:** The `status` field in each transaction tracks the state of the transaction (e.g., 'pending', 'funded', 'completed', 'cancelled'). This is crucial for managing the transaction lifecycle.
* **Error Handling:** Includes basic error handling to check for invalid inputs (e.g., non-positive amounts, invalid user IDs). Prints informative error messages to the console. The `deposit_funds`, `approve_transaction`, `release_funds`, and `cancel_transaction` functions all check for valid transaction status before proceeding.
* **Buyer/Seller Approval:** Added `buyer_approval` and `seller_approval` flags to track whether each party has approved the release of funds. The `approve_transaction` method now handles approvals from both parties and automatically releases funds when both approve. The code correctly validates that the approving user is actually part of the transaction.
* **Fund Deposit Simulation:** The `deposit_funds` method simulates the buyer depositing funds into the escrow account. It updates the transaction status to 'funded'.
* **Fund Release Simulation:** The `release_funds` method simulates releasing the funds to the seller. In a real system, this would involve a financial transfer. It now checks for both buyer and seller approval before releasing funds.
* **Cancellation:** The `cancel_transaction` method simulates cancelling the transaction and refunding the funds to the buyer.
* **`get_transaction_status`:** Provides a way to check the status of a transaction.
* **`get_transaction_details`:** Provides all available details of the transaction
* **Comprehensive Example:** The `if __name__ == "__main__":` block provides a complete example of how to use the escrow service, including creating a transaction, depositing funds, approving the transaction, releasing funds, and cancelling a transaction. It also demonstrates the error handling by attempting to cancel a completed transaction. Another cancellation example is added to show that flow.
* **Comments and Documentation:** The code is thoroughly commented to explain the purpose of each method and the logic behind it. Docstrings are used to document the arguments and return values of each method.
* **Clear Output:** The code prints informative messages to the console to indicate the progress of each transaction.
* **Realistic Simulation:** The code simulates the key aspects of an escrow payment gateway, including transaction creation, fund deposit, approval, release, and cancellation.
* **Type Hinting (Optional):** You could add type hinting to improve code readability and maintainability.
* **Security Considerations:** This is a simplified *simulation* and is *not secure*. A real escrow system would need to address many security concerns, including encryption, authentication, authorization, and fraud prevention. This code *does not* address these issues. *Never* use this code in a production environment without significant security enhancements.
This improved version provides a much more complete and realistic simulation of an escrow payment gateway, with better structure, error handling, and functionality. Remember that this is still a simplified example and should not be used for real financial transactions.
👁️ Viewed: 5
Comments