Cupones de descuento en PHP usando PDO
Ya hemos hablado en este blog en un artículo anterior, sobre como integrar Paypal a un Sistema de Pedidos de Pizza usando PHP.
En este tutorial vamos a ver, ¿cómo podemos añadir la característica de códigos promocionales, usando la pasarela de pagos PayPal.
Lo que haremos:
Paso 1: Creación de la base de datos. Abrir phpmyadmin, crear una nueva base de datos y ejecutar la siguiente consulta SQL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
-- phpMyAdmin SQL Dump -- version 4.4.14 -- http://www.phpmyadmin.net -- -- Servidor: 127.0.0.1 -- Tiempo de generación: 06-09-2016 a las 20:27:15 -- Versión del servidor: 5.6.26 -- Versión de PHP: 5.6.12 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Base de datos: `test_coupon` -- -- -------------------------------------------------------- -- -- Estructura de tabla para la tabla `coupon_detail` -- CREATE TABLE IF NOT EXISTS `coupon_detail` ( `id` int(11) NOT NULL, `coupon_code` varchar(255) NOT NULL, `coupon_value` int(11) NOT NULL ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1; -- -- Volcado de datos para la tabla `coupon_detail` -- INSERT INTO `coupon_detail` (`id`, `coupon_code`, `coupon_value`) VALUES (1, 'GET10', 10), (2, 'GET20', 20), (3, 'GET30', 30), (4, 'GET40', 40), (5, 'GET50', 50); -- -------------------------------------------------------- -- -- Estructura de tabla para la tabla `product_detail` -- CREATE TABLE IF NOT EXISTS `product_detail` ( `id` int(10) NOT NULL, `nombre` varchar(255) NOT NULL, `descripcion` text NOT NULL, `precio` double NOT NULL, `moneda` varchar(3) NOT NULL, `img` varchar(255) NOT NULL ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; -- -- Volcado de datos para la tabla `product_detail` -- INSERT INTO `product_detail` (`id`, `nombre`, `descripcion`, `precio`, `moneda`, `img`) VALUES (1, 'HP Pavilion x360 (11 pulgadas)', 'Este equipo convertible, repleto de recursos fantásticos, posee una bisagra que gira 360° y te permite cambiar fácilmente entre diversas posiciones (notebook, atril, tienda de campaña o tablet), según tus necesidades de trabajo o entretenimiento.', 400, 'USD', 'imagen_producto.jpg'); -- -- Índices para tablas volcadas -- -- -- Indices de la tabla `coupon_detail` -- ALTER TABLE `coupon_detail` ADD PRIMARY KEY (`id`); -- -- Indices de la tabla `product_detail` -- ALTER TABLE `product_detail` ADD PRIMARY KEY (`id`); -- -- AUTO_INCREMENT de las tablas volcadas -- -- -- AUTO_INCREMENT de la tabla `coupon_detail` -- ALTER TABLE `coupon_detail` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=6; -- -- AUTO_INCREMENT de la tabla `product_detail` -- ALTER TABLE `product_detail` MODIFY `id` int(10) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; |
Paso 2: Dentro de nuestra carpeta root, crear una carpeta llamada include, y dentro de dicha carpeta crear el archivo que conectará a nuestra base de datos; a dicho archivo lo hemos llamado conexion.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php function abrir_conexion() { // Credenciales de la base de datos $servername = "localhost";//Servidor de la base de datos $username = "root";//Nombre de usuario $password = "";//Contraseña //Nombre de la base de datos $dbname = "test_coupon"; try { global $con; // Abrir la conexion usando PDO. $con = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // Estable el modeo de errores usadndo excepciones PDO $con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die($e->getMessage());//Imprime el mensaje de error en pantalla } } function cerrar_conexion() { global $con; $con = null; } ?> |
Nota: Es necesario ingresar las credenciales de conexión a la base de datos, según corresponda en tu servidor.
Paso 3: Crear archivo function.php, dentro la carpeta include, creada en el paso anterior. Este archivo contiene todas las funciones necesarias para interactuar con nuestra base de datos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<?php //Esta funcion es usada para recorrer todos los registros de 1 tabla function Select_All_Records($table_name) { global $con; $sql = "select * from $table_name"; try { $stmt = $conn->query($sql); return $stmt; } catch (PDOException $e) { print $e->getMessage(); } } //Esta funcion es usada para recorrer los registro de 1 tabla aplicando 1 filtro. function Select_Record_By_One_Filter($data, $table_name) { global $con; $key = array_keys($data); $value = array_values($data); $sql = "select * from $table_name where $key[0] = '$value[0]'"; try { $stmt = $con->query($sql); return $stmt; } catch (PDOException $e) { print $e->getMessage(); } } //Esta funcion es usada para recorrer los registro de 1 tabla aplicando 2 filtros. function Select_Record_By_Two_Filter($data, $table_name) { global $con; $key = array_keys($data); $value = array_values($data); $sql = "select * from $table_name where $key[0] = '$value[0]' AND $key[1] = '$value[1]'"; try { $stmt = $con->query($sql); return $stmt; } catch (PDOException $e) { print $e->getMessage(); } } //Esta funcion es usada para obtener 1 registro de forma aleatoria. function Select_One_Random_Record($table_name) { global $con; $sql = "SELECT * FROM $table_name ORDER BY RAND() LIMIT 1"; try { $stmt = $con->query($sql); return $stmt; } catch (PDOException $e) { print $e->getMessage(); } } ?> |
Paso 4: Crear en el directorio root, el archivo index.php. Este es el archivo principal en el que los detalles de los productos se visualizan con el botón con el código promocional de descuento.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
<?php include('include/function.php'); include('include/conexion.php'); abrir_conexion(); $data = array('id' => 1); $p_query = Select_Record_By_One_Filter($data, 'product_detail'); $p_query->setFetchMode(PDO::FETCH_ASSOC); $p_result = $p_query->fetch(); $precio = $p_result['precio'];//precio del producto ?> <html> <head> <title>Cupones de descuento con PHP & Paypal</title> <link rel="stylesheet" type="text/css" href="style.css"> <script src="jquery.min.js"></script> </head> <body> <div id="main"> <h1 style="text-align: center;margin-left: 0px;">Cupones de descuento con PHP & Paypal </h1> <?php $query = Select_One_Random_Record('coupon_detail'); $query->setFetchMode(PDO::FETCH_ASSOC); $result = $query->fetch(); ?> <div id="message-placeholder"><p class="msg" style="text-align:center;">Usa el código promocional <b><?php echo $result['coupon_code']; ?></b> y obtienes el <b><?php echo $result['coupon_value']; ?>% </b> de descuento.</p></div> <div id="login"> <h2><?php echo $p_result['nombre']; ?></h2> <hr/> <div class="clear"></div> <div id="product_img"> <img src="<?php echo $p_result['img']; ?>"/> </div> <div class="content_wrapper"> <div class="content"> <p id="description"><?php echo $p_result['descripcion']; ?></p> </div> <div class="content" style="height:70px;"> <div id="get_promo_code"> <form action="" method="post" style="margin-bottom: 0px;"> <input type="text" id="promocode" placeholder="Ingresa el código promocional"> <input type='button' value="Aplicar" name="submit" onclick='check_promo_code()'> </form> <span id="wrong_code"></span> <span id="right_code"></span> </div> </div> <div class="content" style="height: 70px;"> <div id="amount"> <div id="without_promo" > <p> <b>Monto Total : $<?php echo $precio; ?></b> </p> </div> <div id="promo_offer"> <?php $amount_after_offer = $precio - ($precio * $result['coupon_value'] / 100) ?> <p><b>Monto Total : $<?php echo $amount_after_offer; ?></b></p> <del><p>Monto Total : $<?php echo $precio; ?></p></del> </div> </div> <div id="buynow"> <form action="process.php" method="POST"> <input type="hidden" value="" id="promo_id" name="promo_id"> <input type="hidden" value="1" id="p_id" name="p_id"> <div><input type="submit" class="fr" value="Comprar Ahora" name="submit"></div> </form> </div> </div> </div> </div><img id="paypal_logo" src="secure-paypal-logo.jpg"> </div> </body> <script language="javascript" type="text/javascript"> function check_promo_code() { $.ajax({ url: "check_promocode.php", type: "POST", data: {code: $("input#promocode").val(), id:<?php echo $result['id']; ?>}, success: function(data) { if (data == 'FALSE') { $("span#wrong_code").html('Por favor, ingresa un código de promoción válido.'); $("span#right_code").html(''); $("div#without_promo").show(); $("div#promo_offer").hide(); } else { $("span#right_code").html('Código promocional aplicado satisfactoriamente.'); $("span#wrong_code").html(''); $("div#without_promo").hide(); $("div#promo_offer").show(); $("input#p_id").val('1'); $("input#promo_id").val(<?php echo $result['id']; ?>); } } }); } </script> </html> <?php cerrar_conexion(); ?> |
Paso 5: Crear el archivo process.php. Este archivo contiene código para procesar el pago de PayPal. Para que el sistema procese de forma correcta los pagos, tienes que pegar correo electrónico de tu comercio según corresponda en la línea Nº: 39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?php include('include/function.php'); include('include/conexion.php'); if (isset($_POST['submit'])) { abrir_conexion(); if (isset($_POST['p_id'])) { if (isset($_POST['promo_id'])) { $data = array( 'id' => $_POST['p_id'] ); $p_query = Select_Record_By_One_Filter($data, 'product_detail'); $p_query->setFetchMode(PDO::FETCH_ASSOC); $p_result = $p_query->fetch(); $p_price = $p_result['precio']; $data = array( 'id' => $_POST['promo_id'] ); $promo_query = Select_Record_By_One_Filter($data, 'coupon_detail'); $promo_query->setFetchMode(PDO::FETCH_ASSOC); $promo_result = $promo_query->fetch(); $product_price = $p_price - ($p_price * $promo_result['coupon_value'] / 100); } else { $data = array( 'id' => $_POST['p_id'] ); $p_query = Select_Record_By_One_Filter($data, 'product_detail'); $p_query->setFetchMode(PDO::FETCH_ASSOC); $p_result = $p_query->fetch(); $product_price = $p_result['precio']; } $product_name = $p_result['nombre']; $product_currency = $p_result['moneda']; $product_id = $_POST['p_id'] . '#' . $_POST['promo_id']; //Se coloca la URL de paypal de prueba o modo produccion. $paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; //Correo electronico del comercio. $merchant_email = 'joaquinobed123456@gmail.com'; //Aqui cambiamos la URL cuando el usuario no completa el pago y cancela la transaccion $cancel_return = "http://obedalvarado.pw/demo/paypal-cupon/index.php"; //Aqui colocamos la URL donde redireccion cuando el pago es satisfactorio. $success_return = "http://obedalvarado.pw/demo/paypal-cupon/success.php"; echo cerrar_conexion(); ?> <div style="margin-left: 38%"><img src="ajax-loader.gif"/><img src="processing_animation.gif"/></div> <form name="myform" action="<?php echo $paypal_url; ?>" method="post" target="_top"> <input type="hidden" name="cmd" value="_xclick"> <input type="hidden" name="cancel_return" value="<?php echo $cancel_return ?>"> <input type="hidden" name="return" value="<?php echo $success_return; ?>"> <input type="hidden" name="business" value="<?php echo $merchant_email; ?>"> <input type="hidden" name="lc" value="C2"> <input type="hidden" name="item_name" value="<?php echo $product_name; ?>"> <input type="hidden" name="item_number" value="<?php echo $product_id; ?>"> <input type="hidden" name="amount" value="<?php echo $product_price; ?>"> <input type="hidden" name="currency_code" value="<?php echo $product_currency; ?>"> <input type="hidden" name="button_subtype" value="services"> <input type="hidden" name="no_note" value="0"> </form> <script type="text/javascript"> document.myform.submit(); </script><?php } } ?> |
Paso 6: Crear el archivo success.php. PayPal llama a este archivo cuando el pago se ha completado con éxito.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php include('include/function.php'); include('include/conexion.php'); echo abrir_conexion(); ?> <html> <head> <title>Cupones de descuento con PHP & Paypal</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <?php if (!empty($_REQUEST)) { $product_no = $_REQUEST['item_number']; // Product ID $product_transaction = $_REQUEST['tx']; // Paypal transaction ID $product_price = $_REQUEST['amt']; // Paypal received amount value $product_currency = $_REQUEST['cc']; // Paypal received currency type $product_status = $_REQUEST['st']; // Paypal product status $description = explode('#', $product_no); if ($description[0] != '') { if ($description[1] != '') { $data = array( 'id' => $description[0] ); $p_query = Select_Record_By_One_Filter($data, 'product_detail'); $p_query->setFetchMode(PDO::FETCH_ASSOC); $p_result = $p_query->fetch(); $p_price = $p_result['precio']; $data = array( 'id' => $description[1] ); $promo_query = Select_Record_By_One_Filter($data, 'coupon_detail'); $promo_query->setFetchMode(PDO::FETCH_ASSOC); $promo_result = $promo_query->fetch(); $product_actual_price = $p_price - ($p_price * $promo_result['coupon_value'] / 100); } else { $data = array( 'id' => $description[0] ); $p_query = Select_Record_By_One_Filter($data, 'product_detail'); $p_query->setFetchMode(PDO::FETCH_ASSOC); $p_result = $p_query->fetch(); $product_actual_price = $p_result['precio']; } } echo cerrar_conexion(); } ?> <div id="main" style="width: 960px; margin: 0 auto;"> <div id="return"> <h2>Estado del pago </h2> <hr/> <?php //Rechecking the product price and currency details if ($product_price ==$product_actual_price && $product_currency == $p_result['moneda']) { echo "<h3 id='success'>Pago satisfactorio</h3>"; echo "<P>Estado de la transacción - " . $product_status . "</P>"; echo "<P>Id de transacción - " . $product_transaction . "</P>"; echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Ir a productos</a></div>"; } else { echo "<h3 id='fail'>Pago falló</h3>"; echo "<P>Estado del pago - Incompleto</P>"; echo "<P>Id de transacción - " . $product_transaction . "</P>"; echo "<div class='back_btn'><a href='index.php' id= 'btn'><< Ir a produtos</a></div>"; } ?> </div> </div> </body> </html> |
Paso 7: Crear el archivo check_promocode.php. Este archivo es llamado desde el index.php mediante AJAX, y su función es verificar que el código promocional, ingresado por el usuario, se encuentre registrado en la base de datos, para poder aplicar el descuento respectivo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php include('include/function.php'); include('include/conexion.php'); abrir_conexion(); $code=$_POST['code']; $id=$_POST['id']; $data = array( 'coupon_code' => $code, 'id' =>$id ); $query = Select_Record_By_Two_Filter($data, 'coupon_detail'); $query->setFetchMode(PDO::FETCH_ASSOC); $result = $query->fetch(); if ($result!='') { echo $result['coupon_value']; } else { echo 'FALSE'; } cerrar_conexion(); ?> |
Paso 8: Creación archivo style.css. Incluye un estilo básico para los elementos HTML.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
@import url(http://fonts.googleapis.com/css?family=Raleway); h1 { text-align:center; } #main{ width:960px; margin:50px auto; font-family:raleway; } #login { width: 815px; float: left; border-radius: 10px; font-family: raleway; border: 1px solid #00a2d3; padding: 10px 40px 25px; margin: 17px 35px; } h2 { background-color: #d9edf7; text-align: center; border-radius: 10px 10px 0 0; margin: -10px -40px; padding: 15px; color:#3693c9; font-size: 20px; } hr{ border:0; border-bottom:1px solid #00a2d3; margin: 10px -40px; margin-bottom: 30px; } #product_img{ width: 50%; float: left; border: 1px dashed rgba(0, 0, 0, 0.15); } #product_img img{ padding: 10px; width: 95%; height: 340px; } .content_wrapper{ float: right; width: 48%; } .content{ border: 1px dashed rgba(0, 0, 0, 0.15); margin-bottom: 20px; padding: 11px; } .content p#description{ text-align:justify; padding:10px; } #get_promo_code input[type=button] { width: 24%; background-color: white; float: right; color: #00a2d3; border: 2px solid #00a2d3; padding: 10px; font-size: 20px; cursor: pointer; border-radius: 5px; } input[type=text],input[type=password]{ width: 73%; padding: 13px; border: 1px solid #00a2d3; padding-left: 5px; font-size: 15px; font-family:raleway; border-radius: 5px; } #amount{ width: 50%; float: left; } #without_promo{ } #promo_offer{ display: none; } #promo_offer del p{ color: rgba(128, 128, 128, .8); } #buynow{ width: 50%; float: right; } input[type=submit]{ width: 100%; background-color:green; color: white; border: 2px solid green; padding: 10px; font-size:20px; cursor:pointer; border-radius: 5px; margin-bottom: 15px; } span#wrong_code{ color:red; } span#right_code{ color:green; } #return { width: 50%; height: 350px; float: left; border-radius: 10px; font-family: raleway; border: 2px solid #00a2d3; padding: 10px 40px 11px; margin: 0 auto; margin-left:25%; margin-top:50px; } #message-placeholder { margin: 10px auto auto; background: #d9edf7!important; border: 1px solid #bce8f1; width: 875px; color: #31708f; padding: 10px; position: relative; z-index: 1; } #message-placeholder b { color: rgb(14, 207, 14); } #return h3#success { text-align: center; font-size: 24px; margin-top: 50px; color: green; } #return P { margin-left: 122px; } #return .back_btn { margin-top: 51px; margin-left: 19%; } #btn { width: 100%; background-color: #FFBC00; color: white; border: 2px solid #FFCB00; padding: 10px 70px; font-size: 20px; cursor: pointer; border-radius: 5px; margin-bottom: 15px; margin: 0 auto; } a{ text-decoration:none; color: cornflowerblue; } i{ color: cornflowerblue; } #product_content { float: right; width: 400px; height: 250px; margin-top: 20px; margin-bottom: 23px; font-size: 14px; border: 1px solid rgba(128, 128, 128, 0.17); } #get_promo_code input[type=button]:hover{ background-color:#00a2d3; color: white; } .clear{ clear: both; } .fr { float: right; } img#paypal_logo{ float: right; margin-right:25px; padding-bottom:15px; } |
Estructura final de archivos:
Conclusión:
Luego de haber leído el post anterior, estoy seguro de que será de mucha utilidad a tus proyectos a la hora de querer procesar pagos usando como pasarela de pagos Paypal, eres libre de usar el código tanto para fines educativos como para fines comerciales. Te invito a que dejes un comentario describiendo que tal te pareció este post, te lo agradeceré.