/**
  * Performs an action on authorize.net and updates/inserts records. If record update fails,
  * sends email to admin.
  *
  * @param object &$order Which transaction data will be sent. See enrol_authorize table.
  * @param string &$message Information about error message.
  * @param object &$extra Extra data that used for refunding and credit card information.
  * @param int $action Which action will be performed. See AN_ACTION_*
  * @param string $cctype Used internally to configure credit types automatically.
  * @return int AN_APPROVED Transaction was successful, AN_RETURNZERO otherwise. Use $message for reason.
  */
 public static function process(&$order, &$message, &$extra, $action = AN_ACTION_NONE, $cctype = NULL)
 {
     global $CFG, $DB;
     static $constpd = array();
     require_once $CFG->libdir . '/filelib.php';
     $mconfig = get_config('enrol_authorize');
     if (empty($constpd)) {
         $mconfig = get_config('enrol_authorize');
         $constpd = array('x_version' => '3.1', 'x_delim_data' => 'True', 'x_delim_char' => self::AN_DELIM, 'x_encap_char' => self::AN_ENCAP, 'x_relay_response' => 'FALSE', 'x_login' => $mconfig->an_login);
         if (!empty($mconfig->an_tran_key)) {
             $constpd['x_tran_key'] = $mconfig->an_tran_key;
         } else {
             $constpd['x_password'] = $mconfig->an_password;
         }
     }
     if (empty($order) or empty($order->id)) {
         $message = "Check order->id!";
         return AN_RETURNZERO;
     }
     $method = $order->paymentmethod;
     if (empty($method)) {
         $method = AN_METHOD_CC;
     } elseif ($method != AN_METHOD_CC && $method != AN_METHOD_ECHECK) {
         $message = "Invalid method: {$method}";
         return AN_RETURNZERO;
     }
     $action = intval($action);
     if ($method == AN_METHOD_ECHECK) {
         if ($action != AN_ACTION_AUTH_CAPTURE && $action != AN_ACTION_CREDIT) {
             $message = "Please perform AUTH_CAPTURE or CREDIT for echecks";
             return AN_RETURNZERO;
         }
     }
     $pd = $constpd;
     $pd['x_method'] = $method;
     $test = !empty($mconfig->an_test);
     $pd['x_test_request'] = $test ? 'TRUE' : 'FALSE';
     switch ($action) {
         case AN_ACTION_AUTH_ONLY:
         case AN_ACTION_CAPTURE_ONLY:
         case AN_ACTION_AUTH_CAPTURE:
             if ($order->status != AN_STATUS_NONE) {
                 $message = "Order status must be AN_STATUS_NONE(0)!";
                 return AN_RETURNZERO;
             } elseif (empty($extra)) {
                 $message = "Need extra fields!";
                 return AN_RETURNZERO;
             } elseif ($action == AN_ACTION_CAPTURE_ONLY and empty($extra->x_auth_code)) {
                 $message = "x_auth_code is required for capture only transactions!";
                 return AN_RETURNZERO;
             }
             $ext = (array) $extra;
             $pd['x_type'] = $action == AN_ACTION_AUTH_ONLY ? 'AUTH_ONLY' : ($action == AN_ACTION_CAPTURE_ONLY ? 'CAPTURE_ONLY' : 'AUTH_CAPTURE');
             foreach ($ext as $k => $v) {
                 $pd[$k] = $v;
             }
             break;
         case AN_ACTION_PRIOR_AUTH_CAPTURE:
             if ($order->status != AN_STATUS_AUTH) {
                 $message = "Order status must be authorized!";
                 return AN_RETURNZERO;
             }
             if (self::expired($order)) {
                 $message = "Transaction must be captured within 30 days. EXPIRED!";
                 return AN_RETURNZERO;
             }
             $pd['x_type'] = 'PRIOR_AUTH_CAPTURE';
             $pd['x_trans_id'] = $order->transid;
             break;
         case AN_ACTION_CREDIT:
             if ($order->status != AN_STATUS_AUTHCAPTURE) {
                 $message = "Order status must be authorized/captured!";
                 return AN_RETURNZERO;
             }
             if (!self::settled($order)) {
                 $message = "Order must be settled. Try VOID, check Cut-Off time if it fails!";
                 return AN_RETURNZERO;
             }
             if (empty($extra->amount)) {
                 $message = "No valid amount!";
                 return AN_RETURNZERO;
             }
             $timenowsettle = self::getsettletime(time());
             $timediff = $timenowsettle - 120 * 3600 * 24;
             if ($order->settletime < $timediff) {
                 $message = "Order must be credited within 120 days!";
                 return AN_RETURNZERO;
             }
             $pd['x_type'] = 'CREDIT';
             $pd['x_trans_id'] = $order->transid;
             $pd['x_currency_code'] = $order->currency;
             $pd['x_invoice_num'] = $extra->orderid;
             $pd['x_amount'] = $extra->amount;
             if ($method == AN_METHOD_CC) {
                 $pd['x_card_num'] = sprintf("%04d", intval($order->refundinfo));
             } elseif ($method == AN_METHOD_ECHECK && empty($order->refundinfo)) {
                 $message = "Business checkings can be refunded only.";
                 return AN_RETURNZERO;
             }
             break;
         case AN_ACTION_VOID:
             if (self::expired($order) || self::settled($order)) {
                 $message = "The transaction cannot be voided due to the fact that it is expired or settled.";
                 return AN_RETURNZERO;
             }
             $pd['x_type'] = 'VOID';
             $pd['x_trans_id'] = $order->transid;
             break;
         default:
             $message = "Invalid action: {$action}";
             return AN_RETURNZERO;
     }
     $headers = array('Connection' => 'close');
     if (!(empty($mconfig->an_referer) || $mconfig->an_referer == "http://")) {
         $headers['Referer'] = $mconfig->an_referer;
     }
     @ignore_user_abort(true);
     if (intval(ini_get('max_execution_time')) > 0) {
         @set_time_limit(300);
     }
     $host = $test ? 'test.authorize.net' : 'secure.authorize.net';
     $data = download_file_content("https://{$host}:443/gateway/transact.dll", $headers, $pd, false, 300, 60, true);
     if (!$data) {
         $message = "No connection to https://{$host}:443";
         return AN_RETURNZERO;
     }
     $response = explode(self::AN_ENCAP . self::AN_DELIM . self::AN_ENCAP, $data);
     if ($response === false) {
         $message = "response error";
         return AN_RETURNZERO;
     }
     $rcount = count($response) - 1;
     if ($response[0][0] == self::AN_ENCAP) {
         $response[0] = substr($response[0], 1);
     }
     if (substr($response[$rcount], -1) == self::AN_ENCAP) {
         $response[$rcount] = substr($response[$rcount], 0, -1);
     }
     $responsecode = intval($response[0]);
     if ($responsecode == AN_APPROVED || $responsecode == AN_REVIEW) {
         $transid = floatval($response[6]);
         if ($test || $transid == 0) {
             return $responsecode;
             // don't update original transaction in test mode.
         }
         switch ($action) {
             case AN_ACTION_AUTH_ONLY:
             case AN_ACTION_CAPTURE_ONLY:
             case AN_ACTION_AUTH_CAPTURE:
             case AN_ACTION_PRIOR_AUTH_CAPTURE:
                 $order->transid = $transid;
                 if ($method == AN_METHOD_CC) {
                     if ($action == AN_ACTION_AUTH_ONLY || $responsecode == AN_REVIEW) {
                         $order->status = AN_STATUS_AUTH;
                     } else {
                         $order->status = AN_STATUS_AUTHCAPTURE;
                         $order->settletime = self::getsettletime(time());
                     }
                 } elseif ($method == AN_METHOD_ECHECK) {
                     $order->status = AN_STATUS_UNDERREVIEW;
                 }
                 $DB->update_record('enrol_authorize', $order);
                 break;
             case AN_ACTION_CREDIT:
                 // Credit generates new transaction id.
                 // So, $extra must be updated, not $order.
                 $extra->status = AN_STATUS_CREDIT;
                 $extra->transid = $transid;
                 $extra->settletime = self::getsettletime(time());
                 $extra->id = $DB->insert_record('enrol_authorize_refunds', $extra);
                 break;
             case AN_ACTION_VOID:
                 $tableupdate = 'enrol_authorize';
                 if ($order->status == AN_STATUS_CREDIT) {
                     $tableupdate = 'enrol_authorize_refunds';
                     unset($order->paymentmethod);
                 }
                 $order->status = AN_STATUS_VOID;
                 $DB->update_record($tableupdate, $order);
                 break;
         }
     } else {
         $reasonno = $response[2];
         $reasonstr = "reason" . $reasonno;
         $message = get_string($reasonstr, "enrol_authorize");
         if ($message == '[[' . $reasonstr . ']]') {
             $message = isset($response[3]) ? $response[3] : 'unknown error';
         }
         if ($method == AN_METHOD_CC && !empty($mconfig->an_avs) && $response[5] != "P") {
             $avs = "avs" . strtolower($response[5]);
             $stravs = get_string($avs, "enrol_authorize");
             $message .= "<br />" . get_string("avsresult", "enrol_authorize", $stravs);
         }
         if (!$test) {
             // Autoconfigure :)
             switch ($reasonno) {
                 // Credit card type isn't accepted
                 case self::AN_REASON_NOCCTYPE:
                 case self::AN_REASON_NOCCTYPE2:
                     if (!empty($cctype)) {
                         $ccaccepts = get_list_of_creditcards();
                         unset($ccaccepts[$cctype]);
                         set_config("an_acceptcc_{$cctype}", 0, 'enrol_authorize');
                         foreach ($ccaccepts as $key => $val) {
                             set_config("an_acceptcc_{$key}", 1, 'enrol_authorize');
                         }
                         message_to_admin("{$message} ({$cctype}) This is new config(an_acceptccs):", $ccaccepts);
                     }
                     break;
                     // Echecks only
                 // Echecks only
                 case self::AN_REASON_ACHONLY:
                     set_config("an_acceptmethod_" . AN_METHOD_ECHECK, 1, 'enrol_authorize');
                     message_to_admin("{$message} This is new config(an_acceptmethods):", array(AN_METHOD_ECHECK));
                     break;
                     // Echecks aren't accepted
                 // Echecks aren't accepted
                 case self::AN_REASON_NOACH:
                     set_config("an_acceptmethod_" . AN_METHOD_CC, 1, 'enrol_authorize');
                     message_to_admin("{$message} This is new config(an_acceptmethods):", array(AN_METHOD_CC));
                     break;
                     // This echeck type isn't accepted
                 // This echeck type isn't accepted
                 case self::AN_REASON_NOACHTYPE:
                 case self::AN_REASON_NOACHTYPE2:
                     if (!empty($extra->x_echeck_type)) {
                         switch ($extra->x_echeck_type) {
                             // CCD=BUSINESSCHECKING
                             case 'CCD':
                                 set_config('an_acceptecheck_CHECKING', 1, 'enrol_authorize');
                                 set_config('an_acceptecheck_SAVINGS', 1, 'enrol_authorize');
                                 message_to_admin("{$message} This is new config(an_acceptechecktypes):", array('CHECKING', 'SAVINGS'));
                                 break;
                                 // WEB=CHECKING or SAVINGS
                             // WEB=CHECKING or SAVINGS
                             case 'WEB':
                                 set_config('an_acceptecheck_BUSINESSCHECKING', 1, 'enrol_authorize');
                                 message_to_admin("{$message} This is new config(an_acceptechecktypes):", array('BUSINESSCHECKING'));
                                 break;
                         }
                     }
                     break;
             }
         }
     }
     return $responsecode;
 }
