Integrando la pasarela de pagos Culqi con CodeIgniter

Saludos a todos, espero se encuentren muy bien. En los últimos meses he estado trabajando con un emprendimiento tecnológico en Perú en el área de formación en línea. Pronto podré compartir con ustedes los detalles del proyecto, ya que el lanzamiento a los medios será en los próximos días. Ésta interacción me ha permitido conocer la pasarela de pago Culqi y aprovecho la oportunidad para documentar como he venido integrando la pasarela de pagos Culqi con CodeIgniter.

Integrando la pasarela de pagos Culqi con CodeIgniter

Culqi es un servicio que proporciona facilidades tecnológicos para hacer y recibir pagos con tarjeta de crédito, débito y efectivo. Puede ser integrado tanto para smartphones o paginas web, y permite a cualquier negocio, grande o pequeño, recibir pagos con tarjeta y a cualquier usuario hacerlos de forma fácil y segura.

Pasarela de pagos Culqi con CodeIgniter

Si eres desarrollador de software, lo primero que te sugiero es revisar su documentación en línea, ahí podrás encontrar diferentes implementaciones, desde las librerías en diferentes lenguajes de programación PHP, Python, Java, entre otros. Si sigues estos pasos te vetas integrando la pasarela de pagos Culqi con CodeIgniter más rápido de los que piensas.

Integrando la pasarela de pagos Culqi con CodeIgniter
Culqi del lado del servidor

También encontrarás los plugins de Culqi para WooCommerce, PrestaShop y Magento entre otros. En esta sección está todo lo que necesitas para integrar Culqi en tu página web o en tu aplicación móvil.

Integrando la pasarela de pagos Culqi con CodeIgniter
Culqi para CMS

¿Qué es un API y para que sirve?

De seguro has escuchado mucho sobre el termino API en este artículo, aquí lo hemos usado de forma excesiva, creo que es conveniente definir su significado antes de continuar.

La Interfaz de Programación de Aplicaciones, conocida también por la sigla API, en inglés, Application Programming Interface,​ es un conjunto de subrutinas, funciones y procedimientos (o métodos, en la programación orientada a objetos) que ofrece cierta biblioteca para ser utilizado por otro software como una capa de abstracción independiente.

Wikipedia

Una API representa la capacidad de comunicación entre componentes de software. Se usan generalmente entre las capas inferiores y las superiores del software. Los desarrolladores de software se benefician de las ventajas del API haciendo uso de su funcionalidad de forma transparente, evitándose el trabajo de programar la lógica de negocio ellos mismos desde 0.

Integrando la pasarela de pagos Culqi con CodeIgniter

Por ejemplo con la implementación de las API en nuestro software, podemos hacer uso de los servicios de autenticación de Google o Facebook, sin que eso represente una incomodidad para el usuario final.

En el caso de la integración de la pasarela de pagos Culqi, toda la lógica de interconexión y verificación bancaria esta encapsulada en la Startup Culqi y nosotros hacemos uso de sus servicios obteniendo la confirmación de pagos bancarios.

Flujo de trabajo de Culqi Pasarela de Pago

Para iniciar la implementación debes estar registrado como comercio en Culqi, un proceso administrativo que luego te dará acceso al panel de control de Culqi (Integración / Producción). Ali deberás activar tus API Keys, las cuales serán necesarias para conectarte de forma segura con el API.

Integrando la pasarela de pagos Culqi con CodeIgniter

Ya con el API activa iniciamos el proceso de integración de Culqi con CodeIgniter, usaremos la forma mas sencilla que tiene Culqi, la cual es el botón Culqi Checkout Multipago, el cual ofrece la función de pago con tarjeta de crédito, débito y efectivo.

Integrando la pasarela de pagos Culqi con CodeIgniter

Partiendo de una instalación estándar de CodeIgniter, nos dirigimos a descargar la librería Culqi en PHP, para luego colocarla en nuestra carpeta third_party.

Lo primero será crear dentro de view/ la vista view.php en el cual colocaremos nuestro formulario con los campos monto a pagar y el botón de pagar, el cual deberá redirigir por submit al método multipago() del controlador Culqi.php.

