major claude changes

This commit is contained in:
2026-01-28 21:54:54 -05:00
parent 76e881d939
commit 1832c8ab62
15 changed files with 423 additions and 296 deletions

View File

@@ -1,9 +1,11 @@
## File: your_app/crud.py ## File: your_app/crud.py
import logging
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from . import models, schemas from . import models, schemas
from decimal import Decimal from decimal import Decimal
logger = logging.getLogger(__name__)
# --- NEW CRUD FUNCTIONS FOR CIM --- # --- NEW CRUD FUNCTIONS FOR CIM ---
def get_card_by_id(db: Session, card_id: int): def get_card_by_id(db: Session, card_id: int):

View File

@@ -1,3 +1,5 @@
import logging
import sys
from fastapi import FastAPI from fastapi import FastAPI
from .database import engine from .database import engine
from . import models from . import models
@@ -7,10 +9,39 @@ from .routers.auto import auto_router
from .routers.user_check import user_check_router from .routers.user_check import user_check_router
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from config import load_config from config import load_config
from authorizenet import apicontractsv1
from authorizenet.apicontrollers import getCustomerProfileIdsController
from authorizenet.constants import constants
ApplicationConfig = load_config() ApplicationConfig = load_config()
# Configure logging
def setup_logging():
"""Configure structured logging for the application."""
log_level = logging.DEBUG if ApplicationConfig.CURRENT_SETTINGS != 'PRODUCTION' else logging.INFO
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
root_logger = logging.getLogger()
root_logger.setLevel(log_level)
root_logger.handlers.clear()
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(log_level)
console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)
# Reduce noise from uvicorn and other libs
logging.getLogger('uvicorn.access').setLevel(logging.WARNING)
return logging.getLogger('eamco_authorize')
logger = setup_logging()
models.Base.metadata.create_all(bind=engine) models.Base.metadata.create_all(bind=engine)
@@ -38,3 +69,64 @@ app.include_router(user_check_router, prefix="/user", tags=["usercheck"])
@app.get("/") @app.get("/")
def read_root(): def read_root():
return {"message": "Welcome to the HVAC Payment API"} return {"message": "Welcome to the HVAC Payment API"}
def validate_authorize_credentials():
"""
Validates Authorize.net credentials at startup.
Returns True if credentials are valid, raises exception if not.
"""
api_login_id = ApplicationConfig.API_LOGIN_ID
transaction_key = ApplicationConfig.TRANSACTION_KEY
# Check if credentials are present
if not api_login_id or not api_login_id.strip():
raise ValueError("AUTHORIZE_API_LOGIN_ID is not configured")
if not transaction_key or not transaction_key.strip():
raise ValueError("AUTHORIZE_TRANSACTION_KEY is not configured")
# Test the credentials by making a simple API call
merchantAuth = apicontractsv1.merchantAuthenticationType(
name=api_login_id,
transactionKey=transaction_key
)
request = apicontractsv1.getCustomerProfileIdsRequest(
merchantAuthentication=merchantAuth
)
controller = getCustomerProfileIdsController(request)
# Set environment based on config
if ApplicationConfig.CURRENT_SETTINGS in ['PRODUCTION', 'LOCAL']:
controller.setenvironment(constants.PRODUCTION)
else:
controller.setenvironment(constants.SANDBOX)
controller.execute()
response = controller.getresponse()
if response is None:
raise ValueError("Could not connect to Authorize.net - check network connectivity")
if response.messages.resultCode != "Ok":
error_code = response.messages.message[0].code if response.messages.message else "Unknown"
error_text = response.messages.message[0].text if response.messages.message else "Unknown error"
raise ValueError(f"Authorize.net credential validation failed: {error_code} - {error_text}")
return True
@app.on_event("startup")
async def startup_event():
"""Application startup - validate payment credentials."""
logger.info("Starting eamco_authorize service...")
logger.info(f"Mode: {ApplicationConfig.CURRENT_SETTINGS}")
try:
validate_authorize_credentials()
logger.info("Authorize.net credentials: VALID")
except ValueError as e:
logger.critical(f"PAYMENT CREDENTIALS INVALID: {e}")
logger.critical("Service will start but ALL PAYMENT OPERATIONS WILL FAIL")
# In production, you might want to sys.exit(1) here instead

View File

