ec_sweep_for_cybercash_zombiesWhat it does:
Looks for confirmed orders that aren't either failed or authorized, i.e., where we didn't hear back from CyberCashDefined in: /web/philip/tcl/ecommerce-scheduled-procs.tcl
Source code:
# cron job to dig up confirmed but not failed or authorized orders
# over 15 minutes old ("zombies")
# These only happen when we go off to CyberCash to authorize an order
# but either we got no response or the response indicated nothing about
# whether the card was actually valid. It also happens if the consumer
# pushes reload after the order is inserted into the database but
# before it goes through to CyberCash.
#
# OVERALL STRATEGY
# (1) query CyberCash to see if they have a record of the order
# (2) if CyberCash has the record and it was successful,
# update order_state to authorized_plus/minus_avs
# (3) if CyberCash doesn't have the order or it was inconclusive,
# retry order
# (a) if successful, update order_state to authorized_*_avs
# (b) if inconclusive, leave in this state
# (c) if a definite failure, change order_state failed_authorization
# (it will later be moved back to in_basket by ec_delayed_credit_denied)
ns_log Notice "ec_sweep_for_cybercash_zombies starting"
set dblist [ns_db gethandle [philg_server_default_pool] 2]
set db [lindex $dblist 0]
set db2 [lindex $dblist 1]
# Note that the outer loop uses $db2, so use $db within it
set selection [ns_db select $db2 "select order_id
from ec_orders
where order_state = 'confirmed'
and (sysdate - confirmed_date) > 1/96"]
while { [ns_db getrow $db2 $selection] } {
set_variables_after_query
ns_log Notice "ec_sweep_for_cybercash_zombies working on order $order_id"
set total_order_price [database_to_tcl_string $db "select ec_order_cost($order_id) from dual"]
if { $total_order_price == 0 } {
set auth_status_is_now "success"
} else {
set transaction_id [database_to_tcl_string $db "select max(transaction_id)
from ec_financial_transactions
where order_id=$order_id"]
# Query CyberCash:
set cc_args [ns_set new]
ns_set put $cc_args "order-id" "$transaction_id"
ns_set put $cc_args "txn-type" "auth"
set ttcc_output [ec_talk_to_cybercash "query" $cc_args]
set txn_status [ns_set get $ttcc_output "txn_status"]
if { [regexp {success} $txn_status] } {
set auth_status_is_now "success"
} elseif { [empty_string_p $txn_status] || [regexp {failure} $txn_status] } {
# Retry the authorization
set new_cc_status [ec_creditcard_authorization $db $order_id]
if { $new_cc_status == "authorized_plus_avs" || $new_cc_status == "authorized_minus_avs" } {
set auth_status_is_now "success"
} elseif { $new_cc_status == "failed_authorization" } {
set auth_status_is_now "failure"
} else {
set auth_status_is_now "lack_of_success"
if { $new_cc_status == "invalid_input" } {
ns_log Notice "invalid input to ec_creditcard_authorization in ec_sweep_for_cybercash_zombies "
}
}
} elseif { [regexp {pending} $txn_status] } {
# We need to retry the auth using the API call "retry"
set cc_args_2 [ns_set new]
ns_set put $cc_args_2 "order-id" "$transaction_id"
ns_set put $cc_args_2 "txn-type" "auth"
set ttcc_output_2 [ec_talk_to_cybercash "retry" $cc_args_2]
if { [regexp {success} [ns_set get $ttcc_output_2 "txn_status"]] } {
set auth_status_is_now "success"
} else {
set auth_status_is_now "lack_of_success"
# This proc won't do anything with it in this case. It'll
# be caught next time around (ec_creditcard_authorization
# knows how to interpret the various failure messages).
}
} else {
# weird result, which we don't know what to do with. We should just leave
# the order_state alone and let it be subjected to this proc again in
# another half-hour, by which time things may have cleared up.
set auth_status_is_now "unknown"
ns_db dml $db "insert into ec_problems_log
(problem_id, problem_date, problem_details, order_id)
values
(ec_problem_id_sequence.nextval, sysdate, 'Strange CyberCash result when querying about auth: [DoubleApos [ns_set get $ttcc_output_2 "txn_status"]]', [ns_dbquotevalue $order_id integer])
"
}
# end of non-free order section
}
# If the auth_status_is_now is "success" or "failure", then we want to
# update the order state. Otherwise, the order
# stays in the confirmed state.
if { $auth_status_is_now == "success" } {
if { $total_order_price > 0 } {
# get avs code from CyberCash log for most recent row containing this
# order_id
set sub_selection [ns_db 1row $db "select avs_code
from ec_cybercash_log where transaction_id=$transaction_id
and txn_attempted_time = (select MAX(txn_attempted_time) from ec_cybercash_log log2 where log2.transaction_id=$transaction_id)"]
set_variables_after_subquery
if { [ec_avs_acceptable_p $avs_code] == 1 } {
set new_order_state "authorized_plus_avs"
} else {
set new_order_state "authorized_minus_avs"
}
} else {
set new_order_state "authorized_plus_avs"
}
# update the order_state
ec_update_state_to_authorized $db $order_id [ec_decode $new_order_state "authorized_plus_avs" "t" "f"]
} elseif { $auth_status_is_now == "failure" } {
# this will get changed to in_basket by the ec_delayed_credit_denied proc
set new_order_state "failed_authorization"
ns_db dml $db "update ec_orders set order_state='$new_order_state' where order_id=$order_id"
}
}
ns_db releasehandle $db
ns_db releasehandle $db2
ns_log Notice "ec_sweep_for_cybercash_zombies finishing"