Creamos dentro de la carpeta view/ el archivo multipago.php el cual contendrá el botón de pago de Culqi. Para poder tokenizar los datos de la tarjeta de forma segura, incluiremos el archivo js en multipago.php. Debes incluirlo antes del cierre de la etiqueta «body» o dentro de la etiqueta «head».

<!-- Incluyendo Culqi Checkout -->
<script src="https://checkout.culqi.com/js/v3"></script>

La vista multipago.php quedará de la siguiente manera

    <div class="modal fade" id="modal-pago" role="dialog">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
         
          <h4 class="modal-title">Confirmación del pago</h4>
        </div>
        <div class="modal-body">          
          
        
<div class="progress">
  <div id="loader" class="progress-bar progress-bar-striped active"  role="progressbar"
  aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width:100%">
  </div>
</div>
            <p align="center" id="pago_msg">

            </p>                
           
        </div>
         <div class="modal-footer">
              <button type="button" class="btn btn-default pull-right" onclick="cerrar()">Cerrar</button>
              
            </div>

      </div>
    </div>
  </div>  

  <!-- =============================================== -->

  <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper">
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <h1>
       Pago
        <!-- <small>Nueva</small>-->  
      </h1>
      <ol class="breadcrumb">
        <li><a href="<?=site_url('escritorio/index')?>" ><i class="fa fa-dashboard"></i> Inicio</a></li>
        <li class="active">Pago</li>
        
      </ol>
    </section>

    <!-- Main content -->
    <section class="content">     

      <div class="box box-primary" id="lista_usuarios">
          <div class="box-header with-border"> 
          <h3 class="box-title"> Confirmación del pago</h3>         
            <div class="box-tools pull-right">
                 <button type="button" class="btn btn-box-tool" onclick="atras()"><i class="fa fa-mail-reply"></i></button>            

              </div> 
        </div>
         <br>         
        
            <!-- /.box-header -->
            <div class="box-body">                
        
          <form action="#" id="form_matricula" method="POST" > 

               <div class="row">

                         <div class="col-md-2">
                        
                         </div>

                         <div class="col-md-8" align="center">                       
                
                        <h2 style="font-size:36px; margin-top:0px; font-family: isocpeur;"> Monto a pagar </h2> 

                         
                           <h3 style="font-size:50px; margin-top:0px; font-family: isocpeur;" ><?=($nu_monto/100)?> Soles</h3>
                           <h3 style="font-size:36px; margin-top:0px; font-family: isocpeur;"><?=($nu_monto/15000)?> Fases</h3>

                           <input hidden id="id_alumno_m" name="id_alumno_m" value="<?=$id_alumno_m?>">
                           <input hidden id="id_padre_m"  name="id_padre_m" value="<?=$id_padre_m?>">                          
                           <input hidden id="token_id"  name="token_id" >   
                           <input hidden id="order_culqi"  name="order_culqi" >   
                           <input hidden id="email_culqi"  name="email_culqi" >
                           <input hidden id="payment_code"  name="payment_code" >
                           <input hidden id="order_number"  name="order_number" >                           
                           
                            <input type="hidden" name="nu_monto" id="nu_monto" value="<?=$nu_monto?>" >
                       
                         </div>

                         <div class="col-md-2">

                         </div>
                    </div>               

            </div>
            <!-- /.box-body -->  

            <div class="box-footer">              
               <input type="submit" value"Pagar">
            </div> 

             </form>            
          </div>
    </div>  

</div>
<!-- ./wrapper -->

<!-- jQuery 3 -->
<script src="<?php echo base_url(); ?>assets/plugins/jquery/dist/jquery.min.js"></script>

<!-- Bootstrap 3.3.7 -->
<script src="<?php echo base_url(); ?>assets/bootstrap/dist/js/bootstrap.min.js"></script>


<!-- AdminLTE App -->
<script src="<?php echo base_url(); ?>assets/dist/js/adminlte.min.js"></script>

<!-- AdminLTE App -->
<script src="<?php echo base_url(); ?>assets/dist/js/app.min.js"></script>

<!-- Culqi App -->
<script src="https://checkout.culqi.com/js/v3"></script>

