From: skodak Date: Thu, 5 Jun 2008 14:06:39 +0000 (+0000) Subject: MDL-15099 towards enrol dml conversion X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=d907d51a556a9f3deea63748c64dff0fdd1d4060;p=moodle.git MDL-15099 towards enrol dml conversion --- diff --git a/enrol/authorize/authorizenet.class.php b/enrol/authorize/authorizenet.class.php new file mode 100644 index 0000000000..0040fec55a --- /dev/null +++ b/enrol/authorize/authorizenet.class.php @@ -0,0 +1,407 @@ +dirroot.'/enrol/authorize/const.php'); +require_once($CFG->dirroot.'/enrol/authorize/localfuncs.php'); + +class AuthorizeNet +{ + const AN_DELIM = '|'; + const AN_ENCAP = '"'; + + const AN_REASON_NOCCTYPE = 17; + const AN_REASON_NOCCTYPE2 = 28; + const AN_REASON_NOACH = 18; + const AN_REASON_ACHONLY = 56; + const AN_REASON_NOACHTYPE = 245; + const AN_REASON_NOACHTYPE2 = 246; + + /** + * Gets settlement time + * + * @param int $time Time processed, usually now. + * @return int Settlement time + */ + public static function getsettletime($time) + { + global $CFG; + + $cutoff = intval($CFG->an_cutoff); + $mins = $cutoff % 60; + $hrs = ($cutoff - $mins) / 60; + $cutofftime = strtotime("$hrs:$mins", $time); + if ($cutofftime < $time) { + $cutofftime = strtotime("$hrs:$mins", $time + (24 * 3600)); + } + return $cutofftime; + } + + /** + * Is order settled? Status must be auth_captured or credited. + * + * @param object $order Order details + * @return bool true, if settled, false otherwise. + */ + public static function settled($order) + { + return ((AN_STATUS_AUTHCAPTURE == $order->status || AN_STATUS_CREDIT == $order->status) and ($order->settletime > 0) and ($order->settletime < time())); + } + + /** + * Is order expired? 'Authorized/Pending Capture' transactions are expired after 30 days. + * + * @param object &$order Order details. + * @return bool true, transaction is expired, false otherwise. + */ + public static function expired(&$order) + { + global $DB; + static $timediff30; + + if ($order->status == AN_STATUS_EXPIRE) { + return true; + } + elseif ($order->status != AN_STATUS_AUTH) { + return false; + } + + if (empty($timediff30)) { + $timediff30 = self::getsettletime(time()) - (30 * 24 * 3600); + } + + $expired = self::getsettletime($order->timecreated) < $timediff30; + if ($expired) + { + $order->status = AN_STATUS_EXPIRE; + $DB->update_record('enrol_authorize', $order); + } + return $expired; + } + + /** + * 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; + require_once($CFG->libdir.'/filelib.php'); + + if (!isset($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' => rc4decrypt($mconfig->an_login) + ); + + if (!empty($mconfig->an_tran_key)) { + $constpd['x_tran_key'] = rc4decrypt($mconfig->an_tran_key); + } + else { + $constpd['x_password'] = rc4decrypt($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($CFG->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($CFG->an_referer) || $CFG->an_referer == "http://")) { + $headers['Referer'] = $CFG->an_referer; + } + + @ignore_user_abort(true); + if (intval(ini_get('max_execution_time')) > 0) { + @set_time_limit(300); + } + + $host = $test ? 'certification.authorize.net' : 'secure.authorize.net'; + $data = download_file_content("https://$host:443/gateway/transact.dll", $headers, $pd, false, 60); + 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 = intval($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; + } + + if (!$DB->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 = self::getsettletime(time()); + if (! $extra->id = $DB->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 (! $DB->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 .= "
" . 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_acceptccs', implode(',', array_keys($ccaccepts))); + email_to_admin("$message ($cctype) This is new config(an_acceptccs):", $ccaccepts); + } + break; + } + // Echecks only + case self::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 + case self::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 + 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_acceptechecktypes', 'CHECKING,SAVINGS'); + email_to_admin("$message This is new config(an_acceptechecktypes):", array('CHECKING','SAVINGS')); + } + break; + // 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; + } +} + +?> diff --git a/enrol/authorize/enrol.php b/enrol/authorize/enrol.php index 60d4c4ce4d..ead43b83f8 100755 --- a/enrol/authorize/enrol.php +++ b/enrol/authorize/enrol.php @@ -147,7 +147,7 @@ class enrolment_plugin_authorize */ private function cc_submit($form, $course) { - global $CFG, $USER, $SESSION; + global $CFG, $USER, $SESSION, $DB; prevent_double_paid($course); @@ -169,7 +169,7 @@ class enrolment_plugin_authorize $order->timecreated = $timenow; $order->amount = $curcost['cost']; $order->currency = $curcost['currency']; - $order->id = insert_record("enrol_authorize", $order); + $order->id = $DB->insert_record("enrol_authorize", $order); if (!$order->id) { email_to_admin("Error while trying to insert new data", $order); return "Insert record error. Admin has been notified!"; @@ -324,7 +324,7 @@ class enrolment_plugin_authorize */ private function echeck_submit($form, $course) { - global $CFG, $USER, $SESSION; + global $CFG, $USER, $SESSION, $DB; prevent_double_paid($course); @@ -346,7 +346,7 @@ class enrolment_plugin_authorize $order->timecreated = $timenow; $order->amount = $curcost['cost']; $order->currency = $curcost['currency']; - $order->id = insert_record("enrol_authorize", $order); + $order->id = $DB->insert_record("enrol_authorize", $order); if (!$order->id) { email_to_admin("Error while trying to insert new data", $order); return "Insert record error. Admin has been notified!"; @@ -433,7 +433,7 @@ class enrolment_plugin_authorize */ public function config_form($frm) { - global $CFG; + global $CFG, $DB; $mconfig = get_config('enrol/authorize'); if (!check_curl_available()) { @@ -470,7 +470,7 @@ class enrolment_plugin_authorize } } - if (($count = count_records('enrol_authorize', 'status', AN_STATUS_AUTH))) { + if (($count = $DB->count_records('enrol_authorize', array('status'=>AN_STATUS_AUTH)))) { $a = new stdClass; $a->count = $count; $a->url = $CFG->wwwroot."/enrol/authorize/index.php?status=".AN_STATUS_AUTH; @@ -600,7 +600,7 @@ class enrolment_plugin_authorize */ public function cron() { - global $CFG; + global $CFG, $DB; $oneday = 86400; $timenow = time(); @@ -624,8 +624,9 @@ class enrolment_plugin_authorize } $timediffcnf = $settlementtime - (intval($CFG->an_capture_day) * $oneday); - $select = "(status = '" .AN_STATUS_AUTH. "') AND (timecreated < '$timediffcnf') AND (timecreated > '$timediff30')"; - if (!($ordercount = count_records_select('enrol_authorize', $select))) { + $select = "(status = ?) AND (timecreated < ?) AND (timecreated > ?)"; + $params = array(AN_STATUS_AUTH, $timediffcnf, $timediff30); + if (!($ordercount = $DB->count_records_select('enrol_authorize', $select, $params))) { mtrace("no pending orders"); return; } @@ -647,14 +648,15 @@ class enrolment_plugin_authorize $this->log = "AUTHORIZE.NET AUTOCAPTURE CRON: " . userdate($timenow) . "\n"; $lastcourseid = 0; - for ($rs = get_recordset_select('enrol_authorize', $select, 'courseid'); ($order = rs_fetch_next_record($rs)); ) + $rs = $DB->get_recordset_select('enrol_authorize', $select, 'courseid', $params); + foreach ( $rs as $order) { $message = ''; $extra = NULL; if (AN_APPROVED == AuthorizeNet::process($order, $message, $extra, AN_ACTION_PRIOR_AUTH_CAPTURE)) { if ($lastcourseid != $order->courseid) { $lastcourseid = $order->courseid; - $course = get_record('course', 'id', $lastcourseid); + $course = $DB->get_record('course', array('id'=>$lastcourseid)); $role = get_default_course_role($course); $context = get_context_instance(CONTEXT_COURSE, $lastcourseid); } @@ -663,7 +665,7 @@ class enrolment_plugin_authorize $timestart = $timenow; $timeend = $order->settletime + $course->enrolperiod; } - $user = get_record('user', 'id', $order->userid); + $user = $DB->get_record('user', array('id'=>$order->userid)); if (role_assign($role->id, $user->id, 0, $context->id, $timestart, $timeend, 0, 'authorize')) { $this->log .= "User($user->id) has been enrolled to course($course->id).\n"; if (!empty($CFG->enrol_mailstudents)) { @@ -681,7 +683,7 @@ class enrolment_plugin_authorize $this->log .= "Error, Order# $order->id: " . $message . "\n"; } } - rs_close($rs); + $rs->close(); mtrace("processed"); $timenow = time(); @@ -714,7 +716,7 @@ class enrolment_plugin_authorize */ private function cron_daily() { - global $CFG, $SITE; + global $CFG, $SITE, $DB; $oneday = 86400; $timenow = time(); @@ -722,25 +724,29 @@ class enrolment_plugin_authorize $settlementtime = AuthorizeNet::getsettletime($timenow); $timediff30 = $settlementtime - (30 * $oneday); - $select = "(status='".AN_STATUS_NONE."') AND (timecreated<'$timediff30')"; - if (delete_records_select('enrol_authorize', $select)) { + $select = "(status=?) AND (timecreateddelete_records_select('enrol_authorize', $select, $params)) { mtrace(" orders no transaction made have deleted"); } - $select = "(status='".AN_STATUS_AUTH."') AND (timecreated<'$timediff30')"; - if (execute_sql("UPDATE {$CFG->prefix}enrol_authorize SET status='".AN_STATUS_EXPIRE."' WHERE $select", false)) { + $select = "(status=?) AND (timecreatedexecute("UPDATE {enrol_authorize SET status=? WHERE $select", $params)) { mtrace(" pending orders to expire have updated"); } $timediff60 = $settlementtime - (60 * $oneday); - $select = "(status='".AN_STATUS_EXPIRE."') AND (timecreated<'$timediff60')"; - if (delete_records_select('enrol_authorize', $select)) { + $select = "(status=?) AND (timecreateddelete_records_select('enrol_authorize', $select, $params)) { mtrace(" orders expired older than 60 days have deleted"); } $adminuser = get_admin(); - $select = "status IN(".AN_STATUS_UNDERREVIEW.",".AN_STATUS_APPROVEDREVIEW.") AND (timecreated<'$onepass') AND (timecreated>'$timediff60')"; - if (($count = count_records_select('enrol_authorize', $select)) && + $select = "status IN(?,?) AND (timecreated?)"; + $params = array(AN_STATUS_UNDERREVIEW, AN_STATUS_APPROVEDREVIEW, $onepass, $timediff30); + if (($count = $DB->count_records_select('enrol_authorize', $select, $params)) && ($csvusers = get_users_by_capability(get_context_instance(CONTEXT_SYSTEM), 'enrol/authorize:uploadcsv'))) { $a = new stdClass; $a->count = $count; @@ -764,8 +770,9 @@ class enrolment_plugin_authorize $timediffem = $settlementtime - ((30 - intval($CFG->an_emailexpired)) * $oneday); - $select = "(status='". AN_STATUS_AUTH ."') AND (timecreated<'$timediffem') AND (timecreated>'$timediff30')"; - $count = count_records_select('enrol_authorize', $select); + $select = "(status=?) AND (timecreated?)"; + $params = array(AN_STATUS_AUTH, $timediffem, $timediff30); + $count = $DB->count_records_select('enrol_authorize', $select, $params); if (!$count) { mtrace("no orders prior to $CFG->an_emailexpired days"); return; @@ -794,15 +801,17 @@ class enrolment_plugin_authorize $sorttype = empty($CFG->an_sorttype) ? 'ttl' : $CFG->an_sorttype; $sql = "SELECT e.courseid, e.currency, c.fullname, c.shortname, COUNT(e.courseid) AS cnt, SUM(e.amount) as ttl - FROM {$CFG->prefix}enrol_authorize e - INNER JOIN {$CFG->prefix}course c ON c.id = e.courseid - WHERE (e.status = ". AN_STATUS_AUTH .") - AND (e.timecreated < $timediffem) - AND (e.timecreated > $timediff30) + FROM {enrol_authorize} e + INNER JOIN {course} c ON c.id = e.courseid + WHERE (e.status = ?) + AND (e.timecreated < ?) + AND (e.timecreated > ?) GROUP BY e.courseid ORDER BY $sorttype DESC"; + $params = array(AN_STATUS_AUTH, $timediffem, $timediff30); - for ($rs = get_recordset_sql($sql); ($courseinfo = rs_fetch_next_record($rs)); ) + $rs = $DB->get_recordset_sql($sql, $params); + foreach ($rs as $courseinfo) { $lastcourse = $courseinfo->courseid; $context = get_context_instance(CONTEXT_COURSE, $lastcourse); @@ -825,7 +834,7 @@ class enrolment_plugin_authorize } } } - rs_close($rs); + $rs->close(); } } ?> diff --git a/enrol/authorize/index.php b/enrol/authorize/index.php index 60146ac9f2..32500db85e 100644 --- a/enrol/authorize/index.php +++ b/enrol/authorize/index.php @@ -13,7 +13,7 @@ $userid = optional_param('user', 0, PARAM_INT); /// Get course - if (! $course = get_record('course', 'id', $courseid)) { + if (! $course = $DB->get_record('course', array('id'=>$courseid))) { print_error('invaliduserid'); } diff --git a/enrol/authorize/localfuncs.php b/enrol/authorize/localfuncs.php index 729c478825..140443fbaa 100644 --- a/enrol/authorize/localfuncs.php +++ b/enrol/authorize/localfuncs.php @@ -120,7 +120,7 @@ function email_to_admin($subject, $data) function send_welcome_messages($orderdata) { - global $CFG, $SITE; + global $CFG, $SITE, $DB; if (empty($orderdata)) { return; @@ -131,12 +131,12 @@ function send_welcome_messages($orderdata) } $sql = "SELECT e.id, e.courseid, e.userid, c.fullname - FROM {$CFG->prefix}enrol_authorize e - INNER JOIN {$CFG->prefix}course c ON c.id = e.courseid + FROM {enrol_authorize} e + INNER JOIN {course} c ON c.id = e.courseid WHERE e.id IN(" . implode(',', $orderdata) . ") ORDER BY e.userid"; - if (($rs = get_recordset_sql($sql)) && ($ei = rs_fetch_next_record($rs))) + if (($rs = $DB->get_recordset_sql($sql)) && ($ei = rs_fetch_next_record($rs))) { if (1 < count($orderdata)) { $sender = get_admin(); @@ -157,7 +157,7 @@ function send_welcome_messages($orderdata) $ei = rs_fetch_next_record($rs); } - if (($user = get_record('user', 'id', $lastuserid))) { + if (($user = $DB->get_record('user', array('id'=>$lastuserid)))) { $a = new stdClass; $a->name = $user->firstname; $a->courses = implode("\n", $usercourses);