Skip to content

Instantly share code, notes, and snippets.

@baamenabar
Created August 7, 2012 21:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baamenabar/3289706 to your computer and use it in GitHub Desktop.
Save baamenabar/3289706 to your computer and use it in GitHub Desktop.
Clase de pago de webpay
<?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='baamenabar@gmail.com';//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='info@empresa.cl';//Este es el mail de la persona que envía los avisos de venta.
protected $mailAministradores='contacto@empresa.cl, ventas@empresa.cl';//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&oacute;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&aacute; invocando la p&aacute;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