Created
August 7, 2012 21:53
-
-
Save baamenabar/3289706 to your computer and use it in GitHub Desktop.
Clase de pago de webpay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Class PagoWebPay | |
Versión: 0.1 | |
Autor: Agustín Amenabar, @baamenabar (es) @ImINaBAR (en) | |
Licencia: MIT | |
parámetros: | |
$rdb: instancia de un objeto PDO ya inicializado, en su defecto, la clase se conectará sola, si es que se entregan los datos de conexión en el parámetro $configuracionClase. | |
$carpetaCGI : Dirección de carpeta CGI de transbank. Es importante dar la dirección correcta en cada instanciación, a veces uno tiene scripts en diferentes direcciones relativas con respecto a la carpeta CGI. | |
$oc [opcional]: Un string de máximo 26 caracteres. La clase buscará su existencia en la base de datos y cargará la información guardada. Si no lo encuentra o no se entrega un número de OC y no viene dentro de GET o POST, se generará inmediatamente un nuevo número OC y se creará un nuevo registro de transacción. | |
OJO: | |
- Esta clase NECESITA la biblioteca PDO funcionando en el servidor (no es mucho pedir) | |
- Esta clase se ve un poco rara porque es una serie de clases combinadas, normalmente manejo estas cosas heredadas, pero así es más simple para copy - paste. | |
*/ | |
class PagoWebPay{ | |
protected $db; | |
protected $id; | |
protected $oc; | |
protected $totalAPagar; | |
protected $pagado; | |
protected $_errores=array(); | |
protected $acciones=array(); | |
/* Configuraciones para envío de correos de aviso*/ | |
protected $mailWebmaster='[email protected]';//aquí llegan las notificaciones de errores de sistema, para que no falle la tienda sin que nos enteremos | |
protected $nombreMarca='Médula Diseño';//Dice Médula Diseño, cambiarlo al nombre de la tienda que se está configurando. | |
protected $mailAministrador='[email protected]';//Este es el mail de la persona que envía los avisos de venta. | |
protected $mailAministradores='[email protected], [email protected]';//Este es el mail de la(s) persona que recibe(n) los avisos de venta. | |
/* --- fin datos de correo */ | |
protected $_carpetaCGI; | |
protected $_configuracionTBK=array(); | |
protected $_datos=array(); | |
protected $listaRespuestasTBK=array('0'=>'Transacción aprobada.', | |
'-1'=>'Rechazo de transacción.', | |
'-2'=>'Transacción debe reintentarse.', | |
'-3'=>'Error en transacción.', | |
'-4'=>'Rechazo de transacción.', | |
'-5'=>'Rechazo por error de tasa.', | |
'-6'=>'Excede cupo máximo mensual.', | |
'-7'=>'Excede límite diario por transacción.', | |
'-8'=>'Rubro no autorizado.');//para el kit de integración V6.0 | |
const noventa = 7776000; | |
const treinta = 2592000; | |
public function __construct(PDO $rdb,$carpetaCGI="/cgi-bin",$oc=false){ | |
date_default_timezone_set ('America/Santiago'); | |
$this->db =$rdb; | |
$this->_carpetaCGI=$carpetaCGI; | |
//$this->cargaConfiguraciones(); | |
$this->oc=$oc; | |
if(!$this->iniciaRegistro())return; | |
if($this->activaAcciones())return true;//esta la uso para definir qué secuencia quiero que haga por sí misma usando GET | |
} | |
public function setTotalAPagar($pesos,$conDecimalesPegados=false){ | |
if(!is_numeric($pesos))return false; | |
if($conDecimalesPegados)$pesos=$pesos/100; | |
$aGuardar=number_format($pesos,0,'',''); | |
$this->totalAPagar=$aGuardar; | |
$this->db->query('UPDATE reg_transacciones SET total_carro = "'.$aGuardar.'" WHERE idr = "'.$this->id.'" LIMIT 1'); | |
} | |
public function getTotalAPagar($conDecimalesAdicionales=true){ | |
$extra='00'; | |
if(!$conDecimalesAdicionales)$extra=''; | |
return $this->totalAPagar.$extra; | |
} | |
public function setPagado(){ | |
$tsPagado=date('Y-n-d H:i:s'); | |
$this->db->query('UPDATE reg_transacciones SET pagado = "'.$tsPagado.'", estampa = '.time().' WHERE idr = "'.$this->id.'" LIMIT 1'); | |
$this->pagado=$tsPagado; | |
} | |
public function print_accionFormPago($devuelve=false){ | |
$welta=$this->_carpetaCGI.'/tbk_bp_pago.cgi'; | |
if(!is_file($welta))$this->desastre('">ERROR de configuración en print_accionFormPago, no se encuentra tbk_bp_pago.cgi'); | |
if($devuelve)$welta; | |
echo $welta; | |
} | |
public function getID(){return $this->id;} | |
public function getOC(){return $this->oc;} | |
public function getIDPago(){return $this->pagado;} | |
public function setOC($loc=''){//guarda OC (orden de compra) o genera una nueav y guarda el dato en el registro de transacciones | |
if(!$loc)$loc=date('YmdHis').'_'.$this->id; | |
$respuesta=$this->db->prepare('UPDATE reg_transacciones SET oc_carro = :loc WHERE idr = "'.$this->id.'" LIMIT 1'); | |
$respuesta->execute(array(':loc'=>$loc)); | |
if($respuesta->errorCode()==='00000'){ | |
$this->oc = $loc; | |
} | |
return $loc; | |
} | |
public function getConfigTBK($nombreParametro){ | |
if(!isset($this->_configuracionTBK[$nombreParametro]))return false; | |
return $this->_configuracionTBK[$nombreParametro]; | |
} | |
public function getDato($nombreParametro){ | |
if(!isset($this->_datos[$nombreParametro]))return false; | |
return $this->_datos[$nombreParametro]; | |
} | |
public function getError($nombre=false){ | |
if($nombre===false){ | |
return (bool) count($this->_errores); | |
}else{ | |
if(!isset($this->_errores[$nombre]))return false; | |
return (bool) $this->_errores[$nombre]; | |
} | |
return false; | |
} | |
public function marcaComoCobradaPorTBK(){ | |
/*$mde='inicio de la funcion marcaComoCobradaPorTBK | |
';*/ | |
if($this->getError())return false;//si hay algún error no se paga. | |
/*$mde.='no hay errores, prosigamos | |
';*/ | |
$microsplit=explode(' ',microtime()); | |
$tsPagado='pp'.date('Y-n-d H:i:s').':'.$microsplit[0]; | |
$guarda = $this->db->prepare('UPDATE reg_transacciones SET pagado = :pagado , estampa = :estampa WHERE idr = :idr LIMIT 1'); | |
/*$mde.='a punto de ejecutar con datos tsPagado:'.$tsPagado.' e idr:'.$this->id.' | |
';*/ | |
$guarda->execute(array(':pagado'=>$tsPagado, | |
':estampa'=>time(), | |
':idr'=>$this->id)); | |
if($guarda->errorCode() !== '00000')$this->avisaWebmaster('Error al actualizar el registro de pagado: '.print_r($guarda->errorInfo(),true)); | |
/*$mde.='ejecutado sin errores fatales | |
';*/ | |
$this->pagado=$tsPagado; | |
//$this->avisaWebmaster($mde); | |
} | |
public function procesaNumerodeCuotas($nume=NULL){ | |
if($nume===NULL)$nume=$this->_datos['TBK_NUMERO_CUOTAS']; | |
if(!is_numeric($nume))return '00'; | |
if(strlen($nume.'')<2)return '0'.$nume; | |
return $nume; | |
} | |
public function procesaTipodeCuotas($tipoc=NULL){ | |
if($tipoc===NULL)$tipoc=$this->_datos['TBK_TIPO_PAGO']; | |
if($tipoc=='VN')return 'Sin Cuotas'; | |
if($tipoc=='VC')return 'en Cuotas Normales'; | |
if($tipoc=='SI')return 'en 3 (tres) Cuotas Sin Interés'; | |
if($tipoc=='S2')return 'en 2 (dos) Cuotas Sin Interés'; | |
if($tipoc=='CI')return 'en Cuotas Comercio'; | |
if($tipoc=='VD')return 'Redcompra (Tarjeta débito)'; | |
} | |
public function enviaComprobantePorMail($mensaje,$para=false){ | |
$to=$this->mailWebmaster; | |
if($para)$to=$para; | |
$subject = 'Combrobante de venta '.$this->nombreMarca; | |
$additionalHeaders = "From: Ventas $this->nombreMarca <".$this->mailAministrador.">\n"; | |
$additionalHeaders .= 'MIME-Version: 1.0' . "\n"; | |
$additionalHeaders .= 'Content-type: text/html; charset=utf-8' . "\n"; | |
@mail($to, $subject,$mensaje,$additionalHeaders); | |
/*------- ANHORA AL ADMINISTRADOR -----*/ | |
$to=$this->mailAministradores; | |
$subject = 'Notificacion venta '.$this->nombreMarca; | |
$additionalHeaders = "From: Sistema $this->nombreMarca <".$this->mailWebmaster.">\n"; | |
$additionalHeaders .= 'MIME-Version: 1.0' . "\n"; | |
$additionalHeaders .= 'Content-type: text/html; charset=utf-8' . "\n"; | |
@mail($to, $subject,$mensaje,$additionalHeaders); | |
} | |
public function getErrorTBK(){ | |
//TBK_RESPUESTA!=0 | |
return $this->listaRespuestasTBK[$this->_datos['TBK_RESPUESTA']]; | |
} | |
protected function cargaConfiguraciones(){ | |
return; | |
if(!$this->_carpetaCGI || !is_dir($this->_carpetaCGI) || $this->_carpetaCGI=='.' || $this->_carpetaCGI=='..' || !is_file($this->_carpetaCGI.'/datos/tbk_config.dat')){ | |
$this->desastre('Problema de configuración en clase PagoWebPay, no se encuentra la carpeta con los cgi o su archivo de configuración'); | |
} | |
$gestor = @fopen($this->_carpetaCGI.'/tbk_config.dat', "rb"); | |
$this->_configuracionTBK=array(); | |
if ($gestor) { | |
while (($buffer = fgets($gestor, 4096)) !== false) { | |
$partes=explode('=',$buffer); | |
$this->_configuracionTBK[trim($partes[0])]=trim($partes[1]); | |
} | |
} | |
} | |
protected function iniciaRegistro(){ | |
if(!$this->oc){//si no se entregó el parámetro $oc | |
if($this->revisaPost()){//si los datos POST están OK | |
if(!$this->getError('OC')){//si no hay errores con la OC | |
if(!isset($_POST['TBK_RESPUESTA']))return false;//estamos en la página de fallo o exito, no debemos procesar el cierre | |
if($this->getError())return false; | |
if($this->procesaCierre()){//hacemos la secuencia de revisiones de la página de cierre | |
echo('ACEPTADO'); | |
return true; | |
} | |
return false; | |
}else{ | |
return false; | |
} | |
}else{ | |
//esto significa que no han llegado datos post o algo falló | |
if($this->getError())return false;//si algo falló cancelamos el procedimiento | |
} | |
$this->creaNuevoRegistro(); | |
$this->setOC(); | |
if(!$this->oc)$this->desastre('No se ha podido generar una nuevo OC, hay un conflicto.'); | |
}else{//ahora buscaremos si existe en la base de datos esta OC | |
$consulta=$this->db->prepare('SELECT * FROM reg_transacciones WHERE oc_carro = :oc ORDER BY idr DESC LIMIT 1'); | |
$consulta->execute(array(':oc'=>$this->oc)); | |
if(!$consulta->rowCount()){// no se ha encontrado la OC en la base de datos | |
$this->creaNuevoRegistro(); | |
$this->setOC($this->oc);//guarda nueva OC en la base de datos | |
}else{ | |
$fila=$consulta->fetch(PDO::FETCH_ASSOC); | |
foreach($fila as $llave=>$valor)$this->_datos[$llave]=$valor; | |
$this->id=$fila['idr']; | |
$this->totalAPagar=$fila['total_carro']; | |
$this->pagado=$fila['pagado']; | |
} | |
// | |
} | |
} | |
protected function revisaPost(){ | |
if(isset($_POST['TBK_ORDEN_COMPRA']) && $_POST['TBK_ORDEN_COMPRA']){ | |
$consulta=$this->db->prepare('SELECT * FROM reg_transacciones WHERE oc_carro = :oc ORDER BY idr DESC LIMIT 1'); | |
$consulta->execute(array(':oc'=>$_POST['TBK_ORDEN_COMPRA'])); | |
if(!$consulta->rowCount()){// no se ha encontrado la OC en la base de datos | |
$this->_errores['OC']=true; | |
if(!isset($_POST['TBK_RESPUESTA'])){//ESTAMOS EN LA PÁGINA DE EXITO | |
$this->desastre('Se está invocando la página de éxito con una OC inexistente:'.$_POST['TBK_ORDEN_COMPRA']); | |
return; | |
} | |
$this->avisaWebmaster('Página de Cierre está siendo llamada con POST TBK_ORDEN_COMPRA:'.$_POST['TBK_ORDEN_COMPRA'].'. Pero no se encuentra en la base de datos.'); | |
echo('RECHAZADO'); | |
return true; | |
} | |
$fila=$consulta->fetch(PDO::FETCH_ASSOC); | |
$this->id=$fila['idr']; | |
$this->totalAPagar=$fila['total_carro']; | |
$this->pagado=$fila['pagado']; | |
$this->oc=$_POST['TBK_ORDEN_COMPRA']; | |
//$this->avisaWebmaster('El idr encontrado es: '.$this->id.' para el oc:'.$_POST['TBK_ORDEN_COMPRA']); | |
if(isset($_POST['TBK_RESPUESTA'])){//ESTAMOS EN LA PÁGINA DE CIERRE | |
if(!isset($_POST['TBK_MONTO']) || $_POST['TBK_MONTO']<100){ | |
echo "RECHAZADO"; | |
$this->_errores['minimo']=true; | |
return true; | |
} | |
$this->guardaPost(); | |
}else{//ESTAMOS EN LA PÁGINA DE EXITO O FALLA// así que cargamos los datos como variables. | |
foreach($fila as $llave=>$valor)$this->_datos[$llave]=$valor; | |
foreach($_POST as $llave=>$valor)$this->_datos[$llave]=$valor; | |
$this->confirmaExito(); | |
return true; | |
} | |
return true; | |
} | |
return false; | |
} | |
protected function procesaCierre(){ | |
$todoOK=true; | |
/* Aquí preparamos el check MAC */ | |
$pathDeArchivoParaRevisarCheckMac=$this->_carpetaCGI."/log/cm".$this->oc.'ts'.implode('_',explode(' ',microtime(true))).".txt"; | |
$juntas=array(); | |
foreach($_POST as $llave=>$valor)$juntas[]=$llave.'='.$valor; | |
$fp = fopen($pathDeArchivoParaRevisarCheckMac,"wb"); | |
fwrite($fp, implode('&',$juntas)); | |
fclose($fp); | |
exec($this->_carpetaCGI.'/tbk_check_mac.cgi '.$pathDeArchivoParaRevisarCheckMac, $resultado); | |
if($resultado[0]!='CORRECTO'){ | |
$this->avisaWebmaster('La comprobación de CHECK MAC ha fallado para transacción id:'.$this->id); | |
echo('RECHAZADO'); | |
return false; | |
} | |
if($_POST['TBK_RESPUESTA']!='0'){//algo falló con la tarjeta del cliente, revisaremos ese problema en la página de fallo | |
$this->_errores['tarjeta']=$_POST['TBK_RESPUESTA']; | |
echo('ACEPTADO'); | |
return false; | |
} | |
if($this->pagado!='0'){// si ya está pagada la transacción, no volver a pagarla. | |
$this->avisaWebmaster('Se está tratando de pagar una segunda vez la transacción idr:'.$this->id); | |
echo('RECHAZADO'); | |
return false; | |
} | |
if($_POST['TBK_MONTO']!=$this->totalAPagar.'00'){//si el monto enviado por TBK no cuadra | |
$this->avisaWebmaster('Se está tratando de pagar un monto diferente al guardado.<br> | |
TBK_MONTO: '.$_POST['TBK_MONTO'].'<br> | |
totalAPagar: '.$this->totalAPagar.'00<br> | |
en la transacción idr:'.$this->id); | |
echo('RECHAZADO'); | |
return false; | |
} | |
return true; | |
} | |
protected function revisaGet(){ | |
return false; | |
} | |
protected function creaNuevoRegistro(){ | |
$inserta=$this->db->prepare('INSERT INTO reg_transacciones (estampa) VALUES ('.time().')'); | |
$inserta->execute(); | |
$this->id=$this->db->lastInsertId(); | |
} | |
protected function confirmaExito(){ | |
if(substr($this->pagado,0,2)=='pp'){ | |
$this->setPagado(); | |
}else if(!$this->pagado){ | |
if($this->_datos['TBK_RESPUESTA']!='0'){//estamos en la página de falla | |
} | |
return false; | |
}else{ | |
//Alguien debe haber apretado F5 en la página de éxito.//$this->avisaWebmaster('Tratando de pagar una transaccion por segunda vez'); | |
return false; | |
} | |
} | |
protected function guardaPost(){ | |
foreach($_POST as $llave=>$valor)$this->_datos[$llave]=$valor; | |
if(!isset($this->_datos['TBK_VCI']))$this->_datos['TBK_VCI']=''; | |
if(!isset($this->_datos['TBK_TASA_INTERES_MAX']))$this->_datos['TBK_TASA_INTERES_MAX']=''; | |
$tampa=time(); | |
$sql='UPDATE reg_transacciones SET | |
TBK_ORDEN_COMPRA = :TBK_ORDEN_COMPRA, | |
TBK_TIPO_TRANSACCION = :TBK_TIPO_TRANSACCION, | |
TBK_RESPUESTA = :TBK_RESPUESTA, | |
TBK_MONTO = :TBK_MONTO, | |
TBK_CODIGO_AUTORIZACION = :TBK_CODIGO_AUTORIZACION, | |
TBK_FINAL_NUMERO_TARJETA = :TBK_FINAL_NUMERO_TARJETA, | |
TBK_FECHA_CONTABLE = :TBK_FECHA_CONTABLE, | |
TBK_FECHA_TRANSACCION = :TBK_FECHA_TRANSACCION, | |
TBK_HORA_TRANSACCION = :TBK_HORA_TRANSACCION, | |
TBK_ID_SESION = :TBK_ID_SESION, | |
TBK_ID_TRANSACCION = :TBK_ID_TRANSACCION, | |
TBK_TIPO_PAGO = :TBK_TIPO_PAGO, | |
TBK_NUMERO_CUOTAS = :TBK_NUMERO_CUOTAS, | |
TBK_TASA_INTERES_MAX = :TBK_TASA_INTERES_MAX, | |
TBK_VCI = :TBK_VCI, | |
TBK_MAC = :TBK_MAC, | |
estampa = :estampa | |
WHERE idr = '.$this->id.' LIMIT 1'; | |
$actualiza=$this->db->prepare($sql); | |
$actualiza->execute(array( | |
':TBK_ORDEN_COMPRA'=>$this->_datos['TBK_ORDEN_COMPRA'], | |
':TBK_TIPO_TRANSACCION'=>$this->_datos['TBK_TIPO_TRANSACCION'], | |
':TBK_RESPUESTA'=>$this->_datos['TBK_RESPUESTA'], | |
':TBK_MONTO'=>$this->_datos['TBK_MONTO'], | |
':TBK_CODIGO_AUTORIZACION'=>$this->_datos['TBK_CODIGO_AUTORIZACION'], | |
':TBK_FINAL_NUMERO_TARJETA'=>$this->_datos['TBK_FINAL_NUMERO_TARJETA'], | |
':TBK_FECHA_CONTABLE'=>$this->_datos['TBK_FECHA_CONTABLE'], | |
':TBK_FECHA_TRANSACCION'=>$this->_datos['TBK_FECHA_TRANSACCION'], | |
':TBK_HORA_TRANSACCION'=>$this->_datos['TBK_HORA_TRANSACCION'], | |
':TBK_ID_SESION'=>$this->_datos['TBK_ID_SESION'], | |
':TBK_ID_TRANSACCION'=>$this->_datos['TBK_ID_TRANSACCION'], | |
':TBK_TIPO_PAGO'=>$this->_datos['TBK_TIPO_PAGO'], | |
':TBK_NUMERO_CUOTAS'=>$this->_datos['TBK_NUMERO_CUOTAS'], | |
':TBK_TASA_INTERES_MAX'=>$this->_datos['TBK_TASA_INTERES_MAX'], | |
':TBK_VCI'=>$this->_datos['TBK_VCI'], | |
':TBK_MAC'=>$this->_datos['TBK_MAC'], | |
':estampa'=>$tampa | |
)); | |
if($actualiza->errorCode() !== '00000')$this->avisaWebmaster('Error al actualizar el registro: | |
'.print_r($actualiza->errorInfo(),true)); | |
} | |
protected function activaAcciones(){ | |
$algunaActivada=false; | |
if(isset($_GET['a'])&& $_GET['a'] && isset($this->acciones[$_GET['a']])){ | |
$this->{$this->acciones[$_GET['a']]}(); | |
$algunaActivada=true;; | |
} | |
return $algunaActivada; | |
} | |
private function desastre($mensaje){ | |
$this->avisaWebmaster($mensaje); | |
echo $mensaje; | |
exit(); | |
return; | |
} | |
public function avisaWebmaster($message=''){//acepto sugerencias para esta función. | |
$message.="\r\n\r\nen la fecha:".date('Y-n-d H:i:s'); | |
$message.="\r\n\r\nen el archivo:".$_SERVER['PHP_SELF']."\r\nllamdo en:".$_SERVER['REQUEST_URI']; | |
$to=$this->mailWebmaster; | |
$subject = 'Error en sitio '.$this->nombreMarca; | |
$additionalHeaders = "From: Soporte ".$this->nombreMarca." <".$this->mailAministrador.">\n"; | |
$additionalHeaders .= 'MIME-Version: 1.0' . "\n"; | |
$additionalHeaders .= 'Content-type: text/plain; charset=utf-8' . "\n"; | |
@mail($to, $subject,$message,$additionalHeaders); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment