Good progession
This commit is contained in:
@@ -90,7 +90,7 @@ def update_transaction_for_capture(db: Session, auth_net_transaction_id: str, ch
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
transaction.charge_amount = charge_amount if status == 0 else Decimal("0.0")
|
transaction.charge_amount = charge_amount if status == 0 else Decimal("0.0")
|
||||||
transaction.transaction_type = 3
|
transaction.transaction_type = 2
|
||||||
transaction.status = status
|
transaction.status = status
|
||||||
if rejection_reason:
|
if rejection_reason:
|
||||||
transaction.rejection_reason = rejection_reason
|
transaction.rejection_reason = rejection_reason
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class Transaction(Base):
|
|||||||
preauthorize_amount = Column(Numeric(10, 2), nullable=True)
|
preauthorize_amount = Column(Numeric(10, 2), nullable=True)
|
||||||
charge_amount = Column(Numeric(10, 2), nullable=True)
|
charge_amount = Column(Numeric(10, 2), nullable=True)
|
||||||
customer_id = Column(Integer)
|
customer_id = Column(Integer)
|
||||||
transaction_type = Column(Integer)
|
transaction_type = Column(Integer)# 0 = charge, 1 = auth, 2 = capture
|
||||||
status = Column(Integer)
|
status = Column(Integer)
|
||||||
auth_net_transaction_id = Column(String, unique=True, index=True, nullable=True)
|
auth_net_transaction_id = Column(String, unique=True, index=True, nullable=True)
|
||||||
service_id = Column(Integer, nullable=True)
|
service_id = Column(Integer, nullable=True)
|
||||||
|
|||||||
@@ -36,55 +36,87 @@ STATE_ID_TO_ABBREVIATION = {
|
|||||||
6: "NY"
|
6: "NY"
|
||||||
}
|
}
|
||||||
|
|
||||||
# This helper function is perfect, keep it.
|
|
||||||
def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[TransactionStatus, Optional[str], Optional[str]]:
|
def _parse_authnet_response(response: Optional[AuthNetResponse]) -> Tuple[TransactionStatus, Optional[str], Optional[str]]:
|
||||||
# ... (Your existing _parse_authnet_response function code) ...
|
"""
|
||||||
if response is not None and hasattr(response, 'messages') and response.messages.resultCode == "Ok":
|
Parse Authorize.net response with proper attribute access for SDK objects.
|
||||||
status = TransactionStatus.APPROVED
|
Authorize.net response objects don't have .text properties, they're direct attributes.
|
||||||
auth_net_transaction_id = str(response.transactionResponse.transId) if hasattr(response, 'transactionResponse') and response.transactionResponse.transId else None
|
"""
|
||||||
rejection_reason = None
|
print(f"DEBUG: Parsing response, type: {type(response)}")
|
||||||
|
print(f"DEBUG: Response exists: {response is not None}")
|
||||||
|
|
||||||
|
if response is not None:
|
||||||
|
print("DEBUG: Checking for messages attribute...")
|
||||||
|
if hasattr(response, 'messages'):
|
||||||
|
print(f"DEBUG: Messages exist, resultCode: {getattr(response.messages, 'resultCode', 'NO resultCode')}")
|
||||||
else:
|
else:
|
||||||
|
print("DEBUG: No messages attribute")
|
||||||
|
|
||||||
|
if response is not None and hasattr(response, 'messages') and response.messages.resultCode == "Ok":
|
||||||
|
print("DEBUG: Taking APPROVED path")
|
||||||
|
status = TransactionStatus.APPROVED
|
||||||
|
auth_net_transaction_id = None
|
||||||
|
|
||||||
|
# Extract transaction ID with proper error handling
|
||||||
|
try:
|
||||||
|
if hasattr(response, 'transactionResponse') and response.transactionResponse:
|
||||||
|
if hasattr(response.transactionResponse, 'transId') and response.transactionResponse.transId:
|
||||||
|
auth_net_transaction_id = str(response.transactionResponse.transId)
|
||||||
|
print(f"DEBUG: FOUND transaction ID: {auth_net_transaction_id}")
|
||||||
|
else:
|
||||||
|
print("DEBUG: transactionResponse exists but no transId")
|
||||||
|
else:
|
||||||
|
print("DEBUG: No transactionResponse in approved response")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DEBUG: Exception extracting transaction ID: {e}")
|
||||||
|
print(f"DEBUG: Response object inspection:")
|
||||||
|
print(type(response))
|
||||||
|
if hasattr(response, 'transactionResponse'):
|
||||||
|
print(f"TransactionResponse type: {type(response.transactionResponse)}")
|
||||||
|
print(dir(response.transactionResponse))
|
||||||
|
|
||||||
|
rejection_reason = None
|
||||||
|
print(f"DEBUG: APPROVED - ID: {auth_net_transaction_id}, rejection: {rejection_reason}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("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."
|
||||||
print("DEBUG: Full response object")
|
|
||||||
print(response)
|
|
||||||
print("DEBUG: response.messages")
|
|
||||||
print(response.messages)
|
|
||||||
print("DEBUG: response.messages.resultCode")
|
|
||||||
print(response.messages.resultCode)
|
|
||||||
if response is not None:
|
if response is not None:
|
||||||
if hasattr(response, 'transactionResponse') and response.transactionResponse and hasattr(response.transactionResponse, 'errors') and response.transactionResponse.errors:
|
# Handle transaction response errors
|
||||||
|
if hasattr(response, 'transactionResponse') and response.transactionResponse:
|
||||||
|
if hasattr(response.transactionResponse, 'errors') and response.transactionResponse.errors:
|
||||||
print("DEBUG: Using transactionResponse.errors")
|
print("DEBUG: Using transactionResponse.errors")
|
||||||
|
try:
|
||||||
error = response.transactionResponse.errors[0]
|
error = response.transactionResponse.errors[0]
|
||||||
rejection_reason = f"{error.errorCode.text}: {error.errorText.text}"
|
# Remove the .text access - use direct attributes
|
||||||
elif hasattr(response, 'messages') and response.messages and hasattr(response.messages, 'message') and response.messages.message:
|
error_code = getattr(error, 'errorCode', 'Unknown')
|
||||||
|
error_text = getattr(error, 'errorText', 'Unknown error')
|
||||||
|
rejection_reason = f"{error_code}: {error_text}"
|
||||||
|
print(f"DEBUG: Transaction error: {rejection_reason}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DEBUG: Exception parsing transaction error: {e}")
|
||||||
|
rejection_reason = "Failed to parse transaction error"
|
||||||
|
|
||||||
|
# Handle message-level errors
|
||||||
|
elif hasattr(response, 'messages') and response.messages:
|
||||||
|
if hasattr(response.messages, 'message') and response.messages.message:
|
||||||
print("DEBUG: Using response.messages.message")
|
print("DEBUG: Using response.messages.message")
|
||||||
msg = response.messages.message[0]
|
try:
|
||||||
print("DEBUG: msg object")
|
msg = response.messages.message
|
||||||
print(msg)
|
if isinstance(msg, list):
|
||||||
print("DEBUG: msg attributes")
|
msg = msg[0] if msg else None
|
||||||
print(dir(msg))
|
if msg:
|
||||||
print("DEBUG: msg.code")
|
code = getattr(msg, 'code', 'Unknown')
|
||||||
print(getattr(msg, 'code', 'NO code ATTR'))
|
text = getattr(msg, 'text', 'Unknown error')
|
||||||
print("DEBUG: msg.text")
|
rejection_reason = f"{code}: {text}"
|
||||||
print(getattr(msg, 'text', 'NO text ATTR'))
|
print(f"DEBUG: Message error: {rejection_reason}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"DEBUG: Exception parsing message error: {e}")
|
||||||
|
rejection_reason = "Failed to parse message error"
|
||||||
|
|
||||||
code_val = None
|
print(f"DEBUG: FINAL RESULT - Status: {status}, ID: {auth_net_transaction_id}, Reason: {rejection_reason}")
|
||||||
text_val = None
|
|
||||||
if hasattr(msg, 'code') and msg.code is not None and hasattr(msg.code, 'text'):
|
|
||||||
code_val = msg.code.text
|
|
||||||
elif hasattr(msg, 'code'):
|
|
||||||
code_val = str(msg.code)
|
|
||||||
|
|
||||||
if hasattr(msg, 'text') and msg.text is not None and hasattr(msg.text, 'text'):
|
|
||||||
text_val = msg.text.text
|
|
||||||
elif hasattr(msg, 'text'):
|
|
||||||
text_val = str(msg.text)
|
|
||||||
|
|
||||||
rejection_reason = f"{code_val}: {text_val}" if code_val and text_val and text_val != "None" else f"{code_val}" if code_val else f"Error: {getattr(msg, 'text', 'Unknown error')}"
|
|
||||||
print("DEBUG: Constructed rejection_reason")
|
|
||||||
print(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")
|
||||||
|
|||||||
@@ -276,3 +276,33 @@ def capture_authorized_transaction(transaction_req: schemas.TransactionCapture):
|
|||||||
controller = createTransactionController(createtransactionrequest)
|
controller = createTransactionController(createtransactionrequest)
|
||||||
controller.execute()
|
controller.execute()
|
||||||
return controller.getresponse()
|
return controller.getresponse()
|
||||||
|
|
||||||
|
|
||||||
|
def charge_customer_profile(customer_profile_id: str, payment_profile_id: str, transaction_req: schemas.TransactionCreateByCardID):
|
||||||
|
"""
|
||||||
|
Creates an AUTH_CAPTURE transaction (charge now) against a customer profile.
|
||||||
|
This charges the customer immediately for the full amount.
|
||||||
|
"""
|
||||||
|
logger.info(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)
|
||||||
|
|
||||||
|
profile_to_charge = apicontractsv1.customerProfilePaymentType()
|
||||||
|
profile_to_charge.customerProfileId = customer_profile_id
|
||||||
|
profile_to_charge.customerPaymentProfileId = payment_profile_id
|
||||||
|
|
||||||
|
transactionRequest = apicontractsv1.transactionRequestType(
|
||||||
|
transactionType="authCaptureTransaction",
|
||||||
|
amount=f"{transaction_req.charge_amount:.2f}",
|
||||||
|
profile=profile_to_charge
|
||||||
|
)
|
||||||
|
|
||||||
|
createtransactionrequest = apicontractsv1.createTransactionRequest(
|
||||||
|
merchantAuthentication=merchantAuth,
|
||||||
|
transactionRequest=transactionRequest
|
||||||
|
)
|
||||||
|
|
||||||
|
controller = createTransactionController(createtransactionrequest)
|
||||||
|
controller.execute()
|
||||||
|
# The response is returned directly to the router to be parsed there
|
||||||
|
return controller.getresponse()
|
||||||
|
|||||||
Reference in New Issue
Block a user