[ic] Unknown charge type (reposted with more info...)

Michael Lehmkuhl interchange-users@icdevgroup.org
Thu Jul 18 06:22:01 2002


Hello fellow IC users,

To review, we are debugging a new payment module for the ECHO payment
system.

I've determined that the my first problem was that my GlobalSub was in
eg/globalsub/openecho, while I was trying to include globalsub/openecho in
interchange.cfg.  I created the globalsub directory at the same level as eg
and moved the openecho file into it.  At that point, IC started complaining
about my GlobalSub itself.

In the error.log for IC, we see this error (line 326 is the first line of
the excerpt below):
- - - [18/July/2002:01:45:00 -0700] - - Bad GlobalSub 'openecho'
> In line 326 of the configuration file 'globalsub/openecho':
> GlobalSub <<EOS
> 
> 

I know someone must know the answer.  I just hope you share it with little
ol' me.

Thanks in advance.



Here's the whole GlobalSub:
___________________________

<EXCERPT FROM="globalsub/openecho">

GlobalSub <<EOS
sub openecho {

::logDebug("openecho payment GlobalSub called");

    my ($user, $secret, $amount) = @_;

#    my (%actual) = Vend::Order::map_actual();
    my (%actual) = Vend::Payment::map_actual();

    # Required for validation
    if (! $user) {
        $user      = $::Variable->{ECHO_PAYMENT_ID} ||
                     $::Variable->{MV_PAYMENT_ID} ||
                     $::Variable->{CYBER_ID}
                     or return undef;
    }
::logDebug("openecho user $user");

    # Required for validation
    if (! $secret) {
        $secret    = $::Variable->{ECHO_PAYMENT_SECRET} ||
                     $::Variable->{MV_PAYMENT_SECRET} ||
                     $::Variable->{CYBER_SECRET}
                     or return undef;
    }

    my $server     = $::Variable->{ECHO_PAYMENT_SERVER} ||
                     $::Variable->{MV_PAYMENT_SERVER} ||
                     $::Variable->{CYBER_SERVER} ||
                     'https://wwws.echo-inc.com/scripts/INR200.EXE';

    my $precision  = $::Variable->{ECHO_PAYMENT_PRECISION} ||
                     $::Variable->{MV_PAYMENT_PRECISION} ||
                     $::Variable->{CYBER_PRECISION} ||
                     2;

    ##### ECHO SPECIFIC VARIABLES #####

    my $order_type = $::Variable->{ECHO_PAYMENT_ORDER_TYPE} || 'S';
    my $isp_echo_id = $::Variable->{ECHO_PAYMENT_ISP_ECHO_ID}
                     or return undef;
    my $isp_pin    = $::Variable->{ECHO_PAYMENT_ISP_PIN}
                     or return undef;
    my $merchant_email = $::Variable->{ECHO_PAYMENT_MERCHANT_EMAIL}
                     or return undef;

    # Set to 'C' for Certify mode to check compliance with the ECHO spec on
    # a transaction-by-transaction basis.  'T' or 'TRUE' for full ECHO
    # debugging.
    my $debug = $::Variable->{ECHO_PAYMENT_DEBUG};

    ##########################

::logDebug("openecho variables have been set");

    $actual{mv_credit_card_exp_month} =~ s/\D//g;
    $actual{mv_credit_card_exp_month} =~ s/^0+//;
    $actual{mv_credit_card_exp_year} =~ s/\D//g;
    $actual{mv_credit_card_exp_year} =~ s/\d\d(\d\d)/$1/;

    $actual{mv_credit_card_number} =~ s/\D//g;

    my $exp = sprintf '%02d%02d',
                        $actual{mv_credit_card_exp_month},
                        $actual{mv_credit_card_exp_year};

    # Using mv_payment_mode for compatibility with older versions, probably
    # not necessary.
    $actual{cyber_mode} = $actual{mv_payment_mode} || 'ES'
        unless $actual{cyber_mode};

    # Credit Card Transactions
    # *    AD (Address Verification)
    # *    AS (Authorization)
    # *    AV (Authorization with Address Verification)
    # *    CR (Credit)
    # *    DS (Deposit)
    # *    ES (Authorization and Deposit)
    # *    EV (Authorization and Deposit with Address Verification)
    # *    CK (System check)
    # Credit Card Transactions Enhanced by CyberSource
    # *    CI (AV Transaction with CyberSource Internet Fraud Screen)
    # *    CE (AV Transaction with CyberSource Export Compliance)
    # *    CB (AV Transaction with CyberSource Internet Fraud Screen and
    #          Export Compliance)
    # Electronic Check Transactions
    # *    DV (Electronic Check Verification)
    # *    DD (Electronic Check Debit)
    # *    DC (Electronic Check Credit)
    my %type_map = (
        mauth_capture             =>    'ES',
        mauthonly                =>    'AS',
        CAPTURE_ONLY            =>  'DS',
        CREDIT                    =>    'CR',
        AUTH_ONLY                =>    'AS',
        PRIOR_AUTH_CAPTURE        =>    'DS',
    );
    
    if (defined $type_map{$actual{cyber_mode}}) {
        $actual{cyber_mode} = $type_map{$actual{cyber_mode}};
    }
    else {
        $actual{cyber_mode} = 'ES';
    }

    if(! $amount) {
        $amount = Vend::Interpolate::total_cost();
        $amount = sprintf("%.${precision}f", $amount);
    }

::logDebug("openecho charge amount is $amount");

    my($orderID);
    my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
gmtime(time());

    ### Make an order ID based on date, time, and Interchange session
    # $mon is the month index where Jan=0 and Dec=11, so we use
    # $mon+1 to get the more familiar Jan=1 and Dec=12
    #$orderID = sprintf("%04d%02d%02d%02d%02d%05d%s",
    #        $year + 1900,$mon + 1,$mday,$hour,$min,$$,$Vend::SessionName);
    $orderID = Vend::Payment::gen_order_id();

::logDebug("openecho orderID is $orderID");

    ### Set up the OpenECHO instance
    require OpenECHO;
    $openecho = new OpenECHO or die "Couldn't make instance of OpenECHO";

::logDebug("openecho created new OpenECHO object");

    ### Connection info
    
$openecho->set_EchoServer("https://wwws.echo-inc.com/scripts/INR200.EXE");
    $openecho->set_transaction_type($actual{cyber_mode});
    $openecho->set_order_type($order_type);

    ### Merchant/ISP info
    $openecho->set_merchant_echo_id($user);
    $openecho->set_merchant_pin($secret);
    $openecho->set_isp_echo_id($isp_echo_id);
    $openecho->set_isp_pin($isp_pin);
    $openecho->set_merchant_email($merchant_email);

    ### Billing info
    $billing_first_name = $actual{b_fname} || $actual{fname};
    $billing_last_name = $actual{b_lname} || $actual{lname};
    $billing_address1 = $actual{b_address1} || $actual{address1};
    $billing_address2 = $actual{b_address2} || $actual{address2};
    $billing_city = $actual{b_city} || $actual{city};
    $billing_state = $actual{b_state} || $actual{state};
    $billing_zip = $actual{b_zip} || $actual{zip};
    $billing_country = $actual{b_country} || $actual{country};
    $billing_phone = $actual{phone_day} || $actual{phone_night};
    $openecho->set_billing_ip_address($Vend::Session->{ohost});
    #$openecho->set_billing_prefix($actual{prefix});
    $openecho->set_billing_first_name($billing_first_name);
    $openecho->set_billing_last_name($billing_last_name);
    #$openecho->set_billing_company_name($actual{company_name});
    $openecho->set_billing_address1($billing_address1);
    $openecho->set_billing_address2($billing_address2);
    $openecho->set_billing_city($billing_city);
    $openecho->set_billing_state($billing_state);
    $openecho->set_billing_zip($billing_zip);
    $openecho->set_billing_country($billing_country);
    $openecho->set_billing_phone($billing_phone);
    #$openecho->set_billing_fax($actual{fax});
    $openecho->set_billing_email($actual{email});

    ### Electronic check payment info if supplied...
    #$openecho->set_ec_bank_name($ec_bank_name);
    #$openecho->set_ec_first_name($billing_first_name);
    #$openecho->set_ec_last_name($billing_last_name);
    #$openecho->set_ec_address1($billing_address1);
    #$openecho->set_ec_address2($billing_address2);
    #$openecho->set_ec_city($billing_city);
    #$openecho->set_ec_state($billing_state);
    #$openecho->set_ec_zip($billing_zip);
    #$openecho->set_ec_rt($ec_rt);
    #$openecho->set_ec_account($ec_account);
    #$openecho->set_ec_serial_number($ec_serial_number);
    #$openecho->set_ec_payee($ec_payee);
    #$openecho->set_ec_id_state($ec_id_state);
    #$openecho->set_ec_id_number($ec_id_number);
    #$openecho->set_ec_id_type($ec_id_type);

    ### Debug on/off
    $openecho->set_debug($debug);
    
    ### Payment details
    $openecho->set_cc_number($actual{mv_credit_card_number});
    $openecho->set_grand_total($amount);
    $openecho->set_ccexp_month($actual{mv_credit_card_exp_month});
    $openecho->set_ccexp_year($actual{mv_credit_card_exp_year});
    $openecho->set_counter($openecho->getRandomCounter());
    $openecho->set_merchant_trace_nbr($orderID);
    
    ### Send payment request
    #print($openecho->get_version() . "<BR>");
    $openecho->Submit();

::logDebug("openecho payment request submitted");

    my %result;
    if ($openecho->EchoSuccess != 0) {
        $result{'MStatus'} = 'success';
        $result{'pop.status'} = 'success';
        $result{'MErrMsg'} = $openecho->avs_result;
        $result{'pop.error-message'} = $openecho->avs_result;
        $result{'order-id'} = $openecho->order_number || 1;
        $result{'pop.order-id'} = $openecho->order_number || 1;
        $result{'auth_code'} = $openecho->auth_code;
        $result{'pop.auth_code'} = $openecho->auth_code;
        $result{'avs_code'} = $openecho->avs_result;
        $result{'pop.avs_code'} = $openecho->avs_result;
    }
    else {
        $result{MStatus} = 'failure';
        $Vend::Session->{MStatus} = 'failure';
        
        # NOTE: A lot more AVS codes could be checked for here.
        if ($avs_code eq 'N') {
            $result{MErrMsg} = "You must enter the correct billing address";
            $result{MErrMsg} .= " of your credit card. The bank returned";
            $result{MErrMsg} .= " the following error: ";
            $result{MErrMsg} .= $openecho->avs_result;
        }
        else {
            $result{MErrMsg} = $openecho->avs_result;
            my $msg = errmsg("ECHO error: %s. Please call in your order or
try again.",
                $openecho->avs_result,
            );
        }
        $Vend::Session->{payment_error} = $result{MErrMsg};
::logDebug("openecho oops: ".$Vend::Session->{payment_error});
    }

    return (%result);
}
EOS