<script>
    // Configura tu llave pública
    Culqi.publicKey = 'pk_test_XXX';

 
 $('#form_matricula').submit(function(e) {

       // Configura tu Culqi Checkout
      Culqi.settings({
      title: 'Pagado desde Culqi',
      currency: 'PEN',
      description: 'Academia ',
      amount: <?=$nu_monto?>,
      order: '<?=$order->id?>'
    });

         Culqi.open();
         e.preventDefault();    

       return false;
  });
  

 function culqi() {
  if (Culqi.token) { // ¡Objeto Token creado exitosamente!
      
      var token = Culqi.token.id;
      //alert('Se ha creado un token:' + token);
      // Aqui enviar token Id a servidor para crear cargo...

      var token = Culqi.token.id;
      var email_culqi = Culqi.token.email; 
      $("#token_id").val(token);
      $("#email_culqi").val(email_culqi);
      
      Culqi.close();

      var data = $("#form_matricula").serialize();

      $("#loader").show();
      $("#pago_msg").html('Estamos validando el pago con la plataforma Culqi. Por favor no cierre esta ventana durante el proceso');
      $("#modal-pago").modal('toggle');      
        var url="<?php echo site_url('culqi/cargo')?>";

        $.post(url,data,function(result){
          
            var data = jQuery.parseJSON(result); 
            console.log(data);  

          if(data.object == 'charge'){ //usado para TDC y TDD

            $("#pago_msg").html(data.outcome.merchant_message);
            $( "#loader" ).removeClass( "progress-bar progress-bar-striped active" );
            $( "#loader" ).toggleClass( "progress-bar progress-bar-success" );
            
          }else{

             $("#pago_msg").html(data.merchant_message);
             $( "#loader" ).removeClass( "progress-bar progress-bar-striped active" );
             $( "#loader" ).toggleClass( "progress-bar progress-bar-danger" );

          }         

        });

  }
  else if (Culqi.order) { //Usado para Culqi Efectivo
      
      console.log(Culqi.order)

      //alert('Se ha elegido el metodo de pago en efectivo'+Culqi.order);

       /* Aqui enviar al servidor el order Id y asociarlo al detalle de tu venta.
          Además, tu venta en tu comercio debe quedar estado pendiente.
        */

        $("#loader").show();
        $("#pago_msg").html('Estamos validando el pago con la plataforma 
        Culqi. Por favor no cierre esta ventana durante el proceso');
        $("#modal-pago").modal('toggle');

        $("#payment_code").val(Culqi.order.payment_code);
        $("#order_number").val(Culqi.order.order_number);
        $("#order_culqi").val(Culqi.order.id);

        var data = $("#form_matricula").serialize();
        var url="<?php echo site_url('culqi/efectivo')?>";

        $.post(url,data,function(res){
            var data = jQuery.parseJSON(res); 
            console.log(data);

           
            $("#pago_msg").html("Pago realizado satisfactoramente con código de pago " + Culqi.order.payment_code);
            $( "#loader" ).removeClass( "progress-bar progress-bar-striped active" );
            $( "#loader" ).toggleClass( "progress-bar progress-bar-success" );

        });

  }
  else { // ¡Hubo algún problema!
      // Mostramos JSON de objeto error en consola
      console.log(Culqi.error);
      alert(Culqi.error.user_message);
  }
};

 function atras(){
    window.location.href = '<?=site_url().'/culqi/view?id='.$id_alumno_m ?>';

 }

   function cerrar(){

  window.location.href = '<?=site_url().'/culqi/view?id='.$id_alumno_m ?>';

 }

</script>

Creamos el controlador llamado Culqi.php y el método multipago() , cargo() y efectivo() para manejar los pagos en TDC, efectivo y cargar el token de seguridad.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Culqi extends CI_Controller {

	function __construct(){
		parent::__construct();     
               $this->load->library('session');              
	  }

   
  public function multipago(){

            include_once APPPATH.'third_party/culqi/Requests/library/Requests.php';
            Requests::register_autoloader();
            include_once APPPATH.'third_party/culqi/lib/culqi.php';

            $nu_monto   =  trim($this->input->post("nu_monto")); 
      
            $data["nu_monto"]  = $this->input->post("nu_monto");
            $data["id_alumno_m"]  = $this->input->post("id_alumno_m");
            $data["id_padre_m"]  = $this->input->post("id_padre_m");

            // Configurar tu API Key y autenticación
            $SECRET_KEY = "sk_test_XXX";
            $culqi = new Culqi\Culqi(array('api_key' => $SECRET_KEY));       

        $order = $culqi->Orders->create(      
      array(
        "amount" =>  $nu_monto,
        "currency_code" => "PEN",
        "description" => "Culqi Pago Efectivo",        
        "order_number" => rand(),  
        "client_details" => array( 
            "first_name"=> 'Juan' , 
            "last_name" => 'Cisneros',
            "email" => 'jotavek@gmail.com', 
            "phone_number" => '123457678'
         ),
         "confirm" => false,       
        "expiration_date" => time() + 24*60*60   // Orden con un dia de validez
      )
            );     
            $data["order"] = $order;

            $this->load->view('templates/header');
            $this->load->view('templates/menu',$menu);
            $this->load->view('culqi/multipago', $data);
            $this->load->view('templates/footer');

    }  


public function view() { 
            
            $this->load->view('templates/header');
            $this->load->view('templates/menu');
            $this->load->view('culqi/view');
            $this->load->view('templates/footer');            
    }
	
public function cargo(){

         include_once APPPATH.'third_party/culqi/Requests/library/Requests.php';
         Requests::register_autoloader();
         include_once APPPATH.'third_party/culqi/lib/culqi.php';


        $token_id   =  trim($this->input->post("token_id")); 
        $email_culqi   =  trim($this->input->post("email_culqi")); 
        $nu_monto   =  trim($this->input->post("nu_monto"));       


        // Configurar tu API Key y autenticación
        $SECRET_KEY = "sk_test_XXX";
        $culqi = new Culqi\Culqi(array('api_key' => $SECRET_KEY));

        $charge = $culqi->Charges->create(
         array(
             "amount" => $nu_monto,
             "currency_code" => "PEN",
             "email" => $email_culqi,
             "description" => 'Academia ',
             "source_id" => $token_id
           )
        );      

        if($charge -> object == 'charge'){

            $datos['id_alumno']            =  trim($this->input->post("id_alumno_m"));       
            $datos['id_padre']             =  trim($this->input->post("id_padre_m"));      
           

            $datos['fe_registro'] = $datos['fe_pago'] = date('Y-m-d H:i:s');       
            $datos['tx_operacion']=  $charge->outcome->merchant_message; 
            $datos['nu_monto']=  $nu_monto/100;
            $datos['nu_fases']=  $nu_monto/15000;
            $datos['tx_orden_culqi']=  $token_id;
            $datos['tx_tipo']=  'Culqi Pago Tarjeta' ;
            $datos['tx_estatus']=  'Pagado' ;           
                
            
            $this->load->model('Matriculacion_model');      
            $filas_afectadas = $this->Matriculacion_model->guardar($datos) ;

            $usuario = $this->session->userdata('usuario'); 
            $this->load->library('Libnotificaciones');
            $param_padre['nombre'] = $usuario->name;
            $param_padre['correo'] =  $email_culqi;  

            $param_padre['fe_pago'] =  $datos['fe_pago'];  
            $param_padre['tx_operacion'] = $charge->outcome->merchant_message; 
            $param_padre['nu_monto'] = $nu_monto/100;

            $this->libnotificaciones->envio_pago_padre($param_padre); 

        }else{

            $datos['id_alumno']            =  trim($this->input->post("id_alumno_m"));       
            $datos['id_padre']             =  trim($this->input->post("id_padre_m"));      
           

            $datos['fe_registro'] = $datos['fe_pago'] = date('Y-m-d H:i:s');       
            $datos['tx_operacion']=  $charge->merchant_message; 
            $datos['nu_monto']=  0;
            $datos['nu_fases']=  0;
            $datos['tx_orden_culqi']=  0;
            $datos['tx_tipo']=  'Culqi Pago Tarjeta' ;
            $datos['tx_estatus']=  'Fallido' ;
                
            
            $this->load->model('Matriculacion_model');      
            $filas_afectadas = $this->Matriculacion_model->guardar($datos) ;

            $usuario = $this->session->userdata('usuario'); 
            $this->load->library('Libnotificaciones');
            $param_padre['nombre'] = $usuario->name;
            $param_padre['correo'] =  $email_culqi;  

            $param_padre['fe_pago'] =  $datos['fe_pago'];  
            $param_padre['tx_operacion'] = $charge->merchant_message; 
            $param_padre['nu_monto'] =  0;

             $this->libnotificaciones->envio_pago_padre($param_padre); 
        }     
      // Respuesta
        echo json_encode($charge);
    }

    public function webhooks(){
        
          /* Recuperar el cuerpo de la solicitud y parsearlo como JSON */
  $input = json_decode(file_get_contents('php://input'), true);
          // Recuperar el cuerpo de la solicitud y analizarlo como JSON
  
  $input_json = file_get_contents("php://input");
  //$event_json = json_decode($input);
  $array = array();
   

 
  // Escribir el Webhook en mi archivo "log/log-webhooks.json" de ejemplo
  $myfile = fopen("log-webhooks.text", "w") or die("Imposible abrir el archivo.");
  fwrite($myfile, $input_json);


  /* Reconocer tipo de evento recibido */  
  if($input['type'] == 'order.status.changed') {
    
    // Obtener objeto Order
    $objectOrder = json_decode($input['data'], true);    
    
    // Parametros   
    $state = trim($objectOrder['state']);         
    $id = trim($objectOrder['id']); 
    $payment_code = trim($objectOrder['payment_code']); 
    $order_number = trim($objectOrder['order_number']);
    $amount = trim($objectOrder['amount']);
       
         
    /* Acciones según nuevo estado */ 
    
    // Orden pagada
    if($state == 'paid') { 
      // Aquí cambiar estado de la orden en tu sistema ... 
      $array = array(
        "response" => "Webhook de Culqi $state ",
        'id' =>  $id,
        'payment_code' => $payment_code,
        'order_number' =>$order_number,
        'amount' => $amount
        );

      $this->load->model('Matriculacion_model');                   
      $datos['tx_estatus'] = 'Pagado';
      $this->Matriculacion_model->editar_x_order(intval($order_number), $datos);

      $matricula = $this->Matriculacion_model->buscar_x_order(intval($order_number));
      
      $this->load->library('Libnotificaciones');
            $param_padre['nombre'] = $matricula->name;
            $param_padre['correo'] =  $matricula->email;  

            $param_padre['fe_pago'] =  date('d-m-Y');  
            $param_padre['tx_operacion'] = "Su pago con Culqi Efectivo N° $payment_code ha cambiado a estado Pagado"; 
            $param_padre['nu_monto'] =  $amount/100;

      $this->libnotificaciones->envio_pago_padre($param_padre); 

    }
    // Orden expirada
    if($state == 'expired') {     
     // Aquí cambiar estado de la orden en tu sistema ... 
         $array = array(
        "response" => "Webhook de Culqi $state ",
        'id' =>  $id,
        'payment_code' => $payment_code,
        'order_number' =>$order_number,
        'amount' => $amount
        );

        $this->load->model('Matriculacion_model');                   
        $datos['tx_estatus'] = 'Expirado';
        $this->Matriculacion_model->editar_x_order(intval($order_number), $datos);
       $this->load->library('Libnotificaciones');
            $param_padre['nombre'] = $matricula->name;
            $param_padre['correo'] =  $matricula->email;
            $param_padre['fe_pago'] =  date('d-m-Y');  
            $param_padre['tx_operacion'] = "Su pago con Culqi Efectivo N° $payment_code ha cambiado a estado Expirado"; 
            $param_padre['nu_monto'] =  $amount/100;
      $this->libnotificaciones->envio_pago_padre($param_padre); 


    } 
    
    // Orden eliminada
    if($state == 'deleted') {     
     // Aquì cambiar estado de la orden en tu sistema ... 
        $array = array(
        "response" => "Webhook de Culqi $state ",
        'id' =>  $id,
        'payment_code' => $payment_code,
        'order_number' =>$order_number,
        'amount' => $amount
        );

        $this->load->model('Matriculacion_model');                   
        $datos['tx_estatus'] = 'Eliminado';
        $this->Matriculacion_model->editar_x_order(intval($order_number), $datos);

         $this->load->library('Libnotificaciones');
            $param_padre['nombre'] = $matricula->name;
            $param_padre['correo'] =  $matricula->email;  

            $param_padre['fe_pago'] =  date('d-m-Y');  
            $param_padre['tx_operacion'] = "Su pago con Culqi Efectivo N° $payment_code ha cambiado a estado Expirado"; 
            $param_padre['nu_monto'] =  $amount/100;

      $this->libnotificaciones->envio_pago_padre($param_padre);

    } 

  } 

  //Respuesta a Culqi
  http_response_code(200);  
  echo json_encode($array);

    }



    public function efectivo(){         

      
         $nu_monto                      =  trim($this->input->post("nu_monto")); 
         $datos['id_alumno']            =  trim($this->input->post("id_alumno_m"));       
         $datos['id_padre']             =  trim($this->input->post("id_padre_m"));    
         $payment_code                  =  trim($this->input->post("payment_code"));    
         $order_culqi                  =  trim($this->input->post("order_culqi"));    
         $order_number                  =  trim($this->input->post("order_number"));    
           
           

            $datos['fe_registro'] = $datos['fe_pago'] = date('Y-m-d H:i:s');       
            $datos['tx_operacion']=  "Numero de operación Pago Efectivo $payment_code "; 
            $datos['nu_monto']=  $nu_monto/100;
            $datos['nu_fases']=  $nu_monto/15000;
            $datos['tx_orden_culqi']=  $order_culqi ;
            $datos['tx_tipo']=  'Culqi Pago Efectivo' ;
            $datos['tx_estatus']=  'Pendiente' ;
            $datos['nu_codigo_pago']=  $payment_code ;
            $datos['nu_order_number']=  $order_number ;          
                
            
            $this->load->model('Matriculacion_model');      
            $filas_afectadas = $this->Matriculacion_model->guardar($datos) ;

            $usuario = $this->session->userdata('usuario'); 
            $this->load->library('Libnotificaciones');
            $param_padre['nombre'] = $usuario->name;
            $param_padre['correo'] =  'jotavek@gmail.com';  

            $param_padre['fe_pago'] =  $datos['fe_pago'];  
            $param_padre['tx_operacion'] = "Numero de operación Pago Efectivo $payment_code "; 
            $param_padre['nu_monto'] = $nu_monto/100;

            $this->libnotificaciones->envio_pago_padre($param_padre); 

    
      // Respuesta
        echo json_encode($payment_code);
    }    
    
}

De esta manera ya podrás empezar a usar Culqi Multipago, podrás verificar las transacciones realizadas en el panel de control de Culqi.

Integrando la pasarela de pagos Culqi con CodeIgniter

Usando Webhooks de Culqi con CodeIgniter

Luego de creada nuestras ordenes de Culqi pago efectivo o cargos a las tarjetas de crédito, no interesa mantener actualizado los cambios de estado de las ordenes y pedidos dentro de la plataforma Culqi. Por ejemplo un pago efectivo se crea de forma predeterminada en estado «Pendiente» y tiene una fecha de vencimiento de 1 día, cuando es pagada por el usuario en un banco o comercio, Culqi debe notificar a nuestros sistemas contables ese cambio de estado. Para eso usamos los WebHooks.

Los Webhooks son una manera simple de comunicarse entre diferentes servicios web. Te explicare como funcionan los Webhooks de manera general y también con casos de uso comunes en tu integración de Culqi.

En general, un webhook es un endpoint donde puedes ejecutar una acción o serie de acciones cuando es llamado (una petición llega). Por ejemplo, si tienes integrado a Culqi en tu sitio web y se ejecuta una acción como Crear Cargo, esto haría que se realice una petición al endpoint del Webhook. Con ello, podemos reaccionar a ese evento realizando algún cambio en nuestro sistema o simplemente notificando al cliente.

Si tienes un comercio creado en Culqi, puedes configurar los webhooks desde tu Panel Culqi. Entrando a Eventos > Webhooks. Añades los webhooks que necesitarás, por ejemplo para el cambio de estados de las ordenes de pago en efectivo «order.status.changed»

Dentro del controlador Culqi.php encontraras el método webhooks(), el cual es usado para capturar el llamado que desde la plataforma de Culqi se hace hacia nuestro sistema y manejar los mensajes internamente.

Espero este breve ejercicio pueda ayudarte a tus labores de desarrollo e ir integrando la pasarela de pagos Culqi con CodeIgniter en tus proyectos.

Cualquier duda por favor escríbeme un comentario.

Deja un comentario