@@ -1,8 +1,11 @@
import logging
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app import crud, database from app import crud, database
logger = logging.getLogger(__name__)
# Create a router for auto-specific transaction endpoints # Create a router for auto-specific transaction endpoints
auto_router = APIRouter( auto_router = APIRouter(
prefix="/auto/transaction", prefix="/auto/transaction",
@@ -16,7 +19,7 @@ def get_auto_delivery_transaction(auto_id: int, db: Session = Depends(database.g
Get the pre-authorization transaction for an auto ticket delivery. Get the pre-authorization transaction for an auto ticket delivery.
Used by the capture page for auto deliveries. Used by the capture page for auto deliveries.
""" """
logger.info(f"GET /auto/transaction/delivery/{auto_id} - Fetching auto delivery transaction")
transaction = crud.get_transaction_by_auto_id(db, auto_id=auto_id) transaction = crud.get_transaction_by_auto_id(db, auto_id=auto_id)
if not transaction: if not transaction:
@@ -37,6 +40,7 @@ def update_transaction_auto_id(current_auto_id: int, new_auto_id: int, db: Sessi
Update the auto_id of a transaction based on the current auto_id. Update the auto_id of a transaction based on the current auto_id.
Used to change transaction from auto_delivery.id to auto_ticket.id Used to change transaction from auto_delivery.id to auto_ticket.id
""" """
logger.info(f"PUT /auto/transaction/delivery/{current_auto_id}/update/{new_auto_id} - Updating transaction auto ID")
transaction = crud.get_transaction_by_auto_id(db, auto_id=current_auto_id) transaction = crud.get_transaction_by_auto_id(db, auto_id=current_auto_id)
if not transaction: if not transaction:
raise HTTPException(status_code=404, detail="No transaction found for this auto delivery") raise HTTPException(status_code=404, detail="No transaction found for this auto delivery")

View File

@@ -1,6 +1,9 @@
## File: your_app/views.py ## File: your_app/views.py
import logging
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
logger = logging.getLogger(__name__)
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from typing import Tuple, Optional from typing import Tuple, Optional
import enum import enum
@@ -48,18 +51,18 @@ def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[Transa
Parse Authorize.net response with proper attribute access for SDK objects. Parse Authorize.net response with proper attribute access for SDK objects.
Authorize.net response objects don't have .text properties, they're direct attributes. Authorize.net response objects don't have .text properties, they're direct attributes.
""" """
print(f"DEBUG: Parsing response, type: {type(response)}") logger.debug(f"DEBUG: Parsing response, type: {type(response)}")
print(f"DEBUG: Response exists: {response is not None}") logger.debug(f"DEBUG: Response exists: {response is not None}")
if response is not None: if response is not None:
print("DEBUG: Checking for messages attribute...") logger.debug("DEBUG: Checking for messages attribute...")
if hasattr(response, 'messages'): if hasattr(response, 'messages'):
print(f"DEBUG: Messages exist, resultCode: {getattr(response.messages, 'resultCode', 'NO resultCode')}") logger.debug(f"DEBUG: Messages exist, resultCode: {getattr(response.messages, 'resultCode', 'NO resultCode')}")
else: else:
print("DEBUG: No messages attribute") logger.debug("DEBUG: No messages attribute")
if response.messages.resultCode == "Ok": if response.messages.resultCode == "Ok":
print("✅✅ DEBUG: Taking APPROVED path") logger.debug("✅✅ DEBUG: Taking APPROVED path")
status = TransactionStatus.APPROVED status = TransactionStatus.APPROVED
auth_net_transaction_id = None auth_net_transaction_id = None
@@ -68,24 +71,24 @@ def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[Transa
if hasattr(response, 'transactionResponse') and response.transactionResponse is not None: if hasattr(response, 'transactionResponse') and response.transactionResponse is not None:
if hasattr(response.transactionResponse, 'transId') and response.transactionResponse.transId: if hasattr(response.transactionResponse, 'transId') and response.transactionResponse.transId:
auth_net_transaction_id = str(response.transactionResponse.transId) auth_net_transaction_id = str(response.transactionResponse.transId)
print(f"✅✅ DEBUG: FOUND transaction ID: {auth_net_transaction_id}") logger.debug(f"✅✅ DEBUG: FOUND transaction ID: {auth_net_transaction_id}")
else: else:
print("DEBUG: transactionResponse exists but no transId") logger.debug("DEBUG: transactionResponse exists but no transId")
else: else:
print("DEBUG: No transactionResponse in approved response") logger.debug("DEBUG: No transactionResponse in approved response")
except Exception as e: except Exception as e:
print(f"DEBUG: Exception extracting transaction ID: {e}") logger.debug(f"DEBUG: Exception extracting transaction ID: {e}")
print(f"DEBUG: Response object inspection:") logger.debug(f"DEBUG: Response object inspection:")
print(type(response)) logger.debug(type(response))
if hasattr(response, 'transactionResponse'): if hasattr(response, 'transactionResponse'):
print(f"TransactionResponse type: {type(response.transactionResponse)}") logger.debug(f"TransactionResponse type: {type(response.transactionResponse)}")
print(dir(response.transactionResponse)) logger.debug(dir(response.transactionResponse))
rejection_reason = None rejection_reason = None
print(f"✅✅✅ DEBUG: APPROVED - ID: {auth_net_transaction_id}, rejection: {rejection_reason}") logger.debug(f"✅✅✅ DEBUG: APPROVED - ID: {auth_net_transaction_id}, rejection: {rejection_reason}")
else: else:
print("DEBUG: Taking DECLINED path") logger.debug("DEBUG: Taking DECLINED path")
status = TransactionStatus.DECLINED status = TransactionStatus.DECLINED
auth_net_transaction_id = None auth_net_transaction_id = None
rejection_reason = "Payment declined by gateway." rejection_reason = "Payment declined by gateway."
@@ -94,22 +97,22 @@ def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[Transa
# Handle transaction response errors # Handle transaction response errors
if hasattr(response, 'transactionResponse') and response.transactionResponse is not None: if hasattr(response, 'transactionResponse') and response.transactionResponse is not None:
if hasattr(response.transactionResponse, 'errors') and response.transactionResponse.errors: if hasattr(response.transactionResponse, 'errors') and response.transactionResponse.errors:
print("DEBUG: Using transactionResponse.errors") logger.debug("DEBUG: Using transactionResponse.errors")
try: try:
error = response.transactionResponse.errors[0] error = response.transactionResponse.errors[0]
# Remove the .text access - use direct attributes # Remove the .text access - use direct attributes
error_code = getattr(error, 'errorCode', 'Unknown') error_code = getattr(error, 'errorCode', 'Unknown')
error_text = getattr(error, 'errorText', 'Unknown error') error_text = getattr(error, 'errorText', 'Unknown error')
rejection_reason = f"{error_code}: {error_text}" rejection_reason = f"{error_code}: {error_text}"
print(f"DEBUG: Transaction error: {rejection_reason}") logger.debug(f"DEBUG: Transaction error: {rejection_reason}")
except Exception as e: except Exception as e:
print(f"DEBUG: Exception parsing transaction error: {e}") logger.debug(f"DEBUG: Exception parsing transaction error: {e}")
rejection_reason = "Failed to parse transaction error" rejection_reason = "Failed to parse transaction error"
# Handle message-level errors # Handle message-level errors
elif hasattr(response, 'messages') and response.messages: elif hasattr(response, 'messages') and response.messages:
if hasattr(response.messages, 'message') and response.messages.message: if hasattr(response.messages, 'message') and response.messages.message:
print("DEBUG: Using response.messages.message") logger.debug("DEBUG: Using response.messages.message")
try: try:
msg = response.messages.message msg = response.messages.message
if isinstance(msg, list): if isinstance(msg, list):
@@ -118,12 +121,12 @@ def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[Transa
code = getattr(msg, 'code', 'Unknown') code = getattr(msg, 'code', 'Unknown')
text = getattr(msg, 'text', 'Unknown error') text = getattr(msg, 'text', 'Unknown error')
rejection_reason = f"{code}: {text}" rejection_reason = f"{code}: {text}"
print(f"DEBUG: Message error: {rejection_reason}") logger.debug(f"DEBUG: Message error: {rejection_reason}")
except Exception as e: except Exception as e:
print(f"DEBUG: Exception parsing message error: {e}") logger.debug(f"DEBUG: Exception parsing message error: {e}")
rejection_reason = "Failed to parse message error" rejection_reason = "Failed to parse message error"
print(f"✅✅✅ DEBUG: FINAL RESULT - Status: {status}, ID: {auth_net_transaction_id}, Reason: {rejection_reason}") logger.debug(f"✅✅✅ DEBUG: FINAL RESULT - Status: {status}, ID: {auth_net_transaction_id}, Reason: {rejection_reason}")
return status, auth_net_transaction_id, rejection_reason return status, auth_net_transaction_id, rejection_reason
@router.post("/customers/{customer_id}/cards", summary="Add a new payment card for a customer") @router.post("/customers/{customer_id}/cards", summary="Add a new payment card for a customer")
@@ -194,13 +197,13 @@ def update_card_for_customer(customer_id: int, card_id: int, card_info: schemas.
try: try:
# If payment profile ID is null, refresh from Authorize.Net to sync # If payment profile ID is null, refresh from Authorize.Net to sync
if not db_card.auth_net_payment_profile_id: if not db_card.auth_net_payment_profile_id:
print(f"Payment profile ID is null for card {card_id}, refreshing from Authorize.Net") logger.debug(f"Payment profile ID is null for card {card_id}, refreshing from Authorize.Net")
from ..services import user_create from ..services import user_create
user_create.refresh_customer_payment_profiles(db, customer_id, db_customer.auth_net_profile_id) user_create.refresh_customer_payment_profiles(db, customer_id, db_customer.auth_net_profile_id)
# Re-fetch the card to get the updated payment profile ID # Re-fetch the card to get the updated payment profile ID
db.refresh(db_card) db.refresh(db_card)
print(f"After refresh, card {card_id} has payment_profile_id: {db_card.auth_net_payment_profile_id}") logger.debug(f"After refresh, card {card_id} has payment_profile_id: {db_card.auth_net_payment_profile_id}")
# Delete existing payment profile if it exists # Delete existing payment profile if it exists
if db_card.auth_net_payment_profile_id: if db_card.auth_net_payment_profile_id:
@@ -209,13 +212,13 @@ def update_card_for_customer(customer_id: int, card_id: int, card_info: schemas.
db_customer.auth_net_profile_id, db_card.auth_net_payment_profile_id db_customer.auth_net_profile_id, db_card.auth_net_payment_profile_id
) )
if delete_success: if delete_success:
print(f"Successfully deleted old payment profile {db_card.auth_net_payment_profile_id} for card {card_id}") logger.debug(f"Successfully deleted old payment profile {db_card.auth_net_payment_profile_id} for card {card_id}")
# Clear the payment profile ID since it was deleted # Clear the payment profile ID since it was deleted
db_card.auth_net_payment_profile_id = None db_card.auth_net_payment_profile_id = None
db.add(db_card) db.add(db_card)
db.commit() db.commit()
else: else:
print(f"Failed to delete old payment profile {db_card.auth_net_payment_profile_id} for card {card_id}") logger.debug(f"Failed to delete old payment profile {db_card.auth_net_payment_profile_id} for card {card_id}")
# Create new payment profile with updated card information # Create new payment profile with updated card information
new_payment_profile_id = payment_service.add_payment_profile_to_customer( new_payment_profile_id = payment_service.add_payment_profile_to_customer(
@@ -229,7 +232,7 @@ def update_card_for_customer(customer_id: int, card_id: int, card_info: schemas.
db.add(db_card) db.add(db_card)
db.commit() db.commit()
print(f"Successfully updated card {card_id} with new payment profile {new_payment_profile_id}") logger.debug(f"Successfully updated card {card_id} with new payment profile {new_payment_profile_id}")
# Return the new payment_profile_id # Return the new payment_profile_id
return {"payment_profile_id": new_payment_profile_id} return {"payment_profile_id": new_payment_profile_id}
@@ -239,7 +242,7 @@ def update_card_for_customer(customer_id: int, card_id: int, card_info: schemas.
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e))
except Exception as e: except Exception as e:
db.rollback() db.rollback()
print(f"Failed to update card {card_id}: {str(e)}") logger.debug(f"Failed to update card {card_id}: {str(e)}")
raise HTTPException(status_code=500, detail="An internal server error occurred.") raise HTTPException(status_code=500, detail="An internal server error occurred.")
@router.post("/charge/saved-card/{customer_id}", response_model=schemas.Transaction, summary="Charge a customer using a saved card") @router.post("/charge/saved-card/{customer_id}", response_model=schemas.Transaction, summary="Charge a customer using a saved card")
@@ -281,7 +284,7 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
Creates a pre-authorization on a customer's saved card. Creates a pre-authorization on a customer's saved card.
This validates the card and reserves the funds. This validates the card and reserves the funds.
""" """
print("🐛 DEBUG: ENTERING authorize_saved_card ROUTER FUNCTION") logger.debug("🐛 DEBUG: ENTERING authorize_saved_card ROUTER FUNCTION")
db_customer = crud.get_customer(db, customer_id=customer_id) db_customer = crud.get_customer(db, customer_id=customer_id)
db_card = crud.get_card_by_id(db, card_id=transaction_req.card_id) db_card = crud.get_card_by_id(db, card_id=transaction_req.card_id)
@@ -289,18 +292,18 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
if not db_customer or not db_card or db_card.user_id != customer_id: if not db_customer or not db_card or db_card.user_id != customer_id:
raise HTTPException(status_code=404, detail="Customer or card not found for this account") raise HTTPException(status_code=404, detail="Customer or card not found for this account")
print("🐛 DEBUG: CUSTOMER AND CARD FOUND, STARTING PRE-VALIDATION") logger.debug("🐛 DEBUG: CUSTOMER AND CARD FOUND, STARTING PRE-VALIDATION")
# 🚨 ENHANCED PRE-TRANSACTION VALIDATION 🚨 # 🚨 ENHANCED PRE-TRANSACTION VALIDATION 🚨
# Proactively check and fix payment profile issues before attempting transaction # Proactively check and fix payment profile issues before attempting transaction
print(f"🐛 DEBUG: Starting enhanced pre-validation for customer {customer_id}, card {db_card.id}") logger.debug(f"🐛 DEBUG: Starting enhanced pre-validation for customer {customer_id}, card {db_card.id}")
print(f"🔍 PRE-TRANSACTION CHECK: Customer {customer_id}, Card {db_card.id}") logger.debug(f"🔍 PRE-TRANSACTION CHECK: Customer {customer_id}, Card {db_card.id}")
print(f"🔍 Current auth_net_profile_id: '{db_customer.auth_net_profile_id}'") logger.debug(f"🔍 Current auth_net_profile_id: '{db_customer.auth_net_profile_id}'")
print(f"🔍 Current payment_profile_id: '{db_card.auth_net_payment_profile_id}'") logger.debug(f"🔍 Current payment_profile_id: '{db_card.auth_net_payment_profile_id}'")
# Check for missing payment profiles OR test validity of existing ones # Check for missing payment profiles OR test validity of existing ones
needs_recovery = False needs_recovery = False
print(f"🐛 DEBUG: Checking payment profiles - customer_id: {db_customer.auth_net_profile_id}, card_id: {db_card.auth_net_payment_profile_id}") logger.debug(f"🐛 DEBUG: Checking payment profiles - customer_id: {db_customer.auth_net_profile_id}, card_id: {db_card.auth_net_payment_profile_id}")
if (not db_customer.auth_net_profile_id or if (not db_customer.auth_net_profile_id or
not db_card.auth_net_payment_profile_id or not db_card.auth_net_payment_profile_id or
@@ -309,33 +312,33 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
db_card.auth_net_payment_profile_id is None): db_card.auth_net_payment_profile_id is None):
# Missing/null payment profile - needs recovery # Missing/null payment profile - needs recovery
needs_recovery = True needs_recovery = True
print("🐛 DEBUG: NULL/MISSING PAYMENT PROFILE DETECTED") logger.debug("🐛 DEBUG: NULL/MISSING PAYMENT PROFILE DETECTED")
print(f"🔧 NULL/MISSING PAYMENT PROFILE DETECTED - Triggering auto-recovery") logger.debug(f"🔧 NULL/MISSING PAYMENT PROFILE DETECTED - Triggering auto-recovery")
else: else:
# Payment profile exists in DB, but let's test if it's valid in Authorize.net # Payment profile exists in DB, but let's test if it's valid in Authorize.net
print(f"🐛 DEBUG: Payment profile exists, testing validity in Authorize.net...") logger.debug(f"🐛 DEBUG: Payment profile exists, testing validity in Authorize.net...")
print(f"🔍 Payment profile exists, testing validity in Authorize.net...") logger.debug(f"🔍 Payment profile exists, testing validity in Authorize.net...")
try: try:
# Quick test: try to retrieve customer payment profiles to see if our ID is valid # Quick test: try to retrieve customer payment profiles to see if our ID is valid
print(f"🐛 DEBUG: Calling get_customer_payment_profiles for profile_id: {db_customer.auth_net_profile_id}") logger.debug(f"🐛 DEBUG: Calling get_customer_payment_profiles for profile_id: {db_customer.auth_net_profile_id}")
test_profiles = payment_service.get_customer_payment_profiles(db_customer.auth_net_profile_id) test_profiles = payment_service.get_customer_payment_profiles(db_customer.auth_net_profile_id)
print(f"🐛 DEBUG: Got profiles from Authorize.net: {test_profiles}") logger.debug(f"🐛 DEBUG: Got profiles from Authorize.net: {test_profiles}")
current_id = str(db_card.auth_net_payment_profile_id) current_id = str(db_card.auth_net_payment_profile_id)
profile_ids_as_strings = [str(pid) for pid in test_profiles if pid] profile_ids_as_strings = [str(pid) for pid in test_profiles if pid]
print(f"🐛 DEBUG: Checking if '{current_id}' is in: {profile_ids_as_strings}") logger.debug(f"🐛 DEBUG: Checking if '{current_id}' is in: {profile_ids_as_strings}")
if current_id not in profile_ids_as_strings: if current_id not in profile_ids_as_strings:
needs_recovery = True needs_recovery = True
print(f"🐛 DEBUG: PAYMENT PROFILE {current_id} NOT FOUND - NEEDS RECOVERY") logger.debug(f"🐛 DEBUG: PAYMENT PROFILE {current_id} NOT FOUND - NEEDS RECOVERY")
print(f"🔧 PAYMENT PROFILE {db_card.auth_net_payment_profile_id} NOT FOUND IN AUTHORIZE.NET - Invalid ID!") logger.debug(f"🔧 PAYMENT PROFILE {db_card.auth_net_payment_profile_id} NOT FOUND IN AUTHORIZE.NET - Invalid ID!")
print(f"🔧 Available profiles in Authorize.net: {test_profiles}") logger.debug(f"🔧 Available profiles in Authorize.net: {test_profiles}")
else: else:
if ApplicationConfig.penny_test_transaction: if ApplicationConfig.penny_test_transaction:
print(f"🐛 DEBUG: Payment profile {db_card.auth_net_payment_profile_id} exists in Authorize.net, testing usability...") logger.debug(f"🐛 DEBUG: Payment profile {db_card.auth_net_payment_profile_id} exists in Authorize.net, testing usability...")
# Profile exists in Authorize.net, but test if it's actually USABLE # Profile exists in Authorize.net, but test if it's actually USABLE
# by doing a quick test authorization with minimal amount # by doing a quick test authorization with minimal amount
try: try:
print(f"🐛 DEBUG: Testing if payment profile is actually usable...") logger.debug(f"🐛 DEBUG: Testing if payment profile is actually usable...")
# Create a tiny test transaction (like $0.01) to validate the card works # Create a tiny test transaction (like $0.01) to validate the card works
test_transaction_req = schemas.TransactionAuthorizeByCardID( test_transaction_req = schemas.TransactionAuthorizeByCardID(
card_id=db_card.id, card_id=db_card.id,
@@ -356,31 +359,31 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
test_status, _, test_reason = _parse_authnet_response(test_response) test_status, _, test_reason = _parse_authnet_response(test_response)
if "E00121" in str(test_reason) or test_status == 1: # 1 = DECLINED if "E00121" in str(test_reason) or test_status == 1: # 1 = DECLINED
print(f"🐛 DEBUG: TEST AUTH FAILED - Payment profile exists but is INVALID!") logger.debug(f"🐛 DEBUG: TEST AUTH FAILED - Payment profile exists but is INVALID!")
needs_recovery = True needs_recovery = True
print(f"🔧 PAYMENT PROFILE {db_card.auth_net_payment_profile_id} EXISTS BUT IS UNUSABLE - E00121 detected during test!") logger.debug(f"🔧 PAYMENT PROFILE {db_card.auth_net_payment_profile_id} EXISTS BUT IS UNUSABLE - E00121 detected during test!")
print(f"🔧 Test transaction failed: {test_reason}") logger.debug(f"🔧 Test transaction failed: {test_reason}")
else: else:
print(f"🐛 DEBUG: Payment profile {db_card.auth_net_payment_profile_id} is VALID and USABLE") logger.debug(f"🐛 DEBUG: Payment profile {db_card.auth_net_payment_profile_id} is VALID and USABLE")
print(f"✅ Payment profile {db_card.auth_net_payment_profile_id} is valid and usable in Authorize.net") logger.debug(f"✅ Payment profile {db_card.auth_net_payment_profile_id} is valid and usable in Authorize.net")
except Exception as e: except Exception as e:
print(f"🐛 DEBUG: Exception during usability test: {str(e)} - assuming profile needs recreation") logger.debug(f"🐛 DEBUG: Exception during usability test: {str(e)} - assuming profile needs recreation")
needs_recovery = True needs_recovery = True
print(f"🔧 Could not test payment profile usability: {str(e)} - assuming it needs recreation") logger.debug(f"🔧 Could not test payment profile usability: {str(e)} - assuming it needs recreation")
else: else:
print(f"🔍 Skipping penny test transaction (disabled in config)") logger.debug(f"🔍 Skipping penny test transaction (disabled in config)")
except Exception as e: except Exception as e:
print(f"🐛 DEBUG: Exception during profile validation: {str(e)}") logger.debug(f"🐛 DEBUG: Exception during profile validation: {str(e)}")
print(f"🔧 Could not verify payment profile validity in Authorize.net: {str(e)}") logger.debug(f"🔧 Could not verify payment profile validity in Authorize.net: {str(e)}")
# If we can't verify, assume it's okay and let the transaction proceed # If we can't verify, assume it's okay and let the transaction proceed
# (better to try and fail than to block legitimate transactions) # (better to try and fail than to block legitimate transactions)
print(f"⚠️ Unable to verify profile validity - proceeding with transaction anyway") logger.debug(f"⚠️ Unable to verify profile validity - proceeding with transaction anyway")
if needs_recovery: if needs_recovery:
print(f"🔧 DETECTED PAYMENT PROFILE ISSUE - Triggering auto-recovery for customer {customer_id}") logger.debug(f"🔧 DETECTED PAYMENT PROFILE ISSUE - Triggering auto-recovery for customer {customer_id}")
# Auto-recover: Refresh payment profiles before transaction # Auto-recover: Refresh payment profiles before transaction
from ..services import user_create from ..services import user_create
@@ -389,14 +392,14 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
) )
if recovery_success: if recovery_success:
print("✅ Auto-recovery successful - proceeding with transaction") logger.debug("✅ Auto-recovery successful - proceeding with transaction")
# Re-fetch card data to get updated payment profile ID # Re-fetch card data to get updated payment profile ID
db.refresh(db_card) db.refresh(db_card)
db.refresh(db_customer) db.refresh(db_customer)
print(f"🔍 After recovery - payment_profile_id: '{db_card.auth_net_payment_profile_id}'") logger.debug(f"🔍 After recovery - payment_profile_id: '{db_card.auth_net_payment_profile_id}'")
else: else:
print("❌ Auto-recovery failed - cannot proceed with transaction") logger.debug("❌ Auto-recovery failed - cannot proceed with transaction")
raise HTTPException( raise HTTPException(
status_code=400, status_code=400,
detail="Payment profile setup error detected and auto-recovery failed. Please contact support." detail="Payment profile setup error detected and auto-recovery failed. Please contact support."
@@ -404,13 +407,13 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
# Final validation before proceeding # Final validation before proceeding
if not db_customer.auth_net_profile_id or not db_card.auth_net_payment_profile_id: if not db_customer.auth_net_profile_id or not db_card.auth_net_payment_profile_id:
print(f"❌ CRITICAL: Payment profile validation failed after recovery attempt") logger.debug(f"❌ CRITICAL: Payment profile validation failed after recovery attempt")
raise HTTPException( raise HTTPException(
status_code=400, status_code=400,
detail="Payment profile is not set up correctly for this customer/card" detail="Payment profile is not set up correctly for this customer/card"
) )
print(f"✅ Payment profile validation passed - proceeding with authorization") logger.debug(f"✅ Payment profile validation passed - proceeding with authorization")
# 🚨 ENHANCED E00121 ERROR HANDLING 🚨 # 🚨 ENHANCED E00121 ERROR HANDLING 🚨
# If transaction still fails with E00121 despite pre-validation, force-nuke the problematic ID # If transaction still fails with E00121 despite pre-validation, force-nuke the problematic ID
@@ -426,7 +429,7 @@ def authorize_saved_card(customer_id: int, transaction_req: schemas.TransactionA
# Parse the transaction response (no need for E00121 nuclear cleanup since pre-validation should have caught it) # Parse the transaction response (no need for E00121 nuclear cleanup since pre-validation should have caught it)
transaction_status, auth_net_transaction_id, rejection_reason = _parse_authnet_response(auth_net_response) transaction_status, auth_net_transaction_id, rejection_reason = _parse_authnet_response(auth_net_response)
print(transaction_req) logger.debug(transaction_req)
transaction_data = schemas.TransactionBase( transaction_data = schemas.TransactionBase(
preauthorize_amount=transaction_req.preauthorize_amount, preauthorize_amount=transaction_req.preauthorize_amount,
transaction_type=TransactionType.AUTHORIZE, # This is key transaction_type=TransactionType.AUTHORIZE, # This is key

View File

@@ -1,4 +1,5 @@
## File: transaction.py (New transaction router) ## File: transaction.py (New transaction router)
import logging
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
import enum import enum
@@ -11,6 +12,8 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
from app import crud, database, schemas, models from app import crud, database, schemas, models
from app.services import payment_service from app.services import payment_service
logger = logging.getLogger(__name__)
# Create a router for transaction endpoints # Create a router for transaction endpoints
transaction_router = APIRouter() transaction_router = APIRouter()
@@ -22,6 +25,7 @@ class TransactionStatus(enum.IntEnum):
@transaction_router.get("/test/", summary="Test transaction router") @transaction_router.get("/test/", summary="Test transaction router")
def test_transaction_router(): def test_transaction_router():
"""Test endpoint to verify transaction router is loaded""" """Test endpoint to verify transaction router is loaded"""
logger.info("GET /test - Testing transaction router")
return {"test": "transaction router is working"} return {"test": "transaction router is working"}
@@ -34,6 +38,7 @@ def get_delivery_transaction(delivery_id: int, db: Session = Depends(database.ge
Get the pre-authorization transaction for a specific delivery. Get the pre-authorization transaction for a specific delivery.
This endpoint is used to retrieve transaction details for delivery finalization. This endpoint is used to retrieve transaction details for delivery finalization.
""" """
logger.info(f"GET /transaction/delivery/{delivery_id} - Fetching delivery transaction")
transaction = crud.get_transaction_by_delivery_id(db, delivery_id=delivery_id) transaction = crud.get_transaction_by_delivery_id(db, delivery_id=delivery_id)
if not transaction: if not transaction:
raise HTTPException(status_code=404, detail="No pre-authorization transaction found for this delivery") raise HTTPException(status_code=404, detail="No pre-authorization transaction found for this delivery")
@@ -53,6 +58,7 @@ def update_transaction_delivery(delivery_id: int, new_delivery_id: int, db: Sess
Update the delivery_id of a transaction based on the current delivery_id. Update the delivery_id of a transaction based on the current delivery_id.
Used to change transaction from auto_delivery.id to auto_ticket.id Used to change transaction from auto_delivery.id to auto_ticket.id
""" """
logger.info(f"PUT /transaction/delivery/{delivery_id}/update/{new_delivery_id} - Updating transaction delivery ID")
transaction = crud.get_transaction_by_delivery_id(db, delivery_id=delivery_id) transaction = crud.get_transaction_by_delivery_id(db, delivery_id=delivery_id)
if not transaction: if not transaction:
raise HTTPException(status_code=404, detail="No transaction found for this delivery") raise HTTPException(status_code=404, detail="No transaction found for this delivery")
@@ -68,6 +74,7 @@ def update_transaction_auto_id(transaction_id: int, new_auto_id: int, db: Sessio
Update the auto_id of a transaction by its ID. Update the auto_id of a transaction by its ID.
Used to set auto_id to auto_ticket.id after ticket creation. Used to set auto_id to auto_ticket.id after ticket creation.
""" """
logger.info(f"PUT /transaction/{transaction_id}/update_auto_id/{new_auto_id} - Updating transaction auto ID")
transaction = db.query(models.Transaction).filter(models.Transaction.id == transaction_id).first() transaction = db.query(models.Transaction).filter(models.Transaction.id == transaction_id).first()
if not transaction: if not transaction:
raise HTTPException(status_code=404, detail="Transaction not found") raise HTTPException(status_code=404, detail="Transaction not found")
@@ -81,6 +88,7 @@ def update_transaction_auto_id(transaction_id: int, new_auto_id: int, db: Sessio
def capture_authorized_amount(transaction: schemas.TransactionCapture, db: Session = Depends(database.get_db)): def capture_authorized_amount(transaction: schemas.TransactionCapture, db: Session = Depends(database.get_db)):
# This endpoint captures a previously authorized transaction # This endpoint captures a previously authorized transaction
# It finds the original transaction by its ID and captures the funds # It finds the original transaction by its ID and captures the funds
logger.info(f"POST /capture - Capturing authorized transaction {transaction.auth_net_transaction_id}")
auth_transaction = crud.get_transaction_by_auth_id(db, auth_net_transaction_id=transaction.auth_net_transaction_id) auth_transaction = crud.get_transaction_by_auth_id(db, auth_net_transaction_id=transaction.auth_net_transaction_id)
if not auth_transaction: if not auth_transaction:
raise HTTPException(status_code=404, detail="Authorization transaction not found") raise HTTPException(status_code=404, detail="Authorization transaction not found")

View File

@@ -1,3 +1,4 @@
import logging
from fastapi import APIRouter, Depends, HTTPException from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -7,6 +8,8 @@ from ..services.check_user_service import verify_customer_authorize_account
from ..services.user_delete import delete_user_account from ..services.user_delete import delete_user_account
from ..services.user_create import create_user_account from ..services.user_create import create_user_account
logger = logging.getLogger(__name__)
# Create router for user check endpoints # Create router for user check endpoints
user_check_router = APIRouter() user_check_router = APIRouter()
@@ -18,6 +21,7 @@ def check_authorize_account(customer_id: int, db: Session = Depends(get_db)):
Returns status indicating what's needed for payment processing. Returns status indicating what's needed for payment processing.
""" """
logger.info(f"GET /check-authorize-account/{customer_id} - Checking Authorize.net account setup")
try: try:
result = verify_customer_authorize_account(db, customer_id) result = verify_customer_authorize_account(db, customer_id)
return result return result
@@ -32,6 +36,7 @@ def create_account(customer_id: int, db: Session = Depends(get_db)):
This creates the customer profile and all associated payment profiles in Authorize.net, This creates the customer profile and all associated payment profiles in Authorize.net,
and updates the database with the profile IDs. and updates the database with the profile IDs.
""" """
logger.info(f"POST /create-account/{customer_id} - Creating Authorize.net account")
try: try:
result = create_user_account(db, customer_id) result = create_user_account(db, customer_id)
return result return result
@@ -46,6 +51,7 @@ def delete_account(customer_id: int, db: Session = Depends(get_db)):
This removes the customer profile and all associated payment profiles from Authorize.net, This removes the customer profile and all associated payment profiles from Authorize.net,
and updates the database to null out the ID fields. and updates the database to null out the ID fields.
""" """
logger.info(f"DELETE /delete-account/{customer_id} - Deleting Authorize.net account")
try: try:
result = delete_user_account(db, customer_id) result = delete_user_account(db, customer_id)
return result return result

View File

@@ -1,5 +1,8 @@
import logging
import authorizenet.apicontrollers as controllers import authorizenet.apicontrollers as controllers
from authorizenet import apicontractsv1 from authorizenet import apicontractsv1
logger = logging.getLogger(__name__)
from .. import crud, database, schemas from .. import crud, database, schemas
from config import load_config from config import load_config
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@@ -73,7 +76,7 @@ def verify_customer_authorize_account(db: Session, customer_id: int) -> dict:
# Enhanced profile validation - check multiple conditions for profile existence # Enhanced profile validation - check multiple conditions for profile existence
profile_valid = _is_profile_valid(response) profile_valid = _is_profile_valid(response)
if not profile_valid: if not profile_valid:
print(f"Profile {customer.auth_net_profile_id} for customer {customer_id} is invalid/not found. Nulling out in database.") logger.debug(f"Profile {customer.auth_net_profile_id} for customer {customer_id} is invalid/not found. Nulling out in database.")
# Profile not found or invalid - set auth_net_profile_id to NULL in database # Profile not found or invalid - set auth_net_profile_id to NULL in database
try: try:
@@ -81,9 +84,9 @@ def verify_customer_authorize_account(db: Session, customer_id: int) -> dict:
customer.auth_net_profile_id = None customer.auth_net_profile_id = None
db.add(customer) # Mark for update db.add(customer) # Mark for update
db.commit() # Persist the change db.commit() # Persist the change
print(f"Successfully nulled out auth_net_profile_id for customer {customer_id}") logger.debug(f"Successfully nulled out auth_net_profile_id for customer {customer_id}")
except Exception as update_error: except Exception as update_error:
print(f"Failed to update customer auth_net_profile_id to NULL: {update_error}") logger.debug(f"Failed to update customer auth_net_profile_id to NULL: {update_error}")
db.rollback() # Rollback on error db.rollback() # Rollback on error
return { return {
@@ -112,7 +115,7 @@ def verify_customer_authorize_account(db: Session, customer_id: int) -> dict:
} }
except Exception as e: except Exception as e:
print(f"Error verifying customer authorize account for customer {customer_id}: {str(e)}") logger.debug(f"Error verifying customer authorize account for customer {customer_id}: {str(e)}")
return { return {
"profile_exists": False, "profile_exists": False,
"has_payment_methods": False, "has_payment_methods": False,
@@ -163,7 +166,7 @@ def _is_profile_valid(response) -> bool:
return True return True
except Exception as e: except Exception as e:
print(f"Error validating profile response: {str(e)}") logger.debug(f"Error validating profile response: {str(e)}")
return False return False
@@ -204,5 +207,5 @@ def _get_customer_profile(profile_id: str):
return response return response
except Exception as e: except Exception as e:
print(f"Error getting customer profile {profile_id}: {str(e)}") logger.debug(f"Error getting customer profile {profile_id}: {str(e)}")
return None return None

View File

@@ -1,9 +1,11 @@
## File: your_app/services/payment_service.py ## File: your_app/services/payment_service.py
import pprint import logging
import traceback import traceback
import re import re
from authorizenet import apicontractsv1 from authorizenet import apicontractsv1
logger = logging.getLogger(__name__)
from authorizenet.apicontrollers import ( from authorizenet.apicontrollers import (
createTransactionController, createTransactionController,
createCustomerProfileController, createCustomerProfileController,
@@ -55,19 +57,19 @@ def _is_e00121_response(response):
if isinstance(message, list): if isinstance(message, list):
for msg in message: for msg in message:
if getattr(msg, 'code', '') == 'E00121': if getattr(msg, 'code', '') == 'E00121':
print("E00121 detected in message list") logger.debug("E00121 detected in message list")
return True return True
# Handle single message # Handle single message
elif hasattr(message, 'code'): elif hasattr(message, 'code'):
if message.code == 'E00121': if message.code == 'E00121':
print(f"E00121 detected: '{getattr(message, 'text', 'No details')}'") logger.debug(f"E00121 detected: '{getattr(message, 'text', 'No details')}'")
return True return True
else: else:
print(f"Message code: '{message.code}' (not E00121)") logger.debug(f"Message code: '{message.code}' (not E00121)")
return False return False
except Exception as e: except Exception as e:
print(f"Error checking for E00121: {str(e)}") logger.debug(f"Error checking for E00121: {str(e)}")
return False return False
def _get_authnet_error_message(response): def _get_authnet_error_message(response):
@@ -91,7 +93,7 @@ def _get_authnet_error_message(response):
text = msg.text if hasattr(msg, 'text') else 'No details provided.' text = msg.text if hasattr(msg, 'text') else 'No details provided.'
return f"Error {code}: {text}" return f"Error {code}: {text}"
except Exception as e: except Exception as e:
print(f"Error while parsing Auth.Net error message: {e}") logger.debug(f"Error while parsing Auth.Net error message: {e}")
return "An unparsable error occurred with the payment gateway." return "An unparsable error occurred with the payment gateway."
return "An unknown error occurred with the payment gateway." return "An unknown error occurred with the payment gateway."
@@ -101,13 +103,11 @@ def create_customer_profile(customer: schemas.Customer, card_info: schemas.CardC
Creates a new customer profile in Authorize.Net (payment profiles added separately). Creates a new customer profile in Authorize.Net (payment profiles added separately).
This version sanitizes and trims customer data before sending. This version sanitizes and trims customer data before sending.
""" """
print(f"Attempting to create Auth.Net profile for customer ID: {customer.id}") # Note: Never log API credentials
print(API_LOGIN_ID)
print(TRANSACTION_KEY)
try: try:
merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY)
except Exception as e: except Exception as e:
print(e) pass # Will be handled by request failure below
# API max lengths: email=255 # API max lengths: email=255
email = (customer.customer_email or f"no-email-{customer.id}@example.com")[:255] email = (customer.customer_email or f"no-email-{customer.id}@example.com")[:255]
@@ -138,26 +138,25 @@ def create_customer_profile(customer: schemas.Customer, card_info: schemas.CardC
# Check if response is None (API call failed) # Check if response is None (API call failed)
if response is None: if response is None:
print("ERROR: Authorize.net API call returned None - likely a network/connectivity issue") logger.debug("ERROR: Authorize.net API call returned None - likely a network/connectivity issue")
raise ValueError("Could not connect to the payment gateway. Please check network connectivity.") raise ValueError("Could not connect to the payment gateway. Please check network connectivity.")
try: try:
if response.messages.resultCode == "Ok": if response.messages.resultCode == "Ok":
profile_id = response.customerProfileId profile_id = response.customerProfileId
print(profile_id) logger.debug(profile_id)
# # Payment profile ID is not available since profiles are added separately # # Payment profile ID is not available since profiles are added separately
# payment_id = "" # payment_id = ""
print(f"SUCCESS: Created customer profile: {profile_id} (payment profiles added separately)") logger.debug(f"SUCCESS: Created customer profile: {profile_id} (payment profiles added separately)")
# Add detailed logging # Add detailed logging
print(f"API Response - Profile ID: {profile_id}") logger.debug(f"API Response - Profile ID: {profile_id}")
print(f"Returning: profile_id='{str(profile_id)}', payment_id=''") logger.debug(f"Returning: profile_id='{str(profile_id)}', payment_id=''")
return str(profile_id), "" return str(profile_id), ""
else: else:
error_msg = _get_authnet_error_message(response) error_msg = _get_authnet_error_message(response)
print(f"Failed to create customer profile (API Error): {error_msg}") logger.debug(f"Failed to create customer profile (API Error): {error_msg}")
print(f"Full API Response: {pprint.pformat(vars(response))}")
raise ValueError(error_msg) raise ValueError(error_msg)
except ValueError: except ValueError:
@@ -165,7 +164,7 @@ def create_customer_profile(customer: schemas.Customer, card_info: schemas.CardC
# Re-raise specific ValueError messages we already set above (like E00039) # Re-raise specific ValueError messages we already set above (like E00039)
raise raise
except Exception as e: except Exception as e:
print(f"A critical exception occurred during the API call: {traceback.format_exc()}") logger.debug(f"A critical exception occurred during the API call: {traceback.format_exc()}")
raise ValueError("Could not connect to the payment gateway.") raise ValueError("Could not connect to the payment gateway.")
@@ -175,24 +174,24 @@ def authorize_customer_profile(customer_profile_id: str, payment_profile_id: str
Creates an AUTH_ONLY transaction against a customer profile with automatic E00121 recovery. Creates an AUTH_ONLY transaction against a customer profile with automatic E00121 recovery.
This holds funds but doesn't capture them, and automatically recovers from invalid payment profiles. This holds funds but doesn't capture them, and automatically recovers from invalid payment profiles.
""" """
print(f"Authorizing profile {customer_profile_id} / payment {payment_profile_id} for ${transaction_req.preauthorize_amount}") logger.debug(f"Authorizing profile {customer_profile_id} / payment {payment_profile_id} for ${transaction_req.preauthorize_amount}")
# Validate inputs # Validate inputs
if not customer_profile_id or customer_profile_id.strip() == "": if not customer_profile_id or customer_profile_id.strip() == "":
print("INVALID: customer_profile_id is None or empty") logger.debug("INVALID: customer_profile_id is None or empty")
if not payment_profile_id or payment_profile_id.strip() == "": if not payment_profile_id or payment_profile_id.strip() == "":
print("INVALID: payment_profile_id is None or empty") logger.debug("INVALID: payment_profile_id is None or empty")
print("Payment profile ID must be a valid, non-empty string") logger.debug("Payment profile ID must be a valid, non-empty string")
# FIRST ATTEMPT - Normal authorization # FIRST ATTEMPT - Normal authorization
print("TRANSACTION ATTEMPT 1: Standard authorization") logger.debug("TRANSACTION ATTEMPT 1: Standard authorization")
response = _perform_authorization(customer_profile_id, payment_profile_id, transaction_req) response = _perform_authorization(customer_profile_id, payment_profile_id, transaction_req)
# CHECK FOR E00121 ERROR - "invalid payment profile ID" # CHECK FOR E00121 ERROR - "invalid payment profile ID"
if db_session and customer_id and card_id and _is_e00121_response(response): if db_session and customer_id and card_id and _is_e00121_response(response):
print(f"E00121 DETECTED! Invalid payment profile {payment_profile_id}") logger.debug(f"E00121 DETECTED! Invalid payment profile {payment_profile_id}")
print("POOOP") logger.debug("POOOP")
print(f"AUTO-RECOVERING: Starting payment profile refresh for customer {customer_id}") logger.debug(f"AUTO-RECOVERING: Starting payment profile refresh for customer {customer_id}")
try: try:
# GET CUSTOMER PROFILE ID (since we have customer_id but need profile_id) # GET CUSTOMER PROFILE ID (since we have customer_id but need profile_id)
@@ -200,7 +199,7 @@ def authorize_customer_profile(customer_profile_id: str, payment_profile_id: str
customer = crud.get_customer(db_session, customer_id) customer = crud.get_customer(db_session, customer_id)
if customer: if customer:
# REFRESH ALL PAYMENT PROFILES FOR THIS CUSTOMER # REFRESH ALL PAYMENT PROFILES FOR THIS CUSTOMER
print(f"CALLING REFRESH: customer_id={customer_id}, profile_id={customer.auth_net_profile_id}") logger.debug(f"CALLING REFRESH: customer_id={customer_id}, profile_id={customer.auth_net_profile_id}")
from .user_create import refresh_customer_payment_profiles from .user_create import refresh_customer_payment_profiles
refresh_customer_payment_profiles(db_session, customer_id, customer.auth_net_profile_id) refresh_customer_payment_profiles(db_session, customer_id, customer.auth_net_profile_id)
@@ -208,25 +207,25 @@ def authorize_customer_profile(customer_profile_id: str, payment_profile_id: str
updated_card = crud.get_card_by_id(db_session, card_id) updated_card = crud.get_card_by_id(db_session, card_id)
if updated_card and updated_card.auth_net_payment_profile_id != payment_profile_id: if updated_card and updated_card.auth_net_payment_profile_id != payment_profile_id:
new_payment_profile_id = updated_card.auth_net_payment_profile_id new_payment_profile_id = updated_card.auth_net_payment_profile_id
print(f"RECOVERY SUCCESS: Old ID '{payment_profile_id}' → New ID '{new_payment_profile_id}'") logger.debug(f"RECOVERY SUCCESS: Old ID '{payment_profile_id}' → New ID '{new_payment_profile_id}'")
# SECOND ATTEMPT - With refreshed payment profile ID # SECOND ATTEMPT - With refreshed payment profile ID
print("TRANSACTION ATTEMPT 2: Retry with refreshed payment profile") logger.debug("TRANSACTION ATTEMPT 2: Retry with refreshed payment profile")
response = _perform_authorization(customer_profile_id, new_payment_profile_id, transaction_req) response = _perform_authorization(customer_profile_id, new_payment_profile_id, transaction_req)
if _is_e00121_response(response): if _is_e00121_response(response):
print("E00121 STILL PERSISTS after refresh - manual intervention may be needed") logger.debug("E00121 STILL PERSISTS after refresh - manual intervention may be needed")
print(f"Payment profile {new_payment_profile_id} also rejected by Authorize.Net") logger.debug(f"Payment profile {new_payment_profile_id} also rejected by Authorize.Net")
else: else:
print(f"SUCCESS! E00121 RESOLVED - Transaction succeeded with refreshed payment profile {new_payment_profile_id}") logger.debug(f"SUCCESS! E00121 RESOLVED - Transaction succeeded with refreshed payment profile {new_payment_profile_id}")
else: else:
print(f"RECOVERY FAILED: No updated payment profile ID found for card {card_id}") logger.debug(f"RECOVERY FAILED: No updated payment profile ID found for card {card_id}")
print("Database refresh did not provide new payment profile ID") logger.debug("Database refresh did not provide new payment profile ID")
else: else:
print(f"RECOVERY FAILED: Customer {customer_id} not found in database") logger.debug(f"RECOVERY FAILED: Customer {customer_id} not found in database")
except Exception as e: except Exception as e:
print(f"AUTO-RECOVERY FAILED: {str(e)}") logger.debug(f"AUTO-RECOVERY FAILED: {str(e)}")
print("Exception during payment profile refresh process") logger.debug("Exception during payment profile refresh process")
return response return response
@@ -271,9 +270,9 @@ def _perform_authorization(customer_profile_id: str, payment_profile_id: str, tr
# Log response details # Log response details
if response is not None and hasattr(response, 'messages'): if response is not None and hasattr(response, 'messages'):
result_code = getattr(response.messages, 'resultCode', 'Unknown') result_code = getattr(response.messages, 'resultCode', 'Unknown')
print(f"✅ Authorize response: resultCode='{result_code}'") logger.debug(f"✅ Authorize response: resultCode='{result_code}'")
else: else:
print("✅ Authorize response: No standard response structure") logger.debug("✅ Authorize response: No standard response structure")
return response return response
@@ -283,7 +282,7 @@ def _perform_authorization(customer_profile_id: str, payment_profile_id: str, tr
def capture_authorized_transaction(transaction_req: schemas.TransactionCapture): def capture_authorized_transaction(transaction_req: schemas.TransactionCapture):
"""Captures a previously authorized transaction.""" """Captures a previously authorized transaction."""
print(f"Capturing transaction {transaction_req.auth_net_transaction_id} for {transaction_req.charge_amount}") logger.debug(f"Capturing transaction {transaction_req.auth_net_transaction_id} for {transaction_req.charge_amount}")
merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY)
@@ -312,7 +311,7 @@ def capture_authorized_transaction(transaction_req: schemas.TransactionCapture):
def add_payment_profile_to_customer(customer_profile_id: str, customer: schemas.Customer, card_info: schemas.CardCreate, is_default: bool = False): def add_payment_profile_to_customer(customer_profile_id: str, customer: schemas.Customer, card_info: schemas.CardCreate, is_default: bool = False):
print(f"Adding {'default ' if is_default else ''}payment profile to Auth.Net customer profile ID: {customer_profile_id}") logger.debug(f"Adding {'default ' if is_default else ''}payment profile to Auth.Net customer profile ID: {customer_profile_id}")
merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY)
@@ -348,7 +347,7 @@ def add_payment_profile_to_customer(customer_profile_id: str, customer: schemas.
else: else:
expiration_date = "0325" expiration_date = "0325"
print(f"Parsed expiration date for card: {card_info.expiration_date} -> {expiration_date}") # Expiration date parsed successfully
creditCard = apicontractsv1.creditCardType( creditCard = apicontractsv1.creditCardType(
cardNumber=card_info.card_number, cardNumber=card_info.card_number,
@@ -396,7 +395,7 @@ def add_payment_profile_to_customer(customer_profile_id: str, customer: schemas.
# Check if response is None (API call failed) # Check if response is None (API call failed)
if response is None: if response is None:
print("ERROR: Authorize.net API call returned None - likely a network/connectivity issue") logger.debug("ERROR: Authorize.net API call returned None - likely a network/connectivity issue")
raise ValueError("Could not connect to the payment gateway. Please check network connectivity.") raise ValueError("Could not connect to the payment gateway. Please check network connectivity.")
if response.messages.resultCode == "Ok": if response.messages.resultCode == "Ok":
@@ -404,20 +403,15 @@ def add_payment_profile_to_customer(customer_profile_id: str, customer: schemas.
if hasattr(response, 'customerPaymentProfileId') and response.customerPaymentProfileId: if hasattr(response, 'customerPaymentProfileId') and response.customerPaymentProfileId:
return str(response.customerPaymentProfileId) return str(response.customerPaymentProfileId)
else: else:
print("WARNING: Added payment profile but no ID returned") logger.debug("WARNING: Added payment profile but no ID returned")
raise ValueError("Payment profile created but ID not found in response") raise ValueError("Payment profile created but ID not found in response")
else: else:
error_msg = _get_authnet_error_message(response) error_msg = _get_authnet_error_message(response)
print(f"Failed to add payment profile: {error_msg}") logger.debug(f"Failed to add payment profile: {error_msg}")
print(f"SANITIZED DATA SENT FOR ADD PROFILE: FirstName='{first_name}', LastName='{last_name}', Address='{address}', City='{city}', State='{state}', Zip='{zip_code}'")
print(f"Card info: number='{card_info.card_number}', exp='{card_info.expiration_date}', cvv='{card_info.cvv}'") # Mask if sensitive
print(pprint.pformat(vars(billTo)))
print(pprint.pformat(vars(request)))
raise ValueError(error_msg) raise ValueError(error_msg)
except Exception as e: except Exception as e:
print(f"A critical exception occurred during the API call: {traceback.format_exc()}") logger.debug(f"A critical exception occurred during the API call: {traceback.format_exc()}")
raise ValueError("Could not connect to the payment gateway.") raise ValueError("Could not connect to the payment gateway.")
@@ -426,7 +420,7 @@ def get_customer_payment_profiles(customer_profile_id: str):
Retrieves all payment profile IDs for a given customer profile from Authorize.net. Retrieves all payment profile IDs for a given customer profile from Authorize.net.
Returns a list of payment profile IDs in the order they were created. Returns a list of payment profile IDs in the order they were created.
""" """
print(f"Retrieving payment profiles for customer profile ID: {customer_profile_id}") logger.debug(f"Retrieving payment profiles for customer profile ID: {customer_profile_id}")
merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY)
@@ -452,7 +446,7 @@ def get_customer_payment_profiles(customer_profile_id: str):
# Check if response is None (API call failed) # Check if response is None (API call failed)
if response is None: if response is None:
print("ERROR: Authorize.net API call returned None - likely a network/connectivity issue") logger.debug("ERROR: Authorize.net API call returned None - likely a network/connectivity issue")
raise ValueError("Could not connect to the payment gateway. Please check network connectivity.") raise ValueError("Could not connect to the payment gateway. Please check network connectivity.")
if response.messages.resultCode == "Ok": if response.messages.resultCode == "Ok":
@@ -461,15 +455,15 @@ def get_customer_payment_profiles(customer_profile_id: str):
for profile in response.profile.paymentProfiles: for profile in response.profile.paymentProfiles:
payment_profile_ids.append(str(profile.customerPaymentProfileId)) payment_profile_ids.append(str(profile.customerPaymentProfileId))
print(f"Retrieved {len(payment_profile_ids)} payment profile IDs for profile {customer_profile_id}") logger.debug(f"Retrieved {len(payment_profile_ids)} payment profile IDs for profile {customer_profile_id}")
return payment_profile_ids return payment_profile_ids
else: else:
error_msg = _get_authnet_error_message(response) error_msg = _get_authnet_error_message(response)
print(f"Failed to retrieve customer profile {customer_profile_id}: {error_msg}") logger.debug(f"Failed to retrieve customer profile {customer_profile_id}: {error_msg}")
raise ValueError(f"Could not retrieve customer profile: {error_msg}") raise ValueError(f"Could not retrieve customer profile: {error_msg}")
except Exception as e: except Exception as e:
print(f"Critical exception while retrieving customer profile {customer_profile_id}: {traceback.format_exc()}") logger.debug(f"Critical exception while retrieving customer profile {customer_profile_id}: {traceback.format_exc()}")
raise ValueError("Could not connect to the payment gateway.") raise ValueError("Could not connect to the payment gateway.")
@@ -478,7 +472,7 @@ def charge_customer_profile(customer_profile_id: str, payment_profile_id: str, t
Creates an AUTH_CAPTURE transaction (charge now) against a customer profile. Creates an AUTH_CAPTURE transaction (charge now) against a customer profile.
This charges the customer immediately for the full amount. This charges the customer immediately for the full amount.
""" """
print(f"Charging profile {customer_profile_id} / payment {payment_profile_id} for ${transaction_req.charge_amount}") logger.debug(f"Charging profile {customer_profile_id} / payment {payment_profile_id} for ${transaction_req.charge_amount}")
merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY) merchantAuth = apicontractsv1.merchantAuthenticationType(name=API_LOGIN_ID, transactionKey=TRANSACTION_KEY)

View File

@@ -1,7 +1,8 @@
import logging import logging
import pprint
import traceback import traceback
from authorizenet import apicontractsv1 from authorizenet import apicontractsv1
logger = logging.getLogger(__name__)
from authorizenet.apicontrollers import ( from authorizenet.apicontrollers import (
createCustomerProfileController, createCustomerProfileController,
createCustomerPaymentProfileController createCustomerPaymentProfileController
@@ -64,7 +65,7 @@ def create_user_account(db: Session, customer_id: int) -> dict:
"message": f"Customer {customer_id} not found", "message": f"Customer {customer_id} not found",
"profile_id": None "profile_id": None
} }
print(f"Found customer id={customer}") logger.debug(f"Found customer id={customer}")
# Get customer's cards from database # Get customer's cards from database
cards = crud.get_customer_cards(db, customer_id) cards = crud.get_customer_cards(db, customer_id)
if not cards: if not cards:
@@ -79,9 +80,7 @@ def create_user_account(db: Session, customer_id: int) -> dict:
# Get the first card to use for initial profile creation # Get the first card to use for initial profile creation
first_card = cards[0] first_card = cards[0]
print(f"Using first card ID={first_card.id} for profile creation") logger.debug(f"Using card ID={first_card.id} (****{first_card.card_number[-4:] if first_card.card_number else '----'}) for profile creation")
print(f"Card Number: {first_card.card_number[:4]}**** ****{first_card.card_number[-4:]}")
print(f"Expiration: {first_card.expiration_month}/{first_card.expiration_year}")
# Create CardCreate object for the first card # Create CardCreate object for the first card
# Format expiration date for string values - pad year to 4 digits and month to 2 digits # Format expiration date for string values - pad year to 4 digits and month to 2 digits
@@ -97,8 +96,7 @@ def create_user_account(db: Session, customer_id: int) -> dict:
cvv=first_card.security_number cvv=first_card.security_number
) )
print(f"Card info expiration_date: {card_info.expiration_date}") logger.debug(f"Processing Authorize.net profile for customer {customer_id} with {len(cards)} cards")
print(f"Processing Authorize.net profile for customer {customer_id} with {len(cards)} cards")
# Create customer profile and payment profiles if not exists # Create customer profile and payment profiles if not exists
if not customer.auth_net_profile_id: if not customer.auth_net_profile_id:
@@ -107,7 +105,7 @@ def create_user_account(db: Session, customer_id: int) -> dict:
auth_profile_id, _ = payment_service.create_customer_profile(customer, card_info) auth_profile_id, _ = payment_service.create_customer_profile(customer, card_info)
except ValueError as e: except ValueError as e:
error_str = str(e) error_str = str(e)
print(f"API call failed: {error_str}") logger.debug(f"API call failed: {error_str}")
return { return {
"success": False, "success": False,
@@ -118,7 +116,7 @@ def create_user_account(db: Session, customer_id: int) -> dict:
} }
if not auth_profile_id: if not auth_profile_id:
print("No auth_profile_id returned from API") logger.debug("No auth_profile_id returned from API")
return { return {
"success": False, "success": False,
"message": "Failed to create customer profile - no profile ID returned", "message": "Failed to create customer profile - no profile ID returned",
@@ -130,12 +128,12 @@ def create_user_account(db: Session, customer_id: int) -> dict:
first_payment_profile_id = payment_service.add_payment_profile_to_customer( first_payment_profile_id = payment_service.add_payment_profile_to_customer(
auth_profile_id, customer, card_info, is_default=True auth_profile_id, customer, card_info, is_default=True
) )
print(f"Successfully added first payment profile: {first_payment_profile_id} (default)") logger.debug(f"Successfully added first payment profile: {first_payment_profile_id} (default)")
# Assign to first_card # Assign to first_card
first_card.auth_net_payment_profile_id = first_payment_profile_id first_card.auth_net_payment_profile_id = first_payment_profile_id
db.add(first_card) db.add(first_card)
except ValueError as e: except ValueError as e:
print(f"Failed to add payment profile for first card: {str(e)}") logger.debug(f"Failed to add payment profile for first card: {str(e)}")
return { return {
"success": False, "success": False,
"message": f"Failed to add first payment profile: {str(e)}", "message": f"Failed to add first payment profile: {str(e)}",
@@ -162,19 +160,19 @@ def create_user_account(db: Session, customer_id: int) -> dict:
payment_profile_id = payment_service.add_payment_profile_to_customer( payment_profile_id = payment_service.add_payment_profile_to_customer(
auth_profile_id, customer, card_info_additional, is_default=False auth_profile_id, customer, card_info_additional, is_default=False
) )
print(f"Successfully added additional payment profile ID '{payment_profile_id}' for card {card.id}") logger.debug(f"Successfully added additional payment profile ID '{payment_profile_id}' for card {card.id}")
except ValueError as e: except ValueError as e:
print(f"Failed to add payment profile for additional card {card.id}: {str(e)}") logger.debug(f"Failed to add payment profile for additional card {card.id}: {str(e)}")
else: else:
auth_profile_id = customer.auth_net_profile_id auth_profile_id = customer.auth_net_profile_id
print(f"Using existing Authorize.net profile {auth_profile_id}") logger.debug(f"Using existing Authorize.net profile {auth_profile_id}")
# RETRIEVE ALL PAYMENT PROFILE IDs - This is the key step # RETRIEVE ALL PAYMENT PROFILE IDs - This is the key step
try: try:
payment_profile_ids = payment_service.get_customer_payment_profiles(auth_profile_id) payment_profile_ids = payment_service.get_customer_payment_profiles(auth_profile_id)
print(f"DEBUG: Retrieved {len(payment_profile_ids)} payment profile IDs: {payment_profile_ids}") logger.debug(f"DEBUG: Retrieved {len(payment_profile_ids)} payment profile IDs: {payment_profile_ids}")
except ValueError as e: except ValueError as e:
print(f"Failed to retrieve payment profiles: {str(e)}") logger.debug(f"Failed to retrieve payment profiles: {str(e)}")
return { return {
"success": False, "success": False,
"message": f"Failed to retrieve payment profiles: {str(e)}", "message": f"Failed to retrieve payment profiles: {str(e)}",
@@ -183,21 +181,21 @@ def create_user_account(db: Session, customer_id: int) -> dict:
# Assign payment profile IDs to cards # Assign payment profile IDs to cards
num_to_update = min(len(cards), len(payment_profile_ids)) num_to_update = min(len(cards), len(payment_profile_ids))
print(f"Assigning {num_to_update} payment profile IDs to cards") logger.debug(f"Assigning {num_to_update} payment profile IDs to cards")
if len(payment_profile_ids) != len(cards): if len(payment_profile_ids) != len(cards):
print(f"Mismatch between payment profile count ({len(payment_profile_ids)}) and card count ({len(cards)})") logger.debug(f"Mismatch between payment profile count ({len(payment_profile_ids)}) and card count ({len(cards)})")
print("This could cause incorrect payment profile assignments!") logger.debug("This could cause incorrect payment profile assignments!")
cards_updated = 0 cards_updated = 0
for i in range(num_to_update): for i in range(num_to_update):
if payment_profile_ids[i] and str(payment_profile_ids[i]).strip(): # Validate the ID exists and isn't empty if payment_profile_ids[i] and str(payment_profile_ids[i]).strip(): # Validate the ID exists and isn't empty
cards[i].auth_net_payment_profile_id = str(payment_profile_ids[i]) # Ensure string cards[i].auth_net_payment_profile_id = str(payment_profile_ids[i]) # Ensure string
db.add(cards[i]) db.add(cards[i])
print(f"Successfully assigned payment profile ID '{payment_profile_ids[i]}' to card {cards[i].id}") logger.debug(f"Successfully assigned payment profile ID '{payment_profile_ids[i]}' to card {cards[i].id}")
cards_updated += 1 cards_updated += 1
else: else:
print(f"Missing or invalid payment profile ID '{payment_profile_ids[i]}' for card {cards[i].id}") logger.debug(f"Missing or invalid payment profile ID '{payment_profile_ids[i]}' for card {cards[i].id}")
# Save customer profile ID if not set (handle both new and existing case) # Save customer profile ID if not set (handle both new and existing case)
if not customer.auth_net_profile_id: if not customer.auth_net_profile_id:
@@ -206,35 +204,35 @@ def create_user_account(db: Session, customer_id: int) -> dict:
# Commit all changes # Commit all changes
db.commit() db.commit()
print(f"Successfully committed payment profile IDs to database ({cards_updated} cards updated)") logger.debug(f"Successfully committed payment profile IDs to database ({cards_updated} cards updated)")
# Enhanced verification - check what was actually saved # Enhanced verification - check what was actually saved
print("Verifying payment profile IDs were saved correctly:") logger.debug("Verifying payment profile IDs were saved correctly:")
all_saved_correctly = True all_saved_correctly = True
for i, card in enumerate(cards[:num_to_update]): for i, card in enumerate(cards[:num_to_update]):
committed_card = crud.get_card_by_id(db, card.id) committed_card = crud.get_card_by_id(db, card.id)
if committed_card and committed_card.auth_net_payment_profile_id: if committed_card and committed_card.auth_net_payment_profile_id:
print(f"SUCCESS: Card {card.id} has payment profile ID '{committed_card.auth_net_payment_profile_id}'") logger.debug(f"SUCCESS: Card {card.id} has payment profile ID '{committed_card.auth_net_payment_profile_id}'")
else: else:
print(f"ERROR: Card {card.id} is missing payment profile ID") logger.debug(f"ERROR: Card {card.id} is missing payment profile ID")
all_saved_correctly = False all_saved_correctly = False
if not all_saved_correctly: if not all_saved_correctly:
print("PAYMENT PROFILE ASSIGNMENT ERRORS DETECTED - This may cause transaction failures!") logger.debug("PAYMENT PROFILE ASSIGNMENT ERRORS DETECTED - This may cause transaction failures!")
operation_type = "created" if not original_profile_id else "updated" operation_type = "created" if not original_profile_id else "updated"
print(f"Successfully {operation_type} Authorize.net profile {auth_profile_id} for customer {customer_id} with {len(cards)} cards") logger.debug(f"Successfully {operation_type} Authorize.net profile {auth_profile_id} for customer {customer_id} with {len(cards)} cards")
# 🔄 PROACTIVELY REFRESH PAYMENT PROFILES TO ENSURE VALIDITY # 🔄 PROACTIVELY REFRESH PAYMENT PROFILES TO ENSURE VALIDITY
print(f"🔄 Auto-refresh START: customer_id={customer_id}, auth_profile_id={auth_profile_id}") logger.debug(f"🔄 Auto-refresh START: customer_id={customer_id}, auth_profile_id={auth_profile_id}")
print(f"🔄 Auto-refresh BEFORE: Cards have these payment profile IDs: {[f'card_{c.id}={c.auth_net_payment_profile_id}' for c in cards]}") logger.debug(f"🔄 Auto-refresh BEFORE: Cards have these payment profile IDs: {[f'card_{c.id}={c.auth_net_payment_profile_id}' for c in cards]}")
# Check what changed after refresh # Check what changed after refresh
cards_after = crud.get_customer_cards(db, customer_id) cards_after = crud.get_customer_cards(db, customer_id)
print(f"🔄 Auto-refresh AFTER: Cards now have these payment profile IDs: {[f'card_{c.id}={c.auth_net_payment_profile_id}' for c in cards_after]}") logger.debug(f"🔄 Auto-refresh AFTER: Cards now have these payment profile IDs: {[f'card_{c.id}={c.auth_net_payment_profile_id}' for c in cards_after]}")
print(f"🔄 Auto-refresh COMPLETE - IDs changed: {len([c for c in cards if c.auth_net_payment_profile_id != cards_after[cards.index(c)].auth_net_payment_profile_id])} cards updated") logger.debug(f"🔄 Auto-refresh COMPLETE - IDs changed: {len([c for c in cards if c.auth_net_payment_profile_id != cards_after[cards.index(c)].auth_net_payment_profile_id])} cards updated")
return { return {
"success": True, "success": True,
@@ -244,7 +242,7 @@ def create_user_account(db: Session, customer_id: int) -> dict:
} }
except Exception as e: except Exception as e:
print(f"Critical exception during user account creation for customer {customer_id}: {traceback.format_exc()}") logger.debug(f"Critical exception during user account creation for customer {customer_id}: {traceback.format_exc()}")
db.rollback() db.rollback()
return { return {
"success": False, "success": False,
@@ -275,31 +273,31 @@ def refresh_customer_payment_profiles(db: Session, customer_id: int, auth_profil
# Get customer's current cards from database # Get customer's current cards from database
cards_before = crud.get_customer_cards(db, customer_id) cards_before = crud.get_customer_cards(db, customer_id)
customer = crud.get_customer(db, customer_id) customer = crud.get_customer(db, customer_id)
print(f"🔄 Refresh START: customer_id={customer_id}, profile_id={auth_profile_id}, current cards={len(cards_before)}") logger.debug(f"🔄 Refresh START: customer_id={customer_id}, profile_id={auth_profile_id}, current cards={len(cards_before)}")
# STEP 1: Try to get actual payment profiles from Authorize.net # STEP 1: Try to get actual payment profiles from Authorize.net
payment_profile_ids = [] payment_profile_ids = []
try: try:
payment_profile_ids = payment_service.get_customer_payment_profiles(auth_profile_id) payment_profile_ids = payment_service.get_customer_payment_profiles(auth_profile_id)
print(f"🔄 Retrieved {len(payment_profile_ids)} payment profiles from Authorize.net: {payment_profile_ids}") logger.debug(f"🔄 Retrieved {len(payment_profile_ids)} payment profiles from Authorize.net: {payment_profile_ids}")
except Exception as e: except Exception as e:
print(f"🔄 Could not retrieve payment profiles from Authorize.net: {str(e)}") logger.debug(f"🔄 Could not retrieve payment profiles from Authorize.net: {str(e)}")
print("🔄 Will attempt to recreate missing payment profiles") logger.debug("🔄 Will attempt to recreate missing payment profiles")
# STEP 2: Check if we have enough payment profiles for our cards # STEP 2: Check if we have enough payment profiles for our cards
cards_need_update = [] cards_need_update = []
for card in cards_before: for card in cards_before:
if not card.auth_net_payment_profile_id or card.auth_net_payment_profile_id.strip() == "": if not card.auth_net_payment_profile_id or card.auth_net_payment_profile_id.strip() == "":
cards_need_update.append(card) cards_need_update.append(card)
print(f"🔄 Card {card.id} needs payment profile ID assignment") logger.debug(f"🔄 Card {card.id} needs payment profile ID assignment")
elif str(card.auth_net_payment_profile_id) not in [str(pid) for pid in payment_profile_ids if pid]: elif str(card.auth_net_payment_profile_id) not in [str(pid) for pid in payment_profile_ids if pid]:
# Payment profile ID exists in DB but not found in Authorize.net - likely invalid # Payment profile ID exists in DB but not found in Authorize.net - likely invalid
cards_need_update.append(card) cards_need_update.append(card)
print(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} but it's not found in Authorize.net - NEEDS RECREATION") logger.debug(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} but it's not found in Authorize.net - NEEDS RECREATION")
else: else:
if ApplicationConfig.penny_test_transaction: if ApplicationConfig.penny_test_transaction:
# Profile exists in Authorize.net, but let's double-check it's usable by doing a quick test # Profile exists in Authorize.net, but let's double-check it's usable by doing a quick test
print(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} in Authorize.net - testing usability...") logger.debug(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} in Authorize.net - testing usability...")
try: try:
test_req = schemas.TransactionAuthorizeByCardID( test_req = schemas.TransactionAuthorizeByCardID(
card_id=card.id, card_id=card.id,
@@ -316,33 +314,33 @@ def refresh_customer_payment_profiles(db: Session, customer_id: int, auth_profil
_, _, test_reason = payment_service._parse_authnet_response(test_response) _, _, test_reason = payment_service._parse_authnet_response(test_response)
if "E00121" in str(test_reason): if "E00121" in str(test_reason):
cards_need_update.append(card) cards_need_update.append(card)
print(f"🔄 Card {card.id} has profile {card.auth_net_payment_profile_id} that EXISTS but is CORRUPTED - NEEDS RECREATION") logger.debug(f"🔄 Card {card.id} has profile {card.auth_net_payment_profile_id} that EXISTS but is CORRUPTED - NEEDS RECREATION")
# Explicitly delete the corrupted profile first # Explicitly delete the corrupted profile first
try: try:
from . import user_delete from . import user_delete
delete_success = user_delete._delete_payment_profile(customer.auth_net_profile_id, card.auth_net_payment_profile_id) delete_success = user_delete._delete_payment_profile(customer.auth_net_profile_id, card.auth_net_payment_profile_id)
if delete_success: if delete_success:
print(f"🔄 Successfully deleted corrupted payment profile {card.auth_net_payment_profile_id}") logger.debug(f"🔄 Successfully deleted corrupted payment profile {card.auth_net_payment_profile_id}")
card.auth_net_payment_profile_id = None card.auth_net_payment_profile_id = None
db.add(card) db.add(card)
except Exception as del_e: except Exception as del_e:
print(f"🔄 Failed to delete corrupted profile {card.auth_net_payment_profile_id}: {str(del_e)}") logger.debug(f"🔄 Failed to delete corrupted profile {card.auth_net_payment_profile_id}: {str(del_e)}")
else: else:
print(f"🔄 Card {card.id} has valid and usable payment profile ID {card.auth_net_payment_profile_id}") logger.debug(f"🔄 Card {card.id} has valid and usable payment profile ID {card.auth_net_payment_profile_id}")
except Exception as test_e: except Exception as test_e:
print(f"🔄 Could not test usability of profile {card.auth_net_payment_profile_id} for card {card.id}: {str(test_e)} - assuming it's okay") logger.debug(f"🔄 Could not test usability of profile {card.auth_net_payment_profile_id} for card {card.id}: {str(test_e)} - assuming it's okay")
else: else:
print(f"🔄 Skipping penny test transaction for card {card.id} (disabled in config)") logger.debug(f"🔄 Skipping penny test transaction for card {card.id} (disabled in config)")
print(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} in Authorize.net - skipping usability test (config disabled)") logger.debug(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} in Authorize.net - skipping usability test (config disabled)")
# STEP 3: If we don't have enough valid payment profiles, recreate missing ones # STEP 3: If we don't have enough valid payment profiles, recreate missing ones
if len(cards_need_update) > 0: if len(cards_need_update) > 0:
print(f"🔄 Need to recreate {len(cards_need_update)} payment profiles") logger.debug(f"🔄 Need to recreate {len(cards_need_update)} payment profiles")
# Clear payment profile IDs for cards that need recreation (they're invalid anyway) # Clear payment profile IDs for cards that need recreation (they're invalid anyway)
for card in cards_need_update: for card in cards_need_update:
if card.auth_net_payment_profile_id: if card.auth_net_payment_profile_id:
print(f"🔄 Clearing invalid payment profile ID {card.auth_net_payment_profile_id} for card {card.id}") logger.debug(f"🔄 Clearing invalid payment profile ID {card.auth_net_payment_profile_id} for card {card.id}")
card.auth_net_payment_profile_id = None card.auth_net_payment_profile_id = None
db.add(card) db.add(card)
@@ -364,7 +362,7 @@ def refresh_customer_payment_profiles(db: Session, customer_id: int, auth_profil
cvv=card.security_number cvv=card.security_number
) )
print(f"🔄 Recreating payment profile for card {card.id} (**** **** **** {card.last_four_digits})") logger.debug(f"🔄 Recreating payment profile for card {card.id} (**** **** **** {card.last_four_digits})")
new_payment_profile_id = payment_service.add_payment_profile_to_customer( new_payment_profile_id = payment_service.add_payment_profile_to_customer(
auth_profile_id, customer, card_create_data, is_default=(card.main_card == True) auth_profile_id, customer, card_create_data, is_default=(card.main_card == True)
) )
@@ -373,43 +371,43 @@ def refresh_customer_payment_profiles(db: Session, customer_id: int, auth_profil
card.auth_net_payment_profile_id = str(new_payment_profile_id) card.auth_net_payment_profile_id = str(new_payment_profile_id)
db.add(card) db.add(card)
recreated_cards.append(card) recreated_cards.append(card)
print(f"✅ Successfully recreated payment profile {new_payment_profile_id} for card {card.id}") logger.debug(f"✅ Successfully recreated payment profile {new_payment_profile_id} for card {card.id}")
else: else:
print(f"❌ Failed to recreate payment profile for card {card.id} - no ID returned") logger.debug(f"❌ Failed to recreate payment profile for card {card.id} - no ID returned")
except Exception as e: except Exception as e:
print(f"❌ Failed to recreate payment profile for card {card.id}: {str(e)}") logger.debug(f"❌ Failed to recreate payment profile for card {card.id}: {str(e)}")
continue continue
if recreated_cards: if recreated_cards:
db.commit() db.commit()
print(f"✅ Successfully recreated and saved {len(recreated_cards)} payment profiles") logger.debug(f"✅ Successfully recreated and saved {len(recreated_cards)} payment profiles")
else: else:
print("❌ No payment profiles could be recreated - this is a critical failure") logger.debug("❌ No payment profiles could be recreated - this is a critical failure")
return False return False
else: else:
print(f"🔄 All {len(cards_before)} cards have valid payment profile IDs") logger.debug(f"🔄 All {len(cards_before)} cards have valid payment profile IDs")
# STEP 4: Final verification that everything looks good # STEP 4: Final verification that everything looks good
cards_final = crud.get_customer_cards(db, customer_id) cards_final = crud.get_customer_cards(db, customer_id)
print("🔄 FINAL VERIFICATION:") logger.debug("🔄 FINAL VERIFICATION:")
all_valid = True all_valid = True
for card in cards_final: for card in cards_final:
status = "✅ VALID" if card.auth_net_payment_profile_id and card.auth_net_payment_profile_id.strip() else "❌ INVALID" status = "✅ VALID" if card.auth_net_payment_profile_id and card.auth_net_payment_profile_id.strip() else "❌ INVALID"
print(f"🔄 {status} Card {card.id}: auth_net_payment_profile_id='{card.auth_net_payment_profile_id}'") logger.debug(f"🔄 {status} Card {card.id}: auth_net_payment_profile_id='{card.auth_net_payment_profile_id}'")
if not card.auth_net_payment_profile_id or card.auth_net_payment_profile_id.strip() == "": if not card.auth_net_payment_profile_id or card.auth_net_payment_profile_id.strip() == "":
all_valid = False all_valid = False
if all_valid: if all_valid:
print(f"🔄 Refresh COMPLETE: All {len(cards_final)} cards have valid payment profile IDs") logger.debug(f"🔄 Refresh COMPLETE: All {len(cards_final)} cards have valid payment profile IDs")
return True return True
else: else:
print("🔄 Refresh PARTIAL: Some cards may still have invalid payment profile IDs") logger.debug("🔄 Refresh PARTIAL: Some cards may still have invalid payment profile IDs")
return False return False
except Exception as e: except Exception as e:
print(f"🔄 Refresh FAILED for customer {customer_id}: {str(e)}") logger.debug(f"🔄 Refresh FAILED for customer {customer_id}: {str(e)}")
print(f"🔄 Refresh traceback: {traceback.format_exc()}") logger.debug(f"🔄 Refresh traceback: {traceback.format_exc()}")
db.rollback() db.rollback()
return False return False

View File

@@ -1,5 +1,8 @@
import logging
import traceback import traceback
from authorizenet import apicontractsv1 from authorizenet import apicontractsv1
logger = logging.getLogger(__name__)
from authorizenet.apicontrollers import ( from authorizenet.apicontrollers import (
deleteCustomerProfileController, deleteCustomerProfileController,
deleteCustomerPaymentProfileController deleteCustomerPaymentProfileController
@@ -53,7 +56,7 @@ def _get_authnet_error_message(response):
text = msg.text if hasattr(msg, 'text') else 'No details provided.' text = msg.text if hasattr(msg, 'text') else 'No details provided.'
return f"Error {code}: {text}" return f"Error {code}: {text}"
except Exception as e: except Exception as e:
print(f"Error while parsing Auth.Net error message: {e}") logger.debug(f"Error while parsing Auth.Net error message: {e}")
return "An unparsable error occurred with the payment gateway." return "An unparsable error occurred with the payment gateway."
return "An unknown error occurred with the payment gateway." return "An unknown error occurred with the payment gateway."
@@ -98,29 +101,29 @@ def delete_user_account(db: Session, customer_id: int) -> dict:
# Get customer's payment profiles/cards from database # Get customer's payment profiles/cards from database
cards = crud.get_customer_cards(db, customer_id) cards = crud.get_customer_cards(db, customer_id)
print(f"Starting deletion of Authorize.net account for customer {customer_id} (Profile ID: {profile_id_to_delete})") logger.debug(f"Starting deletion of Authorize.net account for customer {customer_id} (Profile ID: {profile_id_to_delete})")
# Step 1: Delete payment profiles first (must delete these before customer profile) # Step 1: Delete payment profiles first (must delete these before customer profile)
deleted_payment_profiles = [] deleted_payment_profiles = []
if cards: if cards:
print(f"Found {len(cards)} cards to delete from Authorize.net") logger.debug(f"Found {len(cards)} cards to delete from Authorize.net")
for card_index, card in enumerate(cards): for card_index, card in enumerate(cards):
if card.auth_net_payment_profile_id: if card.auth_net_payment_profile_id:
try: try:
print(f"Deleting payment profile {card.auth_net_payment_profile_id} for card {card.id}") logger.debug(f"Deleting payment profile {card.auth_net_payment_profile_id} for card {card.id}")
# Delete payment profile from Authorize.net # Delete payment profile from Authorize.net
success = _delete_payment_profile(profile_id_to_delete, card.auth_net_payment_profile_id) success = _delete_payment_profile(profile_id_to_delete, card.auth_net_payment_profile_id)
if success: if success:
deleted_payment_profiles.append(card.auth_net_payment_profile_id) deleted_payment_profiles.append(card.auth_net_payment_profile_id)
print(f"Successfully deleted payment profile {card.auth_net_payment_profile_id}") logger.debug(f"Successfully deleted payment profile {card.auth_net_payment_profile_id}")
else: else:
print(f"Failed to delete payment profile {card.auth_net_payment_profile_id} - it may not exist or already deleted") logger.debug(f"Failed to delete payment profile {card.auth_net_payment_profile_id} - it may not exist or already deleted")
except Exception as e: except Exception as e:
print(f"Error deleting payment profile {card.auth_net_payment_profile_id}: {str(e)}") logger.debug(f"Error deleting payment profile {card.auth_net_payment_profile_id}: {str(e)}")
# Continue with other payment profiles - we want to delete as much as possible # Continue with other payment profiles - we want to delete as much as possible
# Always null out the payment profile ID in database (even if API delete failed) # Always null out the payment profile ID in database (even if API delete failed)
@@ -128,7 +131,7 @@ def delete_user_account(db: Session, customer_id: int) -> dict:
db.add(card) db.add(card)
# Step 2: Delete customer profile # Step 2: Delete customer profile
print(f"Deleting customer profile {profile_id_to_delete}") logger.debug(f"Deleting customer profile {profile_id_to_delete}")
profile_deleted_success = _delete_customer_profile(profile_id_to_delete) profile_deleted_success = _delete_customer_profile(profile_id_to_delete)
# Step 3: Update database regardless of API results # Step 3: Update database regardless of API results
@@ -139,7 +142,7 @@ def delete_user_account(db: Session, customer_id: int) -> dict:
db.commit() db.commit()
if profile_deleted_success: if profile_deleted_success:
print(f"Successfully deleted Authorize.net account for customer {customer_id}") logger.debug(f"Successfully deleted Authorize.net account for customer {customer_id}")
return { return {
"success": True, "success": True,
"message": f"Successfully deleted Authorize.net account with profile ID {profile_id_to_delete}", "message": f"Successfully deleted Authorize.net account with profile ID {profile_id_to_delete}",
@@ -148,7 +151,7 @@ def delete_user_account(db: Session, customer_id: int) -> dict:
"deleted_payment_profiles": deleted_payment_profiles "deleted_payment_profiles": deleted_payment_profiles
} }
else: else:
print(f"Customer profile {profile_id_to_delete} may not have been completely removed from Authorize.net, but database has been updated") logger.debug(f"Customer profile {profile_id_to_delete} may not have been completely removed from Authorize.net, but database has been updated")
return { return {
"success": False, "success": False,
"message": f"Profile {profile_id_to_delete} may not have been completely removed from Authorize.net, but database has been cleaned up", "message": f"Profile {profile_id_to_delete} may not have been completely removed from Authorize.net, but database has been cleaned up",
@@ -158,7 +161,7 @@ def delete_user_account(db: Session, customer_id: int) -> dict:
} }
except Exception as e: except Exception as e:
print(f"Critical exception during account deletion for customer {customer_id}: {traceback.format_exc()}") logger.debug(f"Critical exception during account deletion for customer {customer_id}: {traceback.format_exc()}")
db.rollback() db.rollback()
return { return {
"success": False, "success": False,
@@ -200,23 +203,23 @@ def _delete_customer_profile(profile_id: str) -> bool:
response = controller.getresponse() response = controller.getresponse()
if response is None: if response is None:
print(f"No response received when trying to delete profile {profile_id}") logger.debug(f"No response received when trying to delete profile {profile_id}")
return False return False
if hasattr(response, 'messages') and response.messages.resultCode == "Ok": if hasattr(response, 'messages') and response.messages.resultCode == "Ok":
print(f"Successfully deleted customer profile {profile_id}") logger.debug(f"Successfully deleted customer profile {profile_id}")
return True return True
else: else:
error_msg = _get_authnet_error_message(response) error_msg = _get_authnet_error_message(response)
print(f"Failed to delete customer profile {profile_id}: {error_msg}") logger.debug(f"Failed to delete customer profile {profile_id}: {error_msg}")
# Still count as success if the profile was already deleted/not found # Still count as success if the profile was already deleted/not found
if "not found" in error_msg.lower() or "E00040" in error_msg or "E00035" in error_msg: if "not found" in error_msg.lower() or "E00040" in error_msg or "E00035" in error_msg:
print(f"Profile {profile_id} was already deleted or doesn't exist") logger.debug(f"Profile {profile_id} was already deleted or doesn't exist")
return True return True
return False return False
except Exception as e: except Exception as e:
print(f"Exception during delete customer profile {profile_id}: {str(e)}") logger.debug(f"Exception during delete customer profile {profile_id}: {str(e)}")
return False return False
@@ -255,21 +258,21 @@ def _delete_payment_profile(customer_profile_id: str, payment_profile_id: str) -
response = controller.getresponse() response = controller.getresponse()
if response is None: if response is None:
print(f"No response received when trying to delete payment profile {payment_profile_id}") logger.debug(f"No response received when trying to delete payment profile {payment_profile_id}")
return False return False
if hasattr(response, 'messages') and response.messages.resultCode == "Ok": if hasattr(response, 'messages') and response.messages.resultCode == "Ok":
print(f"Successfully deleted payment profile {payment_profile_id}") logger.debug(f"Successfully deleted payment profile {payment_profile_id}")
return True return True
else: else:
error_msg = _get_authnet_error_message(response) error_msg = _get_authnet_error_message(response)
print(f"Failed to delete payment profile {payment_profile_id}: {error_msg}") logger.debug(f"Failed to delete payment profile {payment_profile_id}: {error_msg}")
# Still count as success if the payment profile was already deleted/not found # Still count as success if the payment profile was already deleted/not found
if "not found" in error_msg.lower() or "E00040" in error_msg or "E00035" in error_msg: if "not found" in error_msg.lower() or "E00040" in error_msg or "E00035" in error_msg:
print(f"Payment profile {payment_profile_id} was already deleted or doesn't exist") logger.debug(f"Payment profile {payment_profile_id} was already deleted or doesn't exist")
return True return True
return False return False
except Exception as e: except Exception as e:
print(f"Exception during delete payment profile {payment_profile_id}: {str(e)}") logger.debug(f"Exception during delete payment profile {payment_profile_id}: {str(e)}")
return False return False

View File

@@ -3,7 +3,6 @@ import os
def load_config(mode=os.environ.get('MODE')): def load_config(mode=os.environ.get('MODE')):
try: try:
print(f"mode is {mode}")
if mode == 'PRODUCTION': if mode == 'PRODUCTION':
from settings_prod import ApplicationConfig from settings_prod import ApplicationConfig
return ApplicationConfig return ApplicationConfig
@@ -22,4 +21,4 @@ def load_config(mode=os.environ.get('MODE')):
except ImportError: except ImportError:
from settings_dev import ApplicationConfig from settings_dev import ApplicationConfig
return ApplicationConfig return ApplicationConfig

View File

@@ -1,7 +1,15 @@
fastapi # eamco_authorize dependencies
uvicorn # FastAPI web framework and server
sqlalchemy fastapi==0.115.6
psycopg2-binary uvicorn==0.34.0
pydantic pydantic==2.10.5
python-dotenv
authorizenet # Database
SQLAlchemy==2.0.40
psycopg2-binary==2.9.10
# Configuration
python-dotenv==1.1.0
# Authorize.net SDK
authorizenet==1.1.4

View File

@@ -1,39 +1,40 @@
import os
class ApplicationConfig: class ApplicationConfig:
""" """
Basic Configuration for a generic User Development Configuration (Sandbox/Testing)
""" """
print("USING TESTING APPLICATIONCONFIG!!!!!")
CURRENT_SETTINGS = 'DEVELOPMENT' CURRENT_SETTINGS = 'DEVELOPMENT'
# databases info
POSTGRES_USERNAME = 'postgres' # Database credentials from environment variables
POSTGRES_PW = 'password' POSTGRES_USERNAME = os.environ.get('POSTGRES_USERNAME', 'postgres')
POSTGRES_SERVER = '192.168.1.204' POSTGRES_PW = os.environ.get('POSTGRES_PW')
POSTGRES_PORT = '5432' POSTGRES_SERVER = os.environ.get('POSTGRES_SERVER', '192.168.1.204')
POSTGRES_DBNAME00 = 'eamco' POSTGRES_PORT = os.environ.get('POSTGRES_PORT', '5432')
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(POSTGRES_USERNAME, POSTGRES_DBNAME00 = os.environ.get('POSTGRES_DBNAME', 'eamco')
POSTGRES_PW,
POSTGRES_SERVER, SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(
POSTGRES_DBNAME00 POSTGRES_USERNAME,
) POSTGRES_PW,
POSTGRES_SERVER,
POSTGRES_DBNAME00
)
SQLALCHEMY_BINDS = {'eamco': SQLALCHEMY_DATABASE_URI} SQLALCHEMY_BINDS = {'eamco': SQLALCHEMY_DATABASE_URI}
origins = [ origins = [
"http://localhost:9000", "http://localhost:9000",
"https://localhost:9513", "https://localhost:9513",
"http://localhost:9514", "http://localhost:9514",
"http://localhost:9512", "http://localhost:9512",
"http://localhost:9511", "http://localhost:9511",
"http://localhost:5173", # Frontend port "http://localhost:5173",
"http://localhost:9516", # Authorize service port "http://localhost:9516",
]
] # Authorize.net credentials from environment variables (dev/sandbox)
API_LOGIN_ID = '9U6w96gZmX' API_LOGIN_ID = os.environ.get('AUTHORIZE_API_LOGIN_ID_DEV')
TRANSACTION_KEY = '94s6Qy458mMNJr7G' TRANSACTION_KEY = os.environ.get('AUTHORIZE_TRANSACTION_KEY_DEV')
# # # Authorize.net credentials (Sandbox Test Credentials) # Payment processing flags
# API_LOGIN_ID = '5KP3u95bQpv' penny_test_transaction = False
# TRANSACTION_KEY = '346HZ32z3fP4hTG2'
penny_test_transaction = False # Run penny test in development

View File

@@ -1,39 +1,40 @@
import os
class ApplicationConfig: class ApplicationConfig:
""" """
Basic Configuration for a generic User Local Configuration (LAN deployment)
""" """
print("USING LOCAL APPLICATION CONFIG")
CURRENT_SETTINGS = 'LOCAL' CURRENT_SETTINGS = 'LOCAL'
# databases info
POSTGRES_USERNAME = 'postgres' # Database credentials from environment variables
POSTGRES_PW = 'password' POSTGRES_USERNAME = os.environ.get('POSTGRES_USERNAME', 'postgres')
POSTGRES_SERVER = '192.168.1.204' POSTGRES_PW = os.environ.get('POSTGRES_PW')
POSTGRES_PORT = '5432' POSTGRES_SERVER = os.environ.get('POSTGRES_SERVER', '192.168.1.204')
POSTGRES_DBNAME00 = 'auburnoil' POSTGRES_PORT = os.environ.get('POSTGRES_PORT', '5432')
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(POSTGRES_USERNAME, POSTGRES_DBNAME00 = os.environ.get('POSTGRES_DBNAME', 'auburnoil')
POSTGRES_PW,
POSTGRES_SERVER, SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(
POSTGRES_DBNAME00 POSTGRES_USERNAME,
) POSTGRES_PW,
POSTGRES_SERVER,
POSTGRES_DBNAME00
)
SQLALCHEMY_BINDS = {'auburnoil': SQLALCHEMY_DATABASE_URI} SQLALCHEMY_BINDS = {'auburnoil': SQLALCHEMY_DATABASE_URI}
origins = [ origins = [
"http://192.168.1.204:9000", "http://192.168.1.204:9000",
"http://192.168.1.204:9613", "http://192.168.1.204:9613",
"http://192.168.1.204:9614", "http://192.168.1.204:9614",
"http://192.168.1.204:9612", "http://192.168.1.204:9612",
"http://192.168.1.204:9616", "http://192.168.1.204:9616",
"http://192.168.1.204:9611", "http://192.168.1.204:9611",
"http://192.168.1.204:9511", "http://192.168.1.204:9511",
] ]
# Authorize.net credentials # Authorize.net credentials from environment variables
API_LOGIN_ID = '4d2Mn6H23R' API_LOGIN_ID = os.environ.get('AUTHORIZE_API_LOGIN_ID')
TRANSACTION_KEY = '7B94d8xfTQXv37WS' TRANSACTION_KEY = os.environ.get('AUTHORIZE_TRANSACTION_KEY')
# Payment processing flags # Payment processing flags
penny_test_transaction = False # Run penny test in development penny_test_transaction = False

View File

@@ -1,30 +1,35 @@
import os
class ApplicationConfig: class ApplicationConfig:
""" """
Basic Configuration for a generic User Production Configuration
""" """
print("USING PROD APPLICATIONCONFIG!!!!!")
CURRENT_SETTINGS = 'PRODUCTION' CURRENT_SETTINGS = 'PRODUCTION'
# databases info
POSTGRES_USERNAME = 'postgres' # Database credentials from environment variables
POSTGRES_PW = 'password' POSTGRES_USERNAME = os.environ.get('POSTGRES_USERNAME', 'postgres')
POSTGRES_SERVER = '192.168.1.204' POSTGRES_PW = os.environ.get('POSTGRES_PW')
POSTGRES_PORT = '5432' POSTGRES_SERVER = os.environ.get('POSTGRES_SERVER', '192.168.1.204')
POSTGRES_DBNAME00 = 'auburnoil' POSTGRES_PORT = os.environ.get('POSTGRES_PORT', '5432')
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(POSTGRES_USERNAME, POSTGRES_DBNAME00 = os.environ.get('POSTGRES_DBNAME', 'auburnoil')
POSTGRES_PW,
POSTGRES_SERVER, SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://{}:{}@{}/{}".format(
POSTGRES_DBNAME00 POSTGRES_USERNAME,
) POSTGRES_PW,
POSTGRES_SERVER,
POSTGRES_DBNAME00
)
SQLALCHEMY_BINDS = {'auburnoil': SQLALCHEMY_DATABASE_URI} SQLALCHEMY_BINDS = {'auburnoil': SQLALCHEMY_DATABASE_URI}
origins = [ origins = [
"https://oil.edwineames.com", "https://oil.edwineames.com",
"https://apiauto.edwineames.com", "https://apiauto.edwineames.com",
] ]
# Authorize.net credentials # Authorize.net credentials from environment variables
API_LOGIN_ID = '4d2Mn6H23R' API_LOGIN_ID = os.environ.get('AUTHORIZE_API_LOGIN_ID')
TRANSACTION_KEY = '7B94d8xfTQXv37WS' TRANSACTION_KEY = os.environ.get('AUTHORIZE_TRANSACTION_KEY')
# Payment processing flags # Payment processing flags
penny_test_transaction = False # Skip penny test in production penny_test_transaction = False # Skip penny test in production