예제 #2
0
 /**
  * process_config
  *
  * @param object $config
  * @return bool true if it will be saved.
  * @access public
  */
 function process_config($config)
 {
     global $CFG;
     $mconfig = get_config('enrol/authorize');
     // site settings
     if (($cost = optional_param('enrol_cost', 5, PARAM_INT)) > 0) {
         set_config('enrol_cost', $cost);
     }
     set_config('enrol_currency', optional_param('enrol_currency', 'USD', PARAM_ALPHA));
     set_config('enrol_mailstudents', optional_param('enrol_mailstudents', 0, PARAM_BOOL));
     set_config('enrol_mailteachers', optional_param('enrol_mailteachers', 0, PARAM_BOOL));
     set_config('enrol_mailadmins', optional_param('enrol_mailadmins', 0, PARAM_BOOL));
     // optional authorize.net settings
     set_config('an_avs', optional_param('an_avs', 0, PARAM_BOOL));
     set_config('an_authcode', optional_param('an_authcode', 0, PARAM_BOOL));
     set_config('an_test', optional_param('an_test', 0, PARAM_BOOL));
     set_config('an_referer', optional_param('an_referer', 'http://', PARAM_URL));
     $acceptmethods = optional_param('acceptmethods', get_list_of_payment_methods(), PARAM_ALPHA);
     set_config('an_acceptmethods', implode(',', $acceptmethods));
     $acceptccs = optional_param('acceptccs', array_keys(get_list_of_creditcards()), PARAM_ALPHA);
     set_config('an_acceptccs', implode(',', $acceptccs));
     $acceptechecktypes = optional_param('acceptechecktypes', get_list_of_bank_account_types(), PARAM_ALPHA);
     set_config('an_acceptechecktypes', implode(',', $acceptechecktypes));
     $cutoff_hour = optional_param('an_cutoff_hour', 0, PARAM_INT);
     $cutoff_min = optional_param('an_cutoff_min', 5, PARAM_INT);
     set_config('an_cutoff', $cutoff_hour * 60 + $cutoff_min);
     // cron depencies
     $reviewval = optional_param('an_review', 0, PARAM_BOOL);
     $captureday = optional_param('an_capture_day', 5, PARAM_INT);
     $emailexpired = optional_param('an_emailexpired', 2, PARAM_INT);
     $emailexpiredteacher = optional_param('an_emailexpiredteacher', 0, PARAM_BOOL);
     $sorttype = optional_param('an_sorttype', 'ttl', PARAM_ALPHA);
     $captureday = $captureday > 29 ? 29 : ($captureday < 0 ? 0 : $captureday);
     $emailexpired = $emailexpired > 5 ? 5 : ($emailexpired < 0 ? 0 : $emailexpired);
     if (!empty($reviewval) && ($captureday > 0 || $emailexpired > 0)) {
         $lastcron = get_field_sql('SELECT max(lastcron) FROM ' . $CFG->prefix . 'modules');
         if (time() - intval($lastcron) > 3600 * 24) {
             return false;
         }
     }
     set_config('an_review', $reviewval);
     set_config('an_capture_day', $captureday);
     set_config('an_emailexpired', $emailexpired);
     set_config('an_emailexpiredteacher', $emailexpiredteacher);
     set_config('an_sorttype', $sorttype);
     // https and openssl library is required
     if (substr($CFG->wwwroot, 0, 5) !== 'https' and empty($CFG->loginhttps) or !check_openssl_loaded()) {
         return false;
     }
     // REQUIRED fields;
     // an_login
     $loginval = optional_param('an_login', '');
     if (empty($loginval) && empty($mconfig->an_login)) {
         return false;
     }
     $loginval = !empty($loginval) ? rc4encrypt($loginval) : strval($mconfig->an_login);
     set_config('an_login', $loginval, 'enrol/authorize');
     // an_tran_key, an_password
     $tranval = optional_param('an_tran_key', '');
     $tranval = !empty($tranval) ? rc4encrypt($tranval) : (isset($mconfig->an_tran_key) ? $mconfig->an_tran_key : '');
     $passwordval = optional_param('an_password', '');
     $passwordval = !empty($passwordval) ? rc4encrypt($passwordval) : (isset($mconfig->an_password) ? $mconfig->an_password : '');
     $deletecurrent = optional_param('delete_current', '0', PARAM_BOOL);
     if (!empty($deletecurrent) and !empty($tranval)) {
         unset_config('an_password', 'enrol/authorize');
         $passwordval = '';
     } elseif (!empty($passwordval)) {
         set_config('an_password', $passwordval, 'enrol/authorize');
     }
     if (empty($tranval) and empty($passwordval)) {
         return false;
     }
     if (!empty($tranval)) {
         set_config('an_tran_key', $tranval, 'enrol/authorize');
     }
     return true;
 }
