pos/is4c-nf/plugins/Paycards/lib/PaycardDialogs.php
<?php
/*******************************************************************************
Copyright 2012 Whole Foods Co-op
This file is part of IT CORE.
IT CORE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
IT CORE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
in the file license.txt along with IT CORE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*********************************************************************************/
use COREPOS\pos\plugins\Paycards\card\CardReader;
use COREPOS\pos\plugins\Paycards\card\CardValidator;
class PaycardDialogs
{
public function __construct()
{
$this->conf = new PaycardConf();
$this->reader = new CardReader();
$this->dbTrans = PaycardLib::paycard_db();
}
public function enabledCheck()
{
if ($this->conf->get('CCintegrate') != 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Card Integration Disabled",
"Please process credit cards in standalone",
"[clear] to cancel"
));
}
return true;
}
public function validateCard($pan, $expirable=true, $luhn=true)
{
$validator = new CardValidator();
if ($luhn && $validator->validNumber($pan) != 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Invalid Card Number",
"Swipe again or type in manually",
"[clear] to cancel"));
} elseif (!$this->reader->accepted($pan)) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardMsgBox("Unsupported Card Type",
"We cannot process " . $this->conf->get("paycard_issuer") . " cards",
"[clear] to cancel"));
} elseif ($expirable && $validator->validExpiration($this->conf->get("paycard_exp")) != 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Invalid Expiration Date",
"The expiration date has passed or was not recognized",
"[clear] to cancel"));
}
return true;
}
public function voidableCheck($pan4, $trans)
{
$today = date('Ymd');
$sql = 'SELECT transID
FROM PaycardTransactions
WHERE dateID=' . $today . '
AND empNo=' . $trans[0] . '
AND registerNo=' . $trans[1] . '
AND transNo=' . $trans[2] . '
AND PAN LIKE \'%' . $pan4 . '\'';
$search = $this->dbTrans->query($sql);
$num = $this->dbTrans->numRows($search);
if ($num < 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardMsgBox("Card Not Used",
"That card number was not used in this transaction",
"[clear] to cancel"
));
} elseif ($num > 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardMsgBox("Multiple Uses",
"That card number was used more than once in this transaction; select the payment and press VOID",
"[clear] to cancel"
));
}
$payment = $this->dbTrans->fetchRow($search);
return $payment['transID'];
}
public function invalidMode()
{
$mode = $this->conf->get('paycard_mode');
$type = $this->conf->get('paycard_type');
return PaycardLib::paycardErrBox("Invalid Mode",
"This card type does not support that processing mode ({$mode},{$type})",
"[clear] to cancel"
);
}
public function getRequest($trans, $transID)
{
$today = date('Ymd');
// look up the request using transID (within this transaction)
$sql = "SELECT live,
PAN,
transType AS mode,
amount,
name
FROM PaycardTransactions
WHERE dateID=" . $today . "
AND empNo=" . $trans[0] . "
AND registerNo=" . $trans[1] . "
AND transNo=" . $trans[2] . "
AND transID=" . $transID;
$search = $this->dbTrans->query($sql);
$num = $this->dbTrans->numRows($search);
if ($num < 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Internal Error",
"Card request not found, unable to void",
"[clear] to cancel"
));
} elseif ($num > 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Internal Error",
"Card request not distinct, unable to void",
"[clear] to cancel"
));
}
$request = $this->dbTrans->fetchRow($search);
return $request;
}
public function getResponse($trans, $transID)
{
$today = date('Ymd');
$sql = "SELECT commErr,
httpCode,
validResponse,
xResultCode AS xResponseCode,
xTransactionID
FROM PaycardTransactions
WHERE dateID=" . $today . "
AND empNo=" . $trans[0] . "
AND registerNo=" . $trans[1] ."
AND transNo=" . $trans[2] . "
AND transID=" . $transID;
$search = $this->dbTrans->query($sql);
$num = $this->dbTrans->numRows($search);
if ($num < 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Internal Error",
"Card response not found, unable to void",
"[clear] to cancel"
));
} elseif ($num > 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Internal Error",
"Card response not distinct, unable to void",
"[clear] to cancel"
));
}
$response = $this->dbTrans->fetchRow($search);
return $response;
}
public function getTenderLine($trans, $transID)
{
// look up the transaction tender line-item
$sql = "SELECT trans_type,
trans_subtype,
trans_status,
voided
FROM localtemptrans
WHERE trans_id=" . $transID;
$search = $this->dbTrans->query($sql);
$num = $this->dbTrans->numRows($search);
if ($num < 1) {
$sql = "SELECT * FROM localtranstoday WHERE trans_id=".$transID." and emp_no=".$trans[0]
." and register_no=".$trans[1]." and trans_no=".$trans[2]
." AND datetime >= " . $this->dbTrans->curdate();
$search = $this->dbTrans->query($sql);
$num = $this->dbTrans->numRows($search);
if ($num != 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Internal Error",
"Transaction item not found, unable to void",
"[clear] to cancel"
));
}
} elseif ($num > 1) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Internal Error",
"Transaction item not distinct, unable to void",
"[clear] to cancel"
));
}
$lineitem = $this->dbTrans->fetchRow($search);
return $lineitem;
}
public function notVoided($trans, $transID)
{
$today = date('Ymd');
$sql = "SELECT transID
FROM PaycardTransactions
WHERE dateID=" . $today . "
AND empNo=" . $trans[0] . "
AND registerNo=" . $trans[1] . "
AND transNo=" . $trans[2] . "
AND transID=" . $transID . "
AND transType='VOID'
AND xResultCode=1";
$search = $this->dbTrans->query($sql);
$voided = $this->dbTrans->numRows($search);
if ($voided > 0) {
$this->conf->reset();
throw new Exception(PaycardLib::paycardErrBox("Unable to Void",
"Card transaction already voided",
"[clear] to cancel"
));
}
return true;
}
private function voidReqResp($request, $response)
{
$error = false;
if ($response['commErr'] != 0 || $response['httpCode'] != 200 || $response['validResponse'] != 1) {
$error = _("Card transaction not successful");
} elseif ($request['live'] != $this->paycardLive(PaycardLib::PAYCARD_TYPE_CREDIT)) {
// this means the transaction was submitted to the test platform, but we now think we're in live mode, or vice-versa
// I can't imagine how this could happen (short of serious $_SESSION corruption), but worth a check anyway.. --atf 7/26/07
$error = _("Processor platform mismatch");
} elseif( $response['xResponseCode'] != 1) {
$error = _("Card transaction not approved");
} elseif( $response['xTransactionID'] < 1) {
$error = _("Invalid reference number");
}
return $error;
}
private function voidLineItem($lineitem)
{
$error = false;
if ($lineitem['trans_type'] != "T" || ($lineitem['trans_subtype'] != "CC" && $lineitem['trans_subtype'] != 'DC'
&& $lineitem['trans_subtype'] != 'EF' && $lineitem['trans_subtype'] != 'EC' && $lineitem['trans_subtype'] != 'AX') ) {
$error = _("Authorization and tender records do not match ");
} elseif ($lineitem['trans_status'] == "V" || $lineitem['voided'] != 0) {
$error = _("Void records do not match");
}
return $error;
}
public function validateVoid($request, $response, $lineitem)
{
// make sure the payment is applicable to void
$errHeader = _('Unable to Void');
$buttons = _('[clear] to cancel');
$error = $this->voidReqResp($request, $response);
if ($error === false) {
$error = $this->voidLineItem($lineitem);
}
if ($error !== false) {
throw new Exception(PaycardLib::paycardErrBox($errHeader, $error, $buttons));
}
return true;
}
/**
Check whether paycards of a given type are enabled
@param $type is a paycard type constant
@return
- 1 if type is enabled
- 0 if type is disabled
*/
public function paycardLive($type = PaycardLib::PAYCARD_TYPE_UNKNOWN)
{
// these session vars require training mode no matter what card type
if ($this->conf->get("training") != 0 || $this->conf->get("CashierNo") == 9999)
return 0;
// special session vars for each card type
if ($type === PaycardLib::PAYCARD_TYPE_CREDIT && $this->conf->get('CCintegrate') != 1) {
return 0;
}
return 1;
}
}