config issues prod
This commit is contained in:
@@ -263,3 +263,158 @@ def create_user_account(db: Session, customer_id: int) -> dict:
|
||||
"message": f"An unexpected error occurred: {str(e)}",
|
||||
"profile_id": None
|
||||
}
|
||||
|
||||
|
||||
def refresh_customer_payment_profiles(db: Session, customer_id: int, auth_profile_id: str) -> bool:
|
||||
"""
|
||||
Refresh payment profiles for a customer by syncing from Authorize.net to database.
|
||||
This ensures database payment_profile_ids stay in sync with Authorize.net.
|
||||
NOW WITH RECREATION FALLBACK: If no payment profiles exist in Authorize.net,
|
||||
recreates them from stored card data instead of failing.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
customer_id: ID of the customer
|
||||
auth_profile_id: Authorize.net customer profile ID
|
||||
|
||||
Returns:
|
||||
bool: True if refresh successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Import here to avoid circular imports
|
||||
from .. import crud
|
||||
|
||||
# Get customer's current cards from database
|
||||
cards_before = crud.get_customer_cards(db, customer_id)
|
||||
customer = crud.get_customer(db, customer_id)
|
||||
logger.info(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
|
||||
payment_profile_ids = []
|
||||
try:
|
||||
payment_profile_ids = payment_service.get_customer_payment_profiles(auth_profile_id)
|
||||
logger.info(f"🔄 Retrieved {len(payment_profile_ids)} payment profiles from Authorize.net: {payment_profile_ids}")
|
||||
except Exception as e:
|
||||
logger.warning(f"🔄 Could not retrieve payment profiles from Authorize.net: {str(e)}")
|
||||
logger.info("🔄 Will attempt to recreate missing payment profiles")
|
||||
|
||||
# STEP 2: Check if we have enough payment profiles for our cards
|
||||
cards_need_update = []
|
||||
for card in cards_before:
|
||||
if not card.auth_net_payment_profile_id or card.auth_net_payment_profile_id.strip() == "":
|
||||
cards_need_update.append(card)
|
||||
logger.info(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]:
|
||||
# Payment profile ID exists in DB but not found in Authorize.net - likely invalid
|
||||
cards_need_update.append(card)
|
||||
logger.warning(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:
|
||||
# Profile exists in Authorize.net, but let's double-check it's usable by doing a quick test
|
||||
logger.info(f"🔄 Card {card.id} has payment profile ID {card.auth_net_payment_profile_id} in Authorize.net - testing usability...")
|
||||
try:
|
||||
test_req = schemas.TransactionAuthorizeByCardID(
|
||||
card_id=card.id,
|
||||
preauthorize_amount="0.01"
|
||||
)
|
||||
test_response = payment_service.authorize_customer_profile(
|
||||
customer_profile_id=customer.auth_net_profile_id,
|
||||
payment_profile_id=card.auth_net_payment_profile_id,
|
||||
transaction_req=test_req,
|
||||
db_session=None, customer_id=None, card_id=None
|
||||
)
|
||||
|
||||
# Check test result
|
||||
_, _, test_reason = payment_service._parse_authnet_response(test_response)
|
||||
if "E00121" in str(test_reason):
|
||||
cards_need_update.append(card)
|
||||
logger.warning(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
|
||||
try:
|
||||
from . import user_delete
|
||||
delete_success = user_delete._delete_payment_profile(customer.auth_net_profile_id, card.auth_net_payment_profile_id)
|
||||
if delete_success:
|
||||
logger.info(f"🔄 Successfully deleted corrupted payment profile {card.auth_net_payment_profile_id}")
|
||||
card.auth_net_payment_profile_id = None
|
||||
db.add(card)
|
||||
except Exception as del_e:
|
||||
logger.warning(f"🔄 Failed to delete corrupted profile {card.auth_net_payment_profile_id}: {str(del_e)}")
|
||||
else:
|
||||
logger.debug(f"🔄 Card {card.id} has valid and usable payment profile ID {card.auth_net_payment_profile_id}")
|
||||
except Exception as test_e:
|
||||
logger.warning(f"🔄 Could not test usability of profile {card.auth_net_payment_profile_id} for card {card.id}: {str(test_e)} - assuming it's okay")
|
||||
|
||||
# STEP 3: If we don't have enough valid payment profiles, recreate missing ones
|
||||
if len(cards_need_update) > 0:
|
||||
logger.info(f"🔄 Need to recreate {len(cards_need_update)} payment profiles")
|
||||
|
||||
# Clear payment profile IDs for cards that need recreation (they're invalid anyway)
|
||||
for card in cards_need_update:
|
||||
if card.auth_net_payment_profile_id:
|
||||
logger.info(f"🔄 Clearing invalid payment profile ID {card.auth_net_payment_profile_id} for card {card.id}")
|
||||
card.auth_net_payment_profile_id = None
|
||||
db.add(card)
|
||||
|
||||
# Recreate payment profiles for cards that need them
|
||||
recreated_cards = []
|
||||
for card in cards_need_update:
|
||||
try:
|
||||
# Format expiration date for recreation
|
||||
exp_year = card.expiration_year.zfill(4) if len(card.expiration_year) < 4 else card.expiration_year
|
||||
exp_month = card.expiration_month.zfill(2) if len(card.expiration_month) < 2 else card.expiration_month
|
||||
exp_date = f"{exp_year}-{exp_month}"
|
||||
|
||||
card_create_data = schemas.CardCreate(
|
||||
card_number=card.card_number,
|
||||
expiration_date=exp_date,
|
||||
cvv=card.security_number
|
||||
)
|
||||
|
||||
logger.info(f"🔄 Recreating payment profile for card {card.id} (**** **** **** {card.last_four_digits})")
|
||||
new_payment_profile_id = payment_service.add_payment_profile_to_customer(
|
||||
auth_profile_id, customer, card_create_data, is_default=(card.main_card == True)
|
||||
)
|
||||
|
||||
if new_payment_profile_id:
|
||||
card.auth_net_payment_profile_id = str(new_payment_profile_id)
|
||||
db.add(card)
|
||||
recreated_cards.append(card)
|
||||
logger.info(f"✅ Successfully recreated payment profile {new_payment_profile_id} for card {card.id}")
|
||||
else:
|
||||
logger.error(f"❌ Failed to recreate payment profile for card {card.id} - no ID returned")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to recreate payment profile for card {card.id}: {str(e)}")
|
||||
continue
|
||||
|
||||
if recreated_cards:
|
||||
db.commit()
|
||||
logger.info(f"✅ Successfully recreated and saved {len(recreated_cards)} payment profiles")
|
||||
else:
|
||||
logger.error("❌ No payment profiles could be recreated - this is a critical failure")
|
||||
return False
|
||||
else:
|
||||
logger.info(f"🔄 All {len(cards_before)} cards have valid payment profile IDs")
|
||||
|
||||
# STEP 4: Final verification that everything looks good
|
||||
cards_final = crud.get_customer_cards(db, customer_id)
|
||||
logger.info("🔄 FINAL VERIFICATION:")
|
||||
all_valid = True
|
||||
for card in cards_final:
|
||||
status = "✅ VALID" if card.auth_net_payment_profile_id and card.auth_net_payment_profile_id.strip() else "❌ INVALID"
|
||||
logger.info(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() == "":
|
||||
all_valid = False
|
||||
|
||||
if all_valid:
|
||||
logger.info(f"🔄 Refresh COMPLETE: All {len(cards_final)} cards have valid payment profile IDs")
|
||||
return True
|
||||
else:
|
||||
logger.warning("🔄 Refresh PARTIAL: Some cards may still have invalid payment profile IDs")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"🔄 Refresh FAILED for customer {customer_id}: {str(e)}")
|
||||
logger.error(f"🔄 Refresh traceback: {traceback.format_exc()}")
|
||||
db.rollback()
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user