Add all project files
This commit is contained in:
133
app/routers/payment.py
Normal file
133
app/routers/payment.py
Normal file
@@ -0,0 +1,133 @@
|
||||
#
|
||||
# your_app/views.py (or wherever this file is located)
|
||||
#
|
||||
import datetime
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import Tuple, Optional
|
||||
import enum
|
||||
|
||||
# Assuming these are your project's modules
|
||||
from .. import crud, models, schemas, database
|
||||
from ..services import payment_service
|
||||
|
||||
# Placeholder for the Authorize.Net response object type
|
||||
AuthNetResponse = object
|
||||
|
||||
|
||||
router = APIRouter(
|
||||
tags=["Transactions"], # Tags are for documentation only, they don't affect URLs
|
||||
)
|
||||
|
||||
class TransactionStatus(enum.IntEnum):
|
||||
APPROVED = 0
|
||||
DECLINED = 1
|
||||
|
||||
class TransactionType(enum.IntEnum):
|
||||
CHARGE = 0
|
||||
AUTHORIZE = 1
|
||||
CAPTURE = 3
|
||||
|
||||
# --- Helper function to avoid repeating response parsing logic ---
|
||||
def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[TransactionStatus, Optional[str], Optional[str]]:
|
||||
"""
|
||||
Parses the response from the Authorize.Net service.
|
||||
(This is the same helper from before, it's a good change to keep)
|
||||
"""
|
||||
if response and hasattr(response, 'messages') and response.messages.resultCode == "Ok":
|
||||
status = TransactionStatus.APPROVED
|
||||
auth_net_transaction_id = str(response.transactionResponse.transId) if hasattr(response, 'transactionResponse') else None
|
||||
rejection_reason = None
|
||||
else:
|
||||
status = TransactionStatus.DECLINED
|
||||
auth_net_transaction_id = None
|
||||
if hasattr(response, '_rejection_reason'):
|
||||
rejection_reason = str(response._rejection_reason)
|
||||
elif response is None:
|
||||
rejection_reason = "No response received from payment gateway."
|
||||
else:
|
||||
rejection_reason = "Payment declined by gateway."
|
||||
return status, auth_net_transaction_id, rejection_reason
|
||||
|
||||
|
||||
@router.post("/authorize/", response_model=schemas.Transaction)
|
||||
def authorize_card(customer_id: int, transaction: schemas.TransactionAuthorize, db: Session = Depends(database.get_db)):
|
||||
auth_net_response = payment_service.authorize_credit_card(transaction)
|
||||
status, auth_net_transaction_id, rejection_reason = _parse_authnet_response(auth_net_response)
|
||||
|
||||
transaction_data = schemas.TransactionBase(
|
||||
preauthorize_amount=transaction.preauthorize_amount,
|
||||
transaction_type=TransactionType.AUTHORIZE,
|
||||
service_id=transaction.service_id,
|
||||
delivery_id=transaction.delivery_id,
|
||||
card_id=transaction.card_id,
|
||||
rejection_reason=rejection_reason
|
||||
)
|
||||
|
||||
return crud.create_transaction(
|
||||
db=db,
|
||||
transaction=transaction_data,
|
||||
customer_id=customer_id,
|
||||
status=status,
|
||||
auth_net_transaction_id=auth_net_transaction_id
|
||||
)
|
||||
|
||||
@router.post("/charge/{customer_id}", response_model=schemas.Transaction)
|
||||
def charge_card(customer_id: int, transaction: schemas.TransactionCreate, db: Session = Depends(database.get_db)):
|
||||
# Add debug logging
|
||||
print(f"DEBUG: Received charge request for customer_id: {customer_id}")
|
||||
print(f"DEBUG: Transaction data: {transaction.dict() if hasattr(transaction, 'dict') else transaction}")
|
||||
|
||||
try:
|
||||
auth_net_response = payment_service.charge_credit_card(transaction)
|
||||
status, auth_net_transaction_id, rejection_reason = _parse_authnet_response(auth_net_response)
|
||||
|
||||
transaction_data = schemas.TransactionBase(
|
||||
charge_amount=transaction.charge_amount,
|
||||
transaction_type=TransactionType.CHARGE,
|
||||
service_id=transaction.service_id,
|
||||
delivery_id=transaction.delivery_id,
|
||||
card_id=transaction.card_id,
|
||||
rejection_reason=rejection_reason
|
||||
)
|
||||
print(f"DEBUG: Transaction data to create: {transaction_data.dict()}")
|
||||
|
||||
result = crud.create_transaction(
|
||||
db=db,
|
||||
transaction=transaction_data,
|
||||
customer_id=customer_id,
|
||||
status=status,
|
||||
auth_net_transaction_id=auth_net_transaction_id
|
||||
)
|
||||
print(f"DEBUG: Created transaction: {result.dict()}")
|
||||
return result
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Exception in charge_card: {str(e)}")
|
||||
import traceback
|
||||
print(f"DEBUG: Traceback: {traceback.format_exc()}")
|
||||
raise
|
||||
|
||||
|
||||
@router.post("/capture/", response_model=schemas.Transaction)
|
||||
def capture_authorized_amount(transaction: schemas.TransactionCapture, db: Session = Depends(database.get_db)):
|
||||
auth_transaction = crud.get_transaction_by_auth_id(db, auth_net_transaction_id=transaction.auth_net_transaction_id)
|
||||
if not auth_transaction:
|
||||
raise HTTPException(status_code=404, detail="Authorization transaction not found")
|
||||
|
||||
auth_net_response = payment_service.capture_authorized_transaction(transaction)
|
||||
status, _, rejection_reason = _parse_authnet_response(auth_net_response)
|
||||
|
||||
return crud.update_transaction_for_capture(
|
||||
db=db,
|
||||
auth_net_transaction_id=transaction.auth_net_transaction_id,
|
||||
charge_amount=transaction.charge_amount,
|
||||
status=status,
|
||||
rejection_reason=rejection_reason
|
||||
)
|
||||
|
||||
@router.get("/transaction/delivery/{delivery_id}", response_model=schemas.Transaction)
|
||||
def get_transaction_by_delivery(delivery_id: int, db: Session = Depends(database.get_db)):
|
||||
transaction = crud.get_transaction_by_delivery_id(db, delivery_id=delivery_id)
|
||||
if not transaction:
|
||||
raise HTTPException(status_code=404, detail="No pre-authorized transaction found for this delivery")
|
||||
return transaction
|
||||
Reference in New Issue
Block a user