one of the documented procedures in this installation of the ACS
ec_talk_to_cybercash   txn_attempted_type   cc_args
What it does:
This procedure talks to CyberCash to do whatever transaction is specified, adds a row to the ec_cybercash_log table, and returns all of CyberCash's output in an ns_set
Defined in: /web/philip/tcl/ecommerce-credit.tcl

Source code:

    # Possible values of txn_attempted_type are listed below and
    # in the data model (in the ec_cybercash_log table).
    # cc_args should be an ns_set containing the key/value
    # pairs to be sent to CyberCash, as follows:
    # txn_attempted_type    mandatory keys in cc_args
    # ------------------    -------------------------
    # mauthonly             amount (containing currency & price), 
    #                         order-id, card-number, card-exp, 
    #                         [card-zip, card-country and
    #                         card-name are optional]
    # postauth              amount (currency & price), order-id
    # return                amount (currency & price), order-id
    # void                  txn-type (value should be marked or 
    #                         markret), order-id
    # retry                 order-id, txn-type (value in auth,
    #                         postauth, return, voidmark, voidreturn)
    # query                 order-id, txn-type (value in auth, marked,
    #                         settled, markret, setlret, voidmark,
    #                         voidreturn)
    # (September 5, 1999, eveander) When performing queries, the
    # following sentence is no longer true as of sometime in 1999:
    # "Note that this proc assumes we're querying by order-id and
    # txn-type which means that only 0 or 1 relevant row will be
    # returned."  I'm still going to assume that we're querying by
    # order-id and txn-type, but due to CyberCash's unannounced and
    # undocumented changes in the results of the API call "query",
    # any number of rows may be returned and they may or may not
    # contain information about the specified transaction type. So
    # I've had to fix ec_talk_to_cybercash to make it dig through all
    # the irrelevant rows returned when querying. The output of
    # ec_talk_to_cybercash will remain the same, so you don't need
    # to change any code that uses this procedure.
    # If you want to query by, say, order-id and txn-status, do not use
    # this proc.  You'll need to specially handle all the rows of data
    # returned by CyberCash.
    # This proc returns the info that CyberCash returns, except that
    # variables are slightly renamed to stick with legal tcl variable
    # names and our own naming conventions.

    set currency [ad_parameter Currency ecommerce]

    if { [ns_set get $cc_args "amount"] != "" } {
	# This is to take care of cases where the tax table has output an
	# amount that contains a fraction of a cent, which CyberCash
	# dislikes
	set smart_amount [ns_set get $cc_args "amount"]
	regsub -all {[^0-9\.]} $smart_amount "" smart_amount
	ns_set update $cc_args "amount" "$currency [format "%0.2f" $smart_amount]"

    # This will hold what CyberCash outputs
    set cc_output [ns_set new]

    # This will hold what this proc (ec_talk_to_cybercash) outputs
    set ttcc_output [ns_set new]

    cc_send_to_server_21 "$txn_attempted_type" $cc_args $cc_output

    # For non-queries, just grab the info in $cc_output and put
    # it into $ttcc_output with the keys renamed (and also stick in
    # txn_type, which isn't returned in non-queries; we want to
    # insert the txn_type that *would* have been returned if it had
    # been a query, for consistency).  Note that some (many) of 
    # the values will be the empty string because no single 
    # transaction returns values for every key.

    if { $txn_attempted_type != "query" } {
	ns_set put $ttcc_output "txn_status" "[ns_set get $cc_output "MStatus"]"
	ns_set put $ttcc_output "errloc" "[ns_set get $cc_output "MErrLoc"]"
	ns_set put $ttcc_output "errmsg" "[ns_set get $cc_output "MErrMsg"]"
	ns_set put $ttcc_output "merch_txn" "[ns_set get $cc_output "merch-txn"]"
	ns_set put $ttcc_output "cust_txn" "[ns_set get $cc_output "cust-txn"]"
	ns_set put $ttcc_output "aux_msg" "[ns_set get $cc_output "aux-msg"]"
	ns_set put $ttcc_output "auth_code" "[ns_set get $cc_output "auth-code"]"
	ns_set put $ttcc_output "action_code" "[ns_set get $cc_output "action-code"]"
	ns_set put $ttcc_output "avs_code" "[ns_set get $cc_output "avs-code"]"
	ns_set put $ttcc_output "ref_code" "[ns_set get $cc_output "ref-code"]"

	# Figure out what to stick into txn_type
	if { $txn_attempted_type == "mauthonly" } {
	    set txn_type "auth"
	} elseif { $txn_attempted_type == "postauth" } {
	    set txn_type "postauth"
	} elseif { $txn_attempted_type == "return" } {
	    set txn_type "markret"
	} elseif { $txn_attempted_type == "void" && [ns_set get $cc_args "txn-type"] == "marked" } {
	    set txn_type "voidmark"
	} elseif { $txn_attempted_type == "void" && [ns_set get $cc_args "txn-type"] == "markret" } {
	    set txn_type "voidreturn"
	} elseif { $txn_attempted_type == "retry" && [ns_set get $cc_args "txn-type"] == "auth" } {
	    set txn_type "auth"
	} elseif { $txn_attempted_type == "retry" && [ns_set get $cc_args "txn-type"] == "postauth" } {
	    set txn_type "marked"
	} elseif { $txn_attempted_type == "retry" && [ns_set get $cc_args "txn-type"] == "return" } {
	    set txn_type "markret"
	} elseif { $txn_attempted_type == "retry" && [ns_set get $cc_args "txn-type"] == "voidmark" } {
	    set txn_type "voidmark"
	} elseif { $txn_attempted_type == "retry" && [ns_set get $cc_args "txn-type"] == "voidreturn" } {
	    set txn_type "voidreturn"
	} else {
	    set txn_type "unknown"

	ns_set put $ttcc_output "txn_type" $txn_type
    } elseif { $txn_attempted_type == "query" } {

	set cc_output_size [ns_set size $cc_output]

	set relevant_cc_data ""
	for {set i 0} {$i < $cc_output_size} {incr i} {
	    set one_row_of_cc_data [ns_set value $cc_output $i]
	    set cc_txn_type [ec_get_from_quasi_form $one_row_of_cc_data txn-type]
	    if { $cc_txn_type == [ns_set get $cc_args "txn-type"] } {
		set relevant_cc_data $one_row_of_cc_data

	if {![empty_string_p $relevant_cc_data]} {
	    # If it's a query, we have to do some regexping because 
	    # ns_sets of non-ns_set key/value pairs are returned.
	    # It's the 2nd value of $cc_output that's of interest
	    # (no longer true as of September 5, 1999; see comment
	    # at top of this procedure; so we've set relevant_cc_data
	    # above).
	    # Note that the cc_time returned isn't a date as far
	    # as Oracle is concerned (it's a string, so you'll have
	    # to do a to_date('$cc_time','YYYYMMDDHH24MISS') when inserting).
	    ns_set put $ttcc_output "txn_type" [ec_get_from_quasi_form $relevant_cc_data txn-type]
	    ns_set put $ttcc_output "cust_txn" [ec_get_from_quasi_form $relevant_cc_data cust-txn]
	    ns_set put $ttcc_output "merch_txn" [ec_get_from_quasi_form $relevant_cc_data merch-txn]
	    ns_set put $ttcc_output "origin" [ec_get_from_quasi_form $relevant_cc_data origin]
	    ns_set put $ttcc_output "txn_status" [ec_get_from_quasi_form $relevant_cc_data txn-status]
	    # we have to handle date specially so as not to confuse Oracle with
	    # subsecond precision
	    regexp {time=([^.]*)\.} $relevant_cc_data garbage ugly_date
	    if { ![info exists ugly_date] } {
		set ugly_date ""
	    ns_set put $ttcc_output "cc_time" $ugly_date
	    ns_set put $ttcc_output "auth_code" [ec_get_from_quasi_form $relevant_cc_data auth-code]
	    ns_set put $ttcc_output "action_code" [ec_get_from_quasi_form $relevant_cc_data action-code]
	    ns_set put $ttcc_output "avs_code" [ec_get_from_quasi_form $relevant_cc_data avs-code]
	    ns_set put $ttcc_output "ref_code" [ec_get_from_quasi_form $relevant_cc_data ref-code]
	    ns_set put $ttcc_output "batch_id" [ec_get_from_quasi_form $relevant_cc_data batch-id]
	    set long_amount [ec_get_from_quasi_form $relevant_cc_data amount]
	    regsub -all {[^0-9\.]} $long_amount "" numeric_amount
	    # regexp {^[ad_parameter Currency ecommerce] (.*)} $long_amount garbage numeric_amount
	    if { [info exists numeric_amount] } {
		ns_set put $ttcc_output "amount" $numeric_amount	
	    } else {
		ns_set put $ttcc_output "amount" ""	

    # Add a row to cybercash_log
    set db [ns_db gethandle subquery]

    ns_db dml $db "insert into ec_cybercash_log
    (transaction_id, txn_attempted_time, txn_attempted_type, txn_type, cc_time, merch_txn, cust_txn, origin, txn_status, errloc, errmsg, aux_msg, auth_code, action_code, avs_code, ref_code, batch_id, amount)    
    ([ns_set get $cc_args "order-id"], sysdate, '[DoubleApos $txn_attempted_type]', '[DoubleApos [ns_set get $ttcc_output "txn_type"]]', to_date('[ns_set get $ttcc_output "cc_time"]','YYYYMMDDHH24MISS'), '[DoubleApos [ns_set get $ttcc_output "merch_txn"]]', '[DoubleApos [ns_set get $ttcc_output "cust_txn"]]', '[DoubleApos [ns_set get $ttcc_output "origin"]]', '[DoubleApos [ns_set get $ttcc_output "txn_status"]]', '[DoubleApos [ns_set get $ttcc_output "errloc"]]', '[DoubleApos [ns_set get $ttcc_output "errmsg"]]', '[DoubleApos [ns_set get $ttcc_output "aux_msg"]]', '[DoubleApos [ns_set get $ttcc_output "auth_code"]]', '[DoubleApos [ns_set get $ttcc_output "action_code"]]', '[DoubleApos [ns_set get $ttcc_output "avs_code"]]', '[DoubleApos [ns_set get $ttcc_output "ref_code"]]', '[DoubleApos [ns_set get $ttcc_output "batch_id"]]', '[DoubleApos [ns_set get $ttcc_output "amount"]]') "
    ns_db releasehandle $db
    # Finally, return the ns_set
    return $ttcc_output