Updated charge close to working

This commit is contained in:
2025-09-09 18:28:41 -04:00
parent 8c37b6aeab
commit 8d134f691b
15 changed files with 40 additions and 113 deletions
+4
View File
@@ -0,0 +1,4 @@
__pycache__/
*.pyc
*.pyo
*.pyd
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+9 -8
View File
@@ -12,17 +12,17 @@ def get_customers(db: Session, skip: int = 0, limit: int = 100):
def create_transaction(db: Session, transaction: schemas.TransactionBase, customer_id: int, status: int, auth_net_transaction_id: str = None): def create_transaction(db: Session, transaction: schemas.TransactionBase, customer_id: int, status: int, auth_net_transaction_id: str = None):
db_transaction = models.Transaction( db_transaction = models.Transaction(
preauthorize_amount=transaction.preauthorize_amount, preauthorize_amount=transaction.preauthorize_amount if status == 0 else 0, # Only save pre-auth amount if approved
charge_amount=transaction.charge_amount, charge_amount=transaction.charge_amount if transaction.transaction_type != 0 or status == 0 else 0, # Only save charge amount for charges if approved
transaction_type=transaction.transaction_type, transaction_type=transaction.transaction_type,
customer_id=customer_id, customer_id=customer_id,
status=status, status=status,
auth_net_transaction_id=auth_net_transaction_id, auth_net_transaction_id=auth_net_transaction_id,
service_id=transaction.service_id, service_id=transaction.service_id,
delivery_id=transaction.delivery_id, delivery_id=transaction.delivery_id,
card_id=transaction.card_id, card_id=transaction.card_id,
payment_gateway=transaction.payment_gateway, payment_gateway=transaction.payment_gateway,
rejection_reason=transaction.rejection_reason rejection_reason=transaction.rejection_reason
) )
db.add(db_transaction) db.add(db_transaction)
db.commit() db.commit()
@@ -50,7 +50,8 @@ def update_transaction_for_capture(db: Session, auth_net_transaction_id: str, ch
if not transaction: if not transaction:
return None return None
transaction.charge_amount = charge_amount # Set charge_amount only if approved (status == 0), otherwise set to 0
transaction.charge_amount = charge_amount if status == 0 else 0
transaction.transaction_type = 3 # capture transaction.transaction_type = 3 # capture
transaction.status = status transaction.status = status
if rejection_reason: if rejection_reason:
@@ -58,4 +59,4 @@ def update_transaction_for_capture(db: Session, auth_net_transaction_id: str, ch
db.commit() db.commit()
db.refresh(transaction) db.refresh(transaction)
return transaction return transaction
Binary file not shown.
Binary file not shown.
+24 -9
View File
@@ -34,19 +34,39 @@ def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[Transa
Parses the response from the Authorize.Net service. Parses the response from the Authorize.Net service.
(This is the same helper from before, it's a good change to keep) (This is the same helper from before, it's a good change to keep)
""" """
if response and hasattr(response, 'messages') and response.messages.resultCode == "Ok": if response is not None and hasattr(response, 'messages') and response.messages.resultCode == "Ok":
status = TransactionStatus.APPROVED status = TransactionStatus.APPROVED
auth_net_transaction_id = str(response.transactionResponse.transId) if hasattr(response, 'transactionResponse') else None auth_net_transaction_id = str(response.transactionResponse.transId) if hasattr(response, 'transactionResponse') else None
rejection_reason = None rejection_reason = None
else: else:
status = TransactionStatus.DECLINED status = TransactionStatus.DECLINED
auth_net_transaction_id = None auth_net_transaction_id = None
if hasattr(response, '_rejection_reason'):
# Improved rejection reason extraction
rejection_reason = "Payment declined by gateway."
if hasattr(response, '_rejection_reason') and response._rejection_reason:
rejection_reason = str(response._rejection_reason) rejection_reason = str(response._rejection_reason)
elif response is not None:
# Check transaction response for errors
if hasattr(response, 'transactionResponse') and response.transactionResponse:
tr = response.transactionResponse
if hasattr(tr, 'errors') and tr.errors:
for error in tr.errors:
if hasattr(error, 'errorCode') and hasattr(error, 'errorText'):
error_code = error.errorCode.text if error.errorCode else "Unknown"
error_text = error.errorText.text if error.errorText else "No error details"
rejection_reason = f"{error_code}: {error_text}"
break
elif hasattr(tr, 'messages') and tr.messages:
if len(tr.messages) > 0:
msg = tr.messages[0]
if hasattr(msg, 'code') and hasattr(msg, 'description'):
code = msg.code.text if msg.code else "Unknown"
desc = msg.description.text if msg.description else "No description"
rejection_reason = f"{code}: {desc}"
elif response is None: elif response is None:
rejection_reason = "No response received from payment gateway." rejection_reason = "No response received from payment gateway."
else:
rejection_reason = "Payment declined by gateway."
return status, auth_net_transaction_id, rejection_reason return status, auth_net_transaction_id, rejection_reason
@@ -74,9 +94,6 @@ def authorize_card(customer_id: int, transaction: schemas.TransactionAuthorize,
@router.post("/charge/{customer_id}", response_model=schemas.Transaction) @router.post("/charge/{customer_id}", response_model=schemas.Transaction)
def charge_card(customer_id: int, transaction: schemas.TransactionCreate, db: Session = Depends(database.get_db)): def charge_card(customer_id: int, transaction: schemas.TransactionCreate, db: Session = Depends(database.get_db)):
# Add debug logging
print(f"DEBUG: Received charge request for customer_id: {customer_id}")
print(f"DEBUG: Transaction data: {transaction.dict() if hasattr(transaction, 'dict') else transaction}")
try: try:
auth_net_response = payment_service.charge_credit_card(transaction) auth_net_response = payment_service.charge_credit_card(transaction)
@@ -90,7 +107,6 @@ def charge_card(customer_id: int, transaction: schemas.TransactionCreate, db: Se
card_id=transaction.card_id, card_id=transaction.card_id,
rejection_reason=rejection_reason rejection_reason=rejection_reason
) )
print(f"DEBUG: Transaction data to create: {transaction_data.dict()}")
result = crud.create_transaction( result = crud.create_transaction(
db=db, db=db,
@@ -99,7 +115,6 @@ def charge_card(customer_id: int, transaction: schemas.TransactionCreate, db: Se
status=status, status=status,
auth_net_transaction_id=auth_net_transaction_id auth_net_transaction_id=auth_net_transaction_id
) )
print(f"DEBUG: Created transaction: {result.dict()}")
return result return result
except Exception as e: except Exception as e:
print(f"DEBUG: Exception in charge_card: {str(e)}") print(f"DEBUG: Exception in charge_card: {str(e)}")
+3 -96
View File
@@ -55,46 +55,15 @@ def charge_credit_card(transaction: schemas.TransactionCreate):
response = controller.getresponse() response = controller.getresponse()
# Extract rejection reason if payment failed # Log response status if payment failed
rejection_reason = None
if response is not None and response.messages is not None: if response is not None and response.messages is not None:
logger.info(f"Charge response: {response.messages.resultCode}") logger.info(f"Charge response: {response.messages.resultCode}")
# If payment was declined (resultCode is "Error"), extract error details
if response.messages.resultCode == "Error":
rejection_reason = "Authorize.Net Charge Error"
if hasattr(response.messages, 'message'):
try:
if len(response.messages.message) > 0:
for msg in response.messages.message:
if hasattr(msg, 'code') and hasattr(msg, 'text'):
# Convert lxml StringElement objects to Python strings
code_str = msg.code.text if msg.code else "Unknown"
text_str = msg.text.text if msg.text else "No details available"
rejection_reason = f"{code_str}: {text_str}"
break # Use the first error message
elif hasattr(msg, 'text'):
# Convert lxml StringElement to Python string
text_str = msg.text.text if msg.text else "No details available"
rejection_reason = f"Error: {text_str}"
break
else:
rejection_reason = "Charge declined - no specific error details available"
except Exception as e:
rejection_reason = f"Charge declined - error details could not be parsed: {str(e)}"
else:
rejection_reason = "Charge declined - no error message available"
if hasattr(response.messages, 'message') and len(response.messages.message) > 0: if hasattr(response.messages, 'message') and len(response.messages.message) > 0:
for msg in response.messages.message: for msg in response.messages.message:
logger.info(f"Message: {msg.text.text if msg.text else 'No message text'}") logger.info(f"Message: {msg.text.text if msg.text else 'No message text'}")
else: else:
logger.error("No response from Authorize.net") logger.error("No response from Authorize.net")
rejection_reason = "No response received from Authorize.Net"
# Attach rejection reason to response for the router to use
if response is not None:
response._rejection_reason = rejection_reason
return response return response
@@ -128,46 +97,15 @@ def authorize_credit_card(transaction: schemas.TransactionAuthorize):
response = controller.getresponse() response = controller.getresponse()
# Extract rejection reason if payment failed # Log response status
rejection_reason = None
if response is not None and response.messages is not None: if response is not None and response.messages is not None:
logger.info(f"Preauthorization response: {response.messages.resultCode}") logger.info(f"Preauthorization response: {response.messages.resultCode}")
# If payment was declined (resultCode is "Error"), extract error details
if response.messages.resultCode == "Error":
rejection_reason = "Authorize.Net Error"
if hasattr(response.messages, 'message'):
try:
if len(response.messages.message) > 0:
for msg in response.messages.message:
if hasattr(msg, 'code') and hasattr(msg, 'text'):
# Convert lxml StringElement objects to Python strings
code_str = msg.code.text if msg.code else "Unknown"
text_str = msg.text.text if msg.text else "No details available"
rejection_reason = f"{code_str}: {text_str}"
break # Use the first error message
elif hasattr(msg, 'text'):
# Convert lxml StringElement to Python string
text_str = msg.text.text if msg.text else "No details available"
rejection_reason = f"Error: {text_str}"
break
else:
rejection_reason = "Payment declined - no specific error details available"
except Exception as e:
rejection_reason = f"Payment declined - error details could not be parsed: {str(e)}"
else:
rejection_reason = "Payment declined - no error message available"
if hasattr(response.messages, 'message') and len(response.messages.message) > 0: if hasattr(response.messages, 'message') and len(response.messages.message) > 0:
for msg in response.messages.message: for msg in response.messages.message:
logger.info(f"Message: {msg.text.text if msg.text else 'No message text'}") logger.info(f"Message: {msg.text.text if msg.text else 'No message text'}")
else: else:
logger.error("No response from Authorize.net for preauthorization") logger.error("No response from Authorize.net for preauthorization")
rejection_reason = "No response received from Authorize.Net"
# Attach rejection reason to response for the router to use
if response is not None:
response._rejection_reason = rejection_reason
return response return response
@@ -191,45 +129,14 @@ def capture_authorized_transaction(transaction: schemas.TransactionCapture):
response = controller.getresponse() response = controller.getresponse()
# Extract rejection reason if capture failed # Log response status
rejection_reason = None
if response is not None and response.messages is not None: if response is not None and response.messages is not None:
logger.info(f"Capture response: {response.messages.resultCode}") logger.info(f"Capture response: {response.messages.resultCode}")
# If capture was declined (resultCode is "Error"), extract error details
if response.messages.resultCode == "Error":
rejection_reason = "Authorize.Net Capture Error"
if hasattr(response.messages, 'message'):
try:
if len(response.messages.message) > 0:
for msg in response.messages.message:
if hasattr(msg, 'code') and hasattr(msg, 'text'):
# Convert lxml StringElement objects to Python strings
code_str = msg.code.text if msg.code else "Unknown"
text_str = msg.text.text if msg.text else "No details available"
rejection_reason = f"{code_str}: {text_str}"
break # Use the first error message
elif hasattr(msg, 'text'):
# Convert lxml StringElement to Python string
text_str = msg.text.text if msg.text else "No details available"
rejection_reason = f"Error: {text_str}"
break
else:
rejection_reason = "Capture declined - no specific error details available"
except Exception as e:
rejection_reason = f"Capture declined - error details could not be parsed: {str(e)}"
else:
rejection_reason = "Capture declined - no error message available"
if hasattr(response.messages, 'message') and len(response.messages.message) > 0: if hasattr(response.messages, 'message') and len(response.messages.message) > 0:
for msg in response.messages.message: for msg in response.messages.message:
logger.info(f"Message: {msg.text.text if msg.text else 'No message text'}") logger.info(f"Message: {msg.text.text if msg.text else 'No message text'}")
else: else:
logger.error("No response from Authorize.net for capture") logger.error("No response from Authorize.net for capture")
rejection_reason = "No response received from Authorize.Net for capture"
# Attach rejection reason to response for the router to use
if response is not None:
response._rejection_reason = rejection_reason
return response return response