예제 #3
0
<tr valign="top">
    <td align="right">accepts:</td>
    <td><?php 
print_string("adminaccepts", "enrol_authorize");
?>
<br /><br /><?php 
$paymentmethodsenabled = get_list_of_payment_methods();
$allpaymentmethods = get_list_of_payment_methods(true);
foreach ($allpaymentmethods as $key) {
    if ($key == AN_METHOD_CC) {
        print_checkbox('acceptmethods[]', AN_METHOD_CC, in_array(AN_METHOD_CC, $paymentmethodsenabled), get_string('method' . AN_METHOD_CC, 'enrol_authorize'));
        echo "<ul>";
        // blockquote breaks <span> and <br> tags
        $acceptedccs = array_keys(get_list_of_creditcards());
        $allccs = get_list_of_creditcards(true);
        foreach ($allccs as $key => $val) {
            echo "<li>";
            print_checkbox('acceptccs[]', $key, in_array($key, $acceptedccs), $val);
            echo "</li>";
        }
        echo "</ul>";
    } elseif ($key == AN_METHOD_ECHECK) {
        print_checkbox('acceptmethods[]', AN_METHOD_ECHECK, in_array(AN_METHOD_ECHECK, $paymentmethodsenabled), get_string('method' . AN_METHOD_ECHECK, 'enrol_authorize'));
        echo "<ul>";
        // blockquote breaks <span> and <br> tags
        $echecktypesenabled = get_list_of_bank_account_types();
        $allechecktypes = get_list_of_bank_account_types(true);
        foreach ($allechecktypes as $key) {
            echo "<li>";
            print_checkbox('acceptechecktypes[]', $key, in_array($key, $echecktypesenabled), get_string('echeck' . strtolower($key), 'enrol_authorize'));
예제 #4
0
 function validation($data, $files)
 {
     global $CFG;
     $errors = parent::validation($data, $files);
     if (AN_METHOD_CC == $data['paymentmethod']) {
         if (!in_array($data['cctype'], array_keys(get_list_of_creditcards()))) {
             $errors['cctype'] = get_string('missingcctype', 'enrol_authorize');
         }
         $expdate = sprintf("%02d", intval($data['ccexpiremm'])) . $data['ccexpireyyyy'];
         $validcc = $this->validate_cc($data['cc'], $data['cctype'], $expdate);
         if (!$validcc) {
             if ($validcc === 0) {
                 $errors['ccexpiregrp'] = get_string('ccexpired', 'enrol_authorize');
             } else {
                 $errors['cc'] = get_string('ccinvalid', 'enrol_authorize');
             }
         }
         if (!empty($CFG->an_authcode) && !empty($data['haveauth']) && empty($data['ccauthcode'])) {
             $errors['ccauthgrp'] = get_string('missingccauthcode', 'enrol_authorize');
         }
     } elseif (AN_METHOD_ECHECK == $data['paymentmethod']) {
         if (!$this->validate_aba($data['abacode'])) {
             $errors['abacode'] = get_string('invalidaba', 'enrol_authorize');
         }
         if (!in_array($data['acctype'], get_list_of_bank_account_types())) {
             $errors['acctype'] = get_string('invalidacctype', 'enrol_authorize');
         }
     }
     return $errors;
 }
예제 #5
0
/**
 * Performs an action on authorize.net and updates/inserts records. If record update fails,
 * sends email to admin.
 *
 * @param object &$order Which transaction data will be sent. See enrol_authorize table.
 * @param string &$message Information about error message.
 * @param object &$extra Extra data that used for refunding and credit card information.
 * @param int $action Which action will be performed. See AN_ACTION_*
 * @param string $cctype Used internally to configure credit types automatically.
 * @return int AN_APPROVED Transaction was successful, AN_RETURNZERO otherwise. Use $message for reason.
 * @author Ethem Evlice <ethem a.t evlice d.o.t com>
 * @uses $CFG
 */
function authorize_action(&$order, &$message, &$extra, $action = AN_ACTION_NONE, $cctype = NULL)
{
    global $CFG;
    static $conststring;
    if (!isset($conststring)) {
        $mconfig = get_config('enrol/authorize');
        $constdata = array('x_version' => '3.1', 'x_delim_data' => 'True', 'x_delim_char' => AN_DELIM, 'x_encap_char' => AN_ENCAP, 'x_relay_response' => 'FALSE', 'x_login' => rc4decrypt($mconfig->an_login));
        $str = '';
        foreach ($constdata as $ky => $vl) {
            $str .= $ky . '=' . urlencode($vl) . '&';
        }
        $str .= !empty($mconfig->an_tran_key) ? 'x_tran_key=' . urlencode(rc4decrypt($mconfig->an_tran_key)) : 'x_password='******'';
    }
    if (empty($order) or empty($order->id)) {
        $message = "Check order->id!";
        return AN_RETURNZERO;
    }
    $method = $order->paymentmethod;
    if (empty($method)) {
        $method = AN_METHOD_CC;
    } elseif ($method != AN_METHOD_CC && $method != AN_METHOD_ECHECK) {
        $message = "Invalid method: {$method}";
        return AN_RETURNZERO;
    }
    $action = intval($action);
    if ($method == AN_METHOD_ECHECK) {
        if ($action != AN_ACTION_AUTH_CAPTURE && $action != AN_ACTION_CREDIT) {
            $message = "Please perform AUTH_CAPTURE or CREDIT for echecks";
            return AN_RETURNZERO;
        }
    }
    $poststring = $conststring;
    $poststring .= '&x_method=' . $method;
    $test = !empty($CFG->an_test);
    $poststring .= '&x_test_request=' . ($test ? 'TRUE' : 'FALSE');
    switch ($action) {
        case AN_ACTION_AUTH_ONLY:
        case AN_ACTION_CAPTURE_ONLY:
        case AN_ACTION_AUTH_CAPTURE:
            if ($order->status != AN_STATUS_NONE) {
                $message = "Order status must be AN_STATUS_NONE(0)!";
                return AN_RETURNZERO;
            } elseif (empty($extra)) {
                $message = "Need extra fields!";
                return AN_RETURNZERO;
            } elseif ($action == AN_ACTION_CAPTURE_ONLY and empty($extra->x_auth_code)) {
                $message = "x_auth_code is required for capture only transactions!";
                return AN_RETURNZERO;
            }
            $ext = (array) $extra;
            $poststring .= '&x_type=' . ($action == AN_ACTION_AUTH_ONLY ? 'AUTH_ONLY' : ($action == AN_ACTION_CAPTURE_ONLY ? 'CAPTURE_ONLY' : 'AUTH_CAPTURE'));
            foreach ($ext as $k => $v) {
                $poststring .= '&' . $k . '=' . urlencode($v);
            }
            break;
        case AN_ACTION_PRIOR_AUTH_CAPTURE:
            if ($order->status != AN_STATUS_AUTH) {
                $message = "Order status must be authorized!";
                return AN_RETURNZERO;
            }
            if (authorize_expired($order)) {
                $message = "Transaction must be captured within 30 days. EXPIRED!";
                return AN_RETURNZERO;
            }
            $poststring .= '&x_type=PRIOR_AUTH_CAPTURE&x_trans_id=' . urlencode($order->transid);
            break;
        case AN_ACTION_CREDIT:
            if ($order->status != AN_STATUS_AUTHCAPTURE) {
                $message = "Order status must be authorized/captured!";
                return AN_RETURNZERO;
            }
            if (!authorize_settled($order)) {
                $message = "Order must be settled. Try VOID, check Cut-Off time if it fails!";
                return AN_RETURNZERO;
            }
            if (empty($extra->amount)) {
                $message = "No valid amount!";
                return AN_RETURNZERO;
            }
            $timenowsettle = authorize_getsettletime(time());
            $timediff = $timenowsettle - 120 * 3600 * 24;
            if ($order->settletime < $timediff) {
                $message = "Order must be credited within 120 days!";
                return AN_RETURNZERO;
            }
            $poststring .= '&x_type=CREDIT&x_trans_id=' . urlencode($order->transid);
            $poststring .= '&x_currency_code=' . urlencode($order->currency);
            $poststring .= '&x_invoice_num=' . urlencode($extra->orderid);
            $poststring .= '&x_amount=' . urlencode($extra->amount);
            if ($method == AN_METHOD_CC) {
                $poststring .= '&x_card_num=' . sprintf("%04d", intval($order->refundinfo));
            } elseif ($method == AN_METHOD_ECHECK && empty($order->refundinfo)) {
                $message = "Business checkings can be refunded only.";
                return AN_RETURNZERO;
            }
            break;
        case AN_ACTION_VOID:
            if (authorize_expired($order) || authorize_settled($order)) {
                $message = "The transaction cannot be voided due to the fact that it is expired or settled.";
                return AN_RETURNZERO;
            }
            $poststring .= '&x_type=VOID&x_trans_id=' . urlencode($order->transid);
            break;
        default:
            $message = "Invalid action: {$action}";
            return AN_RETURNZERO;
    }
    $referer = '';
    if (!(empty($CFG->an_referer) || $CFG->an_referer == "http://")) {
        $referer = "Referer: {$CFG->an_referer}\r\n";
    }
    $errno = 0;
    $errstr = '';
    $host = $test ? 'certification.authorize.net' : 'secure.authorize.net';
    $fp = fsockopen("ssl://{$host}", 443, $errno, $errstr, 60);
    if (!$fp) {
        $message = "no connection: {$errstr} ({$errno})";
        return AN_RETURNZERO;
    }
    // critical section
    @ignore_user_abort(true);
    if (intval(ini_get('max_execution_time')) > 0) {
        @set_time_limit(300);
    }
    fwrite($fp, "POST /gateway/transact.dll HTTP/1.0\r\n" . "Host: {$host}\r\n" . $referer . "Content-type: application/x-www-form-urlencoded\r\n" . "Connection: close\r\n" . "Content-length: " . strlen($poststring) . "\r\n\r\n" . $poststring . "\r\n");
    $tmpstr = '';
    while (!feof($fp) && !stristr($tmpstr, 'content-length')) {
        $tmpstr = fgets($fp, 4096);
    }
    if (!stristr($tmpstr, 'content-length')) {
        $message = "content-length error";
        @fclose($fp);
        return AN_RETURNZERO;
    }
    $length = trim(substr($tmpstr, strpos($tmpstr, 'content-length') + 15));
    fgets($fp, 4096);
    $data = fgets($fp, $length);
    @fclose($fp);
    $response = explode(AN_ENCAP . AN_DELIM . AN_ENCAP, $data);
    if ($response === false) {
        $message = "response error";
        return AN_RETURNZERO;
    }
    $rcount = count($response) - 1;
    if ($response[0][0] == AN_ENCAP) {
        $response[0] = substr($response[0], 1);
    }
    if (substr($response[$rcount], -1) == AN_ENCAP) {
        $response[$rcount] = substr($response[$rcount], 0, -1);
    }
    $responsecode = intval($response[0]);
    if ($responsecode == AN_APPROVED || $responsecode == AN_REVIEW) {
        $transid = floatval($response[6]);
        if ($test || $transid == 0) {
            return $responsecode;
            // don't update original transaction in test mode.
        }
        switch ($action) {
            case AN_ACTION_AUTH_ONLY:
            case AN_ACTION_CAPTURE_ONLY:
            case AN_ACTION_AUTH_CAPTURE:
            case AN_ACTION_PRIOR_AUTH_CAPTURE:
                $order->transid = $transid;
                if ($method == AN_METHOD_CC) {
                    if ($action == AN_ACTION_AUTH_ONLY || $responsecode == AN_REVIEW) {
                        $order->status = AN_STATUS_AUTH;
                    } else {
                        $order->status = AN_STATUS_AUTHCAPTURE;
                        $order->settletime = authorize_getsettletime(time());
                    }
                } elseif ($method == AN_METHOD_ECHECK) {
                    $order->status = AN_STATUS_UNDERREVIEW;
                }
                if (!update_record('enrol_authorize', $order)) {
                    email_to_admin("Error while trying to update data " . "in table enrol_authorize. Please edit manually this record: ID={$order->id}.", $order);
                }
                break;
            case AN_ACTION_CREDIT:
                // Credit generates new transaction id.
                // So, $extra must be updated, not $order.
                $extra->status = AN_STATUS_CREDIT;
                $extra->transid = $transid;
                $extra->settletime = authorize_getsettletime(time());
                if (!($extra->id = insert_record('enrol_authorize_refunds', $extra))) {
                    unset($extra->id);
                    email_to_admin("Error while trying to insert data " . "into table enrol_authorize_refunds. Please add manually this record:", $extra);
                }
                break;
            case AN_ACTION_VOID:
                $tableupdate = 'enrol_authorize';
                if ($order->status == AN_STATUS_CREDIT) {
                    $tableupdate = 'enrol_authorize_refunds';
                    unset($order->paymentmethod);
                }
                $order->status = AN_STATUS_VOID;
                if (!update_record($tableupdate, $order)) {
                    email_to_admin("Error while trying to update data " . "in table {$tableupdate}. Please edit manually this record: ID={$order->id}.", $order);
                }
                break;
        }
    } else {
        $reasonno = $response[2];
        $reasonstr = "reason" . $reasonno;
        $message = get_string($reasonstr, "enrol_authorize");
        if ($message == '[[' . $reasonstr . ']]') {
            $message = isset($response[3]) ? $response[3] : 'unknown error';
        }
        if ($method == AN_METHOD_CC && !empty($CFG->an_avs) && $response[5] != "P") {
            $avs = "avs" . strtolower($response[5]);
            $stravs = get_string($avs, "enrol_authorize");
            $message .= "<br />" . get_string("avsresult", "enrol_authorize", $stravs);
        }
        if (!$test) {
            // Autoconfigure :)
            switch ($reasonno) {
                // Credit card type isn't accepted
                case AN_REASON_NOCCTYPE:
                case AN_REASON_NOCCTYPE2:
                    if (!empty($cctype)) {
                        $ccaccepts = get_list_of_creditcards();
                        unset($ccaccepts[$cctype]);
                        set_config('an_acceptccs', implode(',', array_keys($ccaccepts)));
                        email_to_admin("{$message} ({$cctype})" . "This is new config(an_acceptccs):", $ccaccepts);
                    }
                    break;
                    // Echecks only
                // Echecks only
                case AN_REASON_ACHONLY:
                    set_config('an_acceptmethods', AN_METHOD_ECHECK);
                    email_to_admin("{$message} " . "This is new config(an_acceptmethods):", array(AN_METHOD_ECHECK));
                    break;
                    // Echecks aren't accepted
                // Echecks aren't accepted
                case AN_REASON_NOACH:
                    set_config('an_acceptmethods', AN_METHOD_CC);
                    email_to_admin("{$message} " . "This is new config(an_acceptmethods):", array(AN_METHOD_CC));
                    break;
                    // This echeck type isn't accepted
                // This echeck type isn't accepted
                case AN_REASON_NOACHTYPE:
                case AN_REASON_NOACHTYPE2:
                    if (!empty($extra->x_echeck_type)) {
                        switch ($extra->x_echeck_type) {
                            // CCD=BUSINESSCHECKING
                            case 'CCD':
                                set_config('an_acceptechecktypes', 'CHECKING,SAVINGS');
                                email_to_admin("{$message} " . "This is new config(an_acceptechecktypes):", array('CHECKING', 'SAVINGS'));
                                break;
                                // WEB=CHECKING or SAVINGS
                            // WEB=CHECKING or SAVINGS
                            case 'WEB':
                                set_config('an_acceptechecktypes', 'BUSINESSCHECKING');
                                email_to_admin("{$message} " . "This is new config(an_acceptechecktypes):", array('BUSINESSCHECKING'));
                                break;
                        }
                    }
                    break;
            }
        }
    }
    return $responsecode;
}