Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/enrol/authorize/authorizenet.class.php
Go to the documentation of this file.
00001 <?php
00002 // This file is part of Moodle - http://moodle.org/
00003 //
00004 // Moodle is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // Moodle is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00016 
00030 if (!defined('MOODLE_INTERNAL')) {
00031     die('Direct access to this script is forbidden.');
00032 }
00033 
00034 require_once($CFG->dirroot.'/enrol/authorize/const.php');
00035 require_once($CFG->dirroot.'/enrol/authorize/localfuncs.php');
00036 
00037 class AuthorizeNet
00038 {
00039     const AN_DELIM = '|';
00040     const AN_ENCAP = '"';
00041 
00042     const AN_REASON_NOCCTYPE    =   17;
00043     const AN_REASON_NOCCTYPE2   =   28;
00044     const AN_REASON_NOACH       =   18;
00045     const AN_REASON_ACHONLY     =   56;
00046     const AN_REASON_NOACHTYPE   =  245;
00047     const AN_REASON_NOACHTYPE2  =  246;
00048 
00055     public static function getsettletime($time)
00056     {
00057         $mconfig = get_config('enrol_authorize');
00058 
00059         $cutoff_hour = intval($mconfig->an_cutoff_min);
00060         $cutoff_min = intval($mconfig->an_cutoff_hour);
00061         $cutofftime = strtotime("{$cutoff_hour}:{$cutoff_min}", $time);
00062         if ($cutofftime < $time) {
00063             $cutofftime = strtotime("{$cutoff_hour}:{$cutoff_min}", $time + (24 * 3600));
00064         }
00065         return $cutofftime;
00066     }
00067 
00074     public static function settled($order)
00075     {
00076         return ((AN_STATUS_AUTHCAPTURE == $order->status || AN_STATUS_CREDIT == $order->status) and ($order->settletime > 0) and ($order->settletime < time()));
00077     }
00078 
00085     public static function expired(&$order)
00086     {
00087         global $DB;
00088         static $timediff30 = 0;
00089 
00090         if ($order->status == AN_STATUS_EXPIRE) {
00091             return true;
00092         }
00093         elseif ($order->status != AN_STATUS_AUTH) {
00094             return false;
00095         }
00096 
00097         if (0 == $timediff30) {
00098             $timediff30 = self::getsettletime(time()) - (30 * 24 * 3600);
00099         }
00100 
00101         $expired = self::getsettletime($order->timecreated) < $timediff30;
00102         if ($expired)
00103         {
00104             $order->status = AN_STATUS_EXPIRE;
00105             $DB->update_record('enrol_authorize', $order);
00106         }
00107         return $expired;
00108     }
00109 
00121     public static function process(&$order, &$message, &$extra, $action=AN_ACTION_NONE, $cctype=NULL)
00122     {
00123         global $CFG, $DB;
00124         static $constpd = array();
00125         require_once($CFG->libdir.'/filelib.php');
00126 
00127         $mconfig = get_config('enrol_authorize');
00128 
00129         if (empty($constpd)) {
00130             $mconfig = get_config('enrol_authorize');
00131             $constpd = array(
00132                 'x_version'         => '3.1',
00133                 'x_delim_data'      => 'True',
00134                 'x_delim_char'      => self::AN_DELIM,
00135                 'x_encap_char'      => self::AN_ENCAP,
00136                 'x_relay_response'  => 'FALSE',
00137                 'x_login'           => $mconfig->an_login
00138             );
00139 
00140             if (!empty($mconfig->an_tran_key)) {
00141                 $constpd['x_tran_key'] = $mconfig->an_tran_key;
00142             }
00143             else {
00144                 $constpd['x_password'] = $mconfig->an_password;
00145             }
00146         }
00147 
00148         if (empty($order) or empty($order->id)) {
00149             $message = "Check order->id!";
00150             return AN_RETURNZERO;
00151         }
00152 
00153         $method = $order->paymentmethod;
00154         if (empty($method)) {
00155             $method = AN_METHOD_CC;
00156         }
00157         elseif ($method != AN_METHOD_CC && $method != AN_METHOD_ECHECK) {
00158             $message = "Invalid method: $method";
00159             return AN_RETURNZERO;
00160         }
00161 
00162         $action = intval($action);
00163         if ($method == AN_METHOD_ECHECK) {
00164             if ($action != AN_ACTION_AUTH_CAPTURE && $action != AN_ACTION_CREDIT) {
00165                 $message = "Please perform AUTH_CAPTURE or CREDIT for echecks";
00166                 return AN_RETURNZERO;
00167             }
00168         }
00169 
00170         $pd = $constpd;
00171         $pd['x_method'] = $method;
00172         $test = !empty($mconfig->an_test);
00173         $pd['x_test_request'] = ($test ? 'TRUE' : 'FALSE');
00174 
00175         switch ($action) {
00176             case AN_ACTION_AUTH_ONLY:
00177             case AN_ACTION_CAPTURE_ONLY:
00178             case AN_ACTION_AUTH_CAPTURE:
00179                 {
00180                     if ($order->status != AN_STATUS_NONE) {
00181                         $message = "Order status must be AN_STATUS_NONE(0)!";
00182                         return AN_RETURNZERO;
00183                     }
00184                     elseif (empty($extra)) {
00185                         $message = "Need extra fields!";
00186                         return AN_RETURNZERO;
00187                     }
00188                     elseif (($action == AN_ACTION_CAPTURE_ONLY) and empty($extra->x_auth_code)) {
00189                         $message = "x_auth_code is required for capture only transactions!";
00190                         return AN_RETURNZERO;
00191                     }
00192 
00193                     $ext = (array)$extra;
00194                     $pd['x_type'] = (($action==AN_ACTION_AUTH_ONLY)
00195                                       ? 'AUTH_ONLY' :( ($action==AN_ACTION_CAPTURE_ONLY)
00196                                                         ? 'CAPTURE_ONLY' : 'AUTH_CAPTURE'));
00197                     foreach($ext as $k => $v) {
00198                         $pd[$k] = $v;
00199                     }
00200                 }
00201                 break;
00202 
00203             case AN_ACTION_PRIOR_AUTH_CAPTURE:
00204                 {
00205                     if ($order->status != AN_STATUS_AUTH) {
00206                         $message = "Order status must be authorized!";
00207                         return AN_RETURNZERO;
00208                     }
00209                     if (self::expired($order)) {
00210                         $message = "Transaction must be captured within 30 days. EXPIRED!";
00211                         return AN_RETURNZERO;
00212                     }
00213                     $pd['x_type'] = 'PRIOR_AUTH_CAPTURE';
00214                     $pd['x_trans_id'] = $order->transid;
00215                 }
00216                 break;
00217 
00218             case AN_ACTION_CREDIT:
00219                 {
00220                     if ($order->status != AN_STATUS_AUTHCAPTURE) {
00221                         $message = "Order status must be authorized/captured!";
00222                         return AN_RETURNZERO;
00223                     }
00224                     if (!self::settled($order)) {
00225                         $message = "Order must be settled. Try VOID, check Cut-Off time if it fails!";
00226                         return AN_RETURNZERO;
00227                     }
00228                     if (empty($extra->amount)) {
00229                         $message = "No valid amount!";
00230                         return AN_RETURNZERO;
00231                     }
00232                     $timenowsettle = self::getsettletime(time());
00233                     $timediff = $timenowsettle - (120 * 3600 * 24);
00234                     if ($order->settletime < $timediff) {
00235                         $message = "Order must be credited within 120 days!";
00236                         return AN_RETURNZERO;
00237                     }
00238 
00239                     $pd['x_type'] = 'CREDIT';
00240                     $pd['x_trans_id'] = $order->transid;
00241                     $pd['x_currency_code'] = $order->currency;
00242                     $pd['x_invoice_num'] = $extra->orderid;
00243                     $pd['x_amount'] = $extra->amount;
00244                     if ($method == AN_METHOD_CC) {
00245                         $pd['x_card_num'] = sprintf("%04d", intval($order->refundinfo));
00246                     }
00247                     elseif ($method == AN_METHOD_ECHECK && empty($order->refundinfo)) {
00248                         $message = "Business checkings can be refunded only.";
00249                         return AN_RETURNZERO;
00250                     }
00251                 }
00252                 break;
00253 
00254             case AN_ACTION_VOID:
00255                 {
00256                     if (self::expired($order) || self::settled($order)) {
00257                         $message = "The transaction cannot be voided due to the fact that it is expired or settled.";
00258                         return AN_RETURNZERO;
00259                     }
00260                     $pd['x_type'] = 'VOID';
00261                     $pd['x_trans_id'] = $order->transid;
00262                 }
00263                 break;
00264 
00265             default:
00266             {
00267                 $message = "Invalid action: $action";
00268                 return AN_RETURNZERO;
00269             }
00270         }
00271 
00272         $headers = array('Connection' => 'close');
00273         if (! (empty($mconfig->an_referer) || $mconfig->an_referer == "http://")) {
00274             $headers['Referer'] = $mconfig->an_referer;
00275         }
00276 
00277         @ignore_user_abort(true);
00278         if (intval(ini_get('max_execution_time')) > 0) {
00279             @set_time_limit(300);
00280         }
00281 
00282         $host = $test ? 'test.authorize.net' : 'secure.authorize.net';
00283         $data = download_file_content("https://$host:443/gateway/transact.dll", $headers, $pd, false, 300, 60, true);
00284         if (!$data) {
00285             $message = "No connection to https://$host:443";
00286             return AN_RETURNZERO;
00287         }
00288         $response = explode(self::AN_ENCAP.self::AN_DELIM.self::AN_ENCAP, $data);
00289         if ($response === false) {
00290             $message = "response error";
00291             return AN_RETURNZERO;
00292         }
00293         $rcount = count($response) - 1;
00294         if ($response[0]{0} == self::AN_ENCAP) {
00295             $response[0] = substr($response[0], 1);
00296         }
00297         if (substr($response[$rcount], -1) == self::AN_ENCAP) {
00298             $response[$rcount] = substr($response[$rcount], 0, -1);
00299         }
00300 
00301         $responsecode = intval($response[0]);
00302         if ($responsecode == AN_APPROVED || $responsecode == AN_REVIEW)
00303         {
00304             $transid = floatval($response[6]);
00305             if ($test || $transid == 0) {
00306                 return $responsecode; // don't update original transaction in test mode.
00307             }
00308             switch ($action) {
00309                 case AN_ACTION_AUTH_ONLY:
00310                 case AN_ACTION_CAPTURE_ONLY:
00311                 case AN_ACTION_AUTH_CAPTURE:
00312                 case AN_ACTION_PRIOR_AUTH_CAPTURE:
00313                     {
00314                         $order->transid = $transid;
00315 
00316                         if ($method == AN_METHOD_CC) {
00317                             if ($action == AN_ACTION_AUTH_ONLY || $responsecode == AN_REVIEW) {
00318                                 $order->status = AN_STATUS_AUTH;
00319                             } else {
00320                                 $order->status = AN_STATUS_AUTHCAPTURE;
00321                                 $order->settletime = self::getsettletime(time());
00322                             }
00323                         }
00324                         elseif ($method == AN_METHOD_ECHECK) {
00325                             $order->status = AN_STATUS_UNDERREVIEW;
00326                         }
00327 
00328                         $DB->update_record('enrol_authorize', $order);
00329                     }
00330                     break;
00331 
00332                 case AN_ACTION_CREDIT:
00333                     {
00334                         // Credit generates new transaction id.
00335                         // So, $extra must be updated, not $order.
00336                         $extra->status = AN_STATUS_CREDIT;
00337                         $extra->transid = $transid;
00338                         $extra->settletime = self::getsettletime(time());
00339                         $extra->id = $DB->insert_record('enrol_authorize_refunds', $extra);
00340                     }
00341                     break;
00342 
00343                 case AN_ACTION_VOID:
00344                     {
00345                         $tableupdate = 'enrol_authorize';
00346                         if ($order->status == AN_STATUS_CREDIT) {
00347                             $tableupdate = 'enrol_authorize_refunds';
00348                             unset($order->paymentmethod);
00349                         }
00350                         $order->status = AN_STATUS_VOID;
00351                         $DB->update_record($tableupdate, $order);
00352                     }
00353                     break;
00354             }
00355         }
00356         else
00357         {
00358             $reasonno = $response[2];
00359             $reasonstr = "reason" . $reasonno;
00360             $message = get_string($reasonstr, "enrol_authorize");
00361             if ($message == '[[' . $reasonstr . ']]') {
00362                 $message = isset($response[3]) ? $response[3] : 'unknown error';
00363             }
00364             if ($method == AN_METHOD_CC && !empty($mconfig->an_avs) && $response[5] != "P") {
00365                 $avs = "avs" . strtolower($response[5]);
00366                 $stravs = get_string($avs, "enrol_authorize");
00367                 $message .= "<br />" . get_string("avsresult", "enrol_authorize", $stravs);
00368             }
00369             if (!$test) { // Autoconfigure :)
00370                 switch($reasonno) {
00371                     // Credit card type isn't accepted
00372                     case self::AN_REASON_NOCCTYPE:
00373                     case self::AN_REASON_NOCCTYPE2:
00374                         {
00375                             if (!empty($cctype)) {
00376                                 $ccaccepts = get_list_of_creditcards();
00377 
00378                                 unset($ccaccepts[$cctype]);
00379                                 set_config("an_acceptcc_{$cctype}", 0, 'enrol_authorize');
00380 
00381                                 foreach ($ccaccepts as $key=>$val) {
00382                                     set_config("an_acceptcc_{$key}", 1, 'enrol_authorize');
00383                                 }
00384                                 message_to_admin("$message ($cctype) This is new config(an_acceptccs):", $ccaccepts);
00385                             }
00386                             break;
00387                         }
00388                     // Echecks only
00389                     case self::AN_REASON_ACHONLY:
00390                         {
00391                             set_config("an_acceptmethod_".AN_METHOD_ECHECK, 1, 'enrol_authorize');
00392                             message_to_admin("$message This is new config(an_acceptmethods):", array(AN_METHOD_ECHECK));
00393                             break;
00394                         }
00395                     // Echecks aren't accepted
00396                     case self::AN_REASON_NOACH:
00397                         {
00398                             set_config("an_acceptmethod_".AN_METHOD_CC, 1, 'enrol_authorize');
00399                             message_to_admin("$message This is new config(an_acceptmethods):", array(AN_METHOD_CC));
00400                             break;
00401                         }
00402                     // This echeck type isn't accepted
00403                     case self::AN_REASON_NOACHTYPE:
00404                     case self::AN_REASON_NOACHTYPE2:
00405                         {
00406                             if (!empty($extra->x_echeck_type)) {
00407                                 switch ($extra->x_echeck_type) {
00408                                     // CCD=BUSINESSCHECKING
00409                                     case 'CCD':
00410                                         {
00411                                             set_config('an_acceptecheck_CHECKING', 1, 'enrol_authorize');
00412                                             set_config('an_acceptecheck_SAVINGS', 1, 'enrol_authorize');
00413                                             message_to_admin("$message This is new config(an_acceptechecktypes):", array('CHECKING','SAVINGS'));
00414                                         }
00415                                         break;
00416                                     // WEB=CHECKING or SAVINGS
00417                                     case 'WEB':
00418                                         {
00419                                             set_config('an_acceptecheck_BUSINESSCHECKING', 1, 'enrol_authorize');
00420                                             message_to_admin("$message This is new config(an_acceptechecktypes):", array('BUSINESSCHECKING'));
00421                                         }
00422                                         break;
00423                                 }
00424                             }
00425                             break;
00426                         }
00427                 }
00428             }
00429         }
00430         return $responsecode;
00431     }
00432 }
00433 
00434 
 All Data Structures Namespaces Files Functions Variables Enumerations