</EXCERPT>


-- 
Michael Lehmkuhl <michael@electricpulp.com>
Partner, Electric Pulp

1.605.988.0177 : 1.888.722.PULP
electricpulp.com



On 7/17/02 12:48 PM, "Michael Lehmkuhl" <michael@electricpulp.com> wrote:

> Hello.
> 
> We are rolling our own Interchange payment method for ECHO.  We've created a
> Perl module that makes the connection and submits the request to ECHO.  That
> part OpenECHO.pm is functional and tested.
> 
> We are getting the following error when we try to submit payment during the
> checkout process:
>   (openecho): Charge operation 'openecho' failed.
> 
> The error.log for the catalog has this message:
>   Unknown charge type: openecho
> 
> The catalog.cfg has a Route set up for openecho:
>   Route  openecho      id           "__ECHO_PAYMENT_ID__"
>   Route  openecho      secret       "__ECHO_PAYMENT_SECRET__"
>   Route  openecho      host         "__ECHO_PAYMENT_HOST__"
> 
> The catalog.cfg also requires the OpenECHO module, which is called
> OpenECHO.pm in the lib directory of the Interchange root directory:
>   # Enable OpenECHO payment processing
>   Require module OpenECHO
> 
> The following variables are set in variable.txt:
>   MV_PAYMENT_ID    1234682203    Payment
>   MV_PAYMENT_MODE    custom openecho    Payment
>   MV_PAYMENT_SECRET    ******    Payment
>   ECHO_PAYMENT_ID    1234682203    Payment
>   ECHO_PAYMENT_SECRET    ******    Payment
>   ECHO_PAYMENT_MODE    custom openecho    Payment
> 
> In interchange.cfg, we include the globalsub:
>   # Include OpenECHO payment method code
>   include globalsub/openecho
> 
> We have a file called openecho in eg/globalsub that has the following code:
>   GlobalSub <<EOS
>   sub openecho {
> 
>   ::logDebug("openecho payment GlobalSub called");
> 
> Since debugging is turned on and we aren't getting an error in /tmp/icdebug,
> it looks like Interchange isn't even realizing that the openecho routine
> exists.
> 
> I've seen the "Unknown charge type:" error before, and it seems like the
> problem that time was that our include statement in the interchange.cfg file
> was looking for globalsubs rather than globalsub.  That isn't the problem
> this time.
> 
> I've checked through the mailing list archives, but none of the solutions
> mentioned there fixed this issue.
> 
> We are getting ready to launch this store very soon, so this is a somewhat
> urgent issue, and I'd really appreciate anyone's help.
> 
> Thanks.