소스 검색

Soporte de categorias
Consulta de ciudades
Fix generales

Fernando Goetz 7 년 전
부모
커밋
f4028f7242
8개의 변경된 파일439개의 추가작업 그리고 124개의 파일을 삭제
  1. 5 0
      .gitignore
  2. BIN
      Documentacion_Pagopar.pdf
  3. 202 62
      Pagopar.php
  4. 2 2
      classes/BuyerPagopar.php
  5. 95 0
      classes/ConsultPagopar.php
  6. 10 13
      classes/ItemPagopar.php
  7. 39 28
      classes/OrderPagopar.php
  8. 86 19
      readme.md

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+old
+payline
+.idea
+api.php
+ejemplos.php

BIN
Documentacion_Pagopar.pdf


+ 202 - 62
Pagopar.php

@@ -8,21 +8,22 @@
 require_once 'lib/DBPagopar.php';
 
 require_once 'classes/OrderPagopar.php';
+require_once 'classes/ConsultPagopar.php';
 
 class Pagopar{
-    //Tokens del comercio //TODO(Quitar después)
-    const TOKEN_PRIVADO = 'dflghdf5458';
-    const TOKEN_PUBLICO = '123456abcdegf';
     //URLs de configuración
     const URL_BASE = 'https://api.pagopar.com/api/';
     const URL_COMERCIOS = self::URL_BASE.'comercios/1.1/iniciar-transaccion';
     const URL_PEDIDOS = self::URL_BASE.'pedidos/1.1/traer';
+    const URL_FLETE = self::URL_BASE.'calcular-flete/1.1/traer';
+    const URL_CATEGORIAS = self::URL_BASE.'categorias/1.1/traer';
+    const URL_CIUDADES = self::URL_BASE.'ciudades/1.1/traer';
     const URL_REDIRECT = 'https://pagopar.com/pagos/%s';
 
     //Tipos de Tokens generados
     const TOKEN_TIPO_CONSULTA = 'CONSULTA';
     const TOKEN_TIPO_CIUDAD = 'CIUDADES';
-    const TOKEN_TIPO_CATEGORIA = 'CATEGORIA';
+    const TOKEN_TIPO_CATEGORIA = 'CATEGORIAS';
     const TOKEN_TIPO_FLETE = 'CALCULAR-FLETE';
 
     //Base de datos
@@ -33,6 +34,11 @@ class Pagopar{
     private $hashOrder;
 
     public $order;
+    private $preOrder;
+    private $itemsIdMethods;
+
+    public $privateKey = null;
+    public $publicKey = null;
 
     /**
      * Constructor de la clase
@@ -75,14 +81,160 @@ class Pagopar{
     }
 
     /**
-     * Inicia la transacción con Pagopar y si tiene éxito al generar el pedido,
-     * redirecciona a la página de pago de Pagopar.
+     * Guarda en un array ($itemsIdMethods) los id_producto de los ítems y sus índices en el array
+     * compras_items ([id_producto => índice]) para que tengamos un acceso más rápido a los ítems.
+     * Además, para los ítems con más de un método de envío, guardamos los tipos de envío disponibles
+     * en un array ($multiple_methods) con sus valores para retornar después al usuario.
+     * @param array $arrayResponse Array que contiene las distintas opciones de envío de los ítems.
+     * @return string Respuesta en formato JSON que contiene las distintas opciones de envío de los ítems.
+     * Si se retorna false, se asume que no existen opciones de envío o que sólo existe una opción
+     * de envío para cada ítem.
+     */
+    private function saveMethodsOfShipping($arrayResponse){
+        $multiple_methods = [];
+        $this->itemsIdMethods = [];
+
+        //Si alguno de los ítems devueltos tiene los dos métodos de pago,
+        foreach ($arrayResponse->compras_items as $index => $item) {
+                //En un array guardamos los ids de los productos como índices y los índices como valor
+                //para que sean más fáciles de encontrar después.
+                $this->itemsIdMethods[$item->id_producto] = $index;
+                if(isset($item->opciones_envio) && isset($item->opciones_envio->metodo_aex) && isset($item->opciones_envio->propio)){
+                    $multiple_methods[$item->id_producto] = [
+                        "metodo_aex"=>$item->opciones_envio['metodo_aex'],
+                        "propio"=>$item->opciones_envio['propio']
+                    ];
+                }
+        }
+        //Guardamos la respuesta en preOrder
+        $this->preOrder = $arrayResponse;
+
+        return (!empty($multiple_methods))?json_encode($multiple_methods):false;
+    }
+
+    /**
+     * Inicia la conexión con Pagopar y obtiene los métodos de envío para cada ítem
+     * @return string|boolean Respuesta en formato JSON que contiene las distintas opciones de envío de los ítems.
+     * Si se retorna false, se asume que no existen opciones de envío o que sólo existe una opción
+     * de envío para cada ítem.
+     */
+    public function getMethodsOfShipping(){
+        $orderPagopar = $this->order->makeOrder();
+
+        $token = $this->generateToken(self::TOKEN_TIPO_FLETE);
+
+        $args = ['token'=>$token,'token_publico'=>$this->order->publicKey, 'dato'=>json_encode($orderPagopar)];
+        $response = $this->runCurl($args, self::URL_FLETE);
+
+        $arrayResponse = json_decode($response);
+
+        if(isset($arrayResponse->respuesta)&&!$arrayResponse->respuesta){
+            throw new Exception($arrayResponse->resultado);
+        }elseif(isset($arrayResponse->resultado) && $arrayResponse->resultado === "Sin datos"){
+            throw new Exception($arrayResponse->resultado);
+        }
+
+        return $this->saveMethodsOfShipping($arrayResponse);
+    }
+
+    /**
+     * Valida el JSON de los métodos de envío seleccionados.
+     * @param array $items Array con los métodos de envío seleccionados. Tiene esta estructura:
+     * ["id_producto_1" => "metodo_1", "id_producto_2" => "metodo_2", ... => ...]
+     * @return bool True si el JSON es válido (los id de los productos existen y los métodos de pago existen),
+     * False si no es un JSON válido.
+     */
+    private function validateItemsMethodsJSON($items){
+        foreach ($items as $id => $method){
+            if(array_key_exists($id,$this->itemsIdMethods)){
+                if(array_key_exists($method,$this->preOrder->compras_items[$this->itemsIdMethods[$id]]->opciones_envio)){
+                    return true;
+                }else{
+                    return false;
+                }
+            }else{
+               return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Completa los ítems de la orden con el campo envio_seleccionado
+     * @param string $json_items Cadena JSON que contiene las opciones de envío de los ítems.
+     * @return array Array de respuesta que contiene la Orden con el flete calculado de los ítems o
+     * un array de error en caso de fallo.
+     * @throws Exception
+     */
+    private function fillShippingOptions($json_items){
+
+        $items_methods = null;
+        if($json_items) {
+            $items_methods = json_decode($json_items);
+            if (!$this->validateItemsMethodsJSON($items_methods)) {
+                throw new Exception("Hay un error con el JSON de los métodos seleccionados de los items");
+            }
+        }
+
+        foreach($this->preOrder->compras_items as $index => $item){
+            //Obtenemos el primer y único elemento en el caso de que sólo haya un método seleccionado
+            if(isset($item->opciones_envio)){
+                $key = key($item->opciones_envio);
+                $item->envio_seleccionado = ($key==="metodo_aex")?"aex":$key;
+            }
+        }
+        //Completamos los campos necesarios para envio_seleccionado
+        if($json_items){
+            foreach($items_methods as $id => $method){
+                $this->preOrder->compras_items[$this->itemsIdMethods[$id]]->envio_seleccionado = $method;
+            }
+        }
+        //Calculamos el flete
+        return $this->getShippingCost();
+    }
+
+    /**
+     * Calcula el flete de los ítems si es necesario
+     * @return array Array de respuesta que contiene la Orden con el flete calculado de los ítems o
+     * un array de error en caso de fallo.
+     */
+    private function getShippingCost(){
+        $token = $this->generateToken(self::TOKEN_TIPO_FLETE);
+
+        $args = ['token'=>$token,'token_publico'=>$this->order->publicKey, 'dato'=> json_encode($this->preOrder)];
+        $response = $this->runCurl($args, self::URL_FLETE);
+
+        return json_decode($response);
+    }
+
+    /**
+     * Reenvía el pedido a Pagopar (con el flete calculado) y genera una transacción. Si tiene éxito al
+     * generar el pedido, redirecciona a la página de pago de Pagopar.
+     * @param string $json_items Cadena JSON que contiene las opciones de envío de los ítems.
+     * Si no recibe este parámetro, se asume que no existen opciones de envío o que sólo existe una opción
+     * de envío para cada ítem.
      * @throws Exception
      */
-    public function newPagoparTransaction(){
-        $orderPagopar = $this->order->makeOrder($this->idOrder);
+    public function newPagoparTransaction($json_items=null){
+
+        $response = $this->fillShippingOptions($json_items);
+
+        //Verificar si hay error
+        if(isset($response->respuesta) && !$response->respuesta){
+            throw new Exception($response->resultado);
+        }
+
+        //Asignamos de nuevo a la orden la respuesta
+        $this->preOrder = $response;
 
-        $response = $this->runCurl($orderPagopar, self::URL_COMERCIOS);
+        //Generamos de nuevo el token
+        $this->preOrder->token = $this->order->generateOrderHash(
+            $this->preOrder->id_pedido_comercio,
+            $this->preOrder->monto_total,
+            $this->order->privateKey
+        );
+
+        $response = $this->runCurl($this->preOrder, self::URL_COMERCIOS);
         $arrayResponse = json_decode($response);
 
         //Verificar si hay error
@@ -92,12 +244,13 @@ class Pagopar{
 
         $this->hashOrder = $arrayResponse->resultado[0]->data;
 
-        $this->db->insertTransaction($orderPagopar['id_pedido_comercio'],
-            $orderPagopar['tipo_pedido'],
-            $orderPagopar['monto_total'],
+        $this->db->insertTransaction(
+            $this->preOrder->id_pedido_comercio,
+            $this->preOrder->tipo_pedido,
+            $this->preOrder->monto_total,
             $this->hashOrder,
-            $orderPagopar['fecha_maxima_pago'],
-            $orderPagopar['descripcion_resumen']
+            $this->preOrder->fecha_maxima_pago,
+            $this->preOrder->descripcion_resumen
         );
 
         $this->redirectToPagopar($this->hashOrder);
@@ -118,11 +271,10 @@ class Pagopar{
      * Inicia la transacción con Pagopar y si tiene éxito al generar el pedido con valores de prueba,
      * redirecciona a la página de pago de Pagopar.
      */
-    public function newTestPagoparTransaction(){
+    public function newTestPagoparTransaction($public_key,$private_key,$seller_public_key){
         //Creamos el comprador
         $buyer = new BuyerPagopar();
         $buyer->name            = 'Juan Perez';
-        $buyer->email           = 'mihares@gmail.com';
         $buyer->cityId          = 1;
         $buyer->tel             = '0972200046';
         $buyer->typeDoc         = 'CI';
@@ -146,11 +298,12 @@ class Pagopar{
         $item1->url_img             = "http://www.clipartkid.com/images/318/tickets-for-the-film-festival-are-for-the-two-day-event-admission-is-lPOEYl-clipart.png";
         $item1->weight              = '0.1';
         $item1->category            = 3;
+        $item1->productId           = 100;
         $item1->sellerPhone         = '0985885487';
-        $item1->sellerEmail         = 'mihares@gmail.com';
         $item1->sellerAddress       = 'dr paiva ca cssssom gaa';
         $item1->sellerAddressRef    = '';
         $item1->sellerAddressCoo    = '-28.75438,-57.1580038';
+        $item1->sellerPublicKey     = $seller_public_key;
 
         $item2 = new ItemPagopar();
         $item2->name                = "Heladera";
@@ -160,30 +313,51 @@ class Pagopar{
         $item2->desc                = "producto";
         $item2->url_img             = "https://cdn1.hendyla.com/archivos/imagenes/2017/04/09/publicacion-564c19b86b235526160f43483c76a69ee1a85c96c976c33e3e21ce6a5f9009b9-234_A.jpg";
         $item2->weight              = '5.0';
-        $item2->category            = 3;
+        $item2->category            = 8;//Cambiar a 8
+        $item2->productId           = 2;
         $item2->sellerPhone         = '0985885487';
-        $item2->sellerEmail         = 'mihares@gmail.com';
         $item2->sellerAddress       = 'dr paiva ca cssssom gaa';
         $item2->sellerAddressRef    = '';
         $item2->sellerAddressCoo    = '-28.75438,-57.1580038';
+        $item2->sellerPublicKey     = $seller_public_key;
 
         //Agregamos los productos al pedido
         $this->order->addPagoparItem($item1);
         $this->order->addPagoparItem($item2);
 
-        $this->order->publicKey = self::TOKEN_PUBLICO;
-        $this->order->privateKey = self::TOKEN_PRIVADO;
+        $this->order->publicKey = $public_key;
+        $this->order->privateKey = $private_key;
         $this->order->typeOrder = 'VENTA-COMERCIO';
         $this->order->desc = 'Entrada Retiro';
-        $this->order->periodDays = 1;
-        $this->order->periodDays = 0;
+        $this->order->periodOfDaysForPayment = 1;
+        $this->order->periodOfHoursForPayment = 0;
+
+        /*Calculamos el flete y... si es algún ítem tiene opcion_envio metodo_aex Y propio, entonces retornamos
+        un json en el que el usuario debe seleccionar el método de pago para el ítem específico*/
+        $json_pedido_con_flete = $this->getMethodsOfShipping();
 
-        $this->newPagoparTransaction();
+        if( !$json_pedido_con_flete ){
+            $this->newPagoparTransaction();
+        }else{
+            /*Seleccionamos los métodos de envío y después generamos la nueva transacción
+            Método para seleccionar el envío, debe ser una pantalla intermedia
+            y hay que llamar a la función newPagoparTransaction con un array como parámetro.
+            El json debe tener esta forma:
+            {
+                id_producto_1 : metodo_seleccionado_1,
+                id_producto_2 : metodo_seleccionado_2,
+                ...           : ...
+            }
+            */
+            //$json_items_metodo_seleccionado = '{"100":"aex"}';
+            //$pedidoPagopar->newPagoparTransaction($json_items_metodo_seleccionado);
+        }
     }
 
     /**
      * Obtiene un JSON con el estado del pedido
      * @param int $id Id del pedido
+     * @return JSON con el estado del Pedido
      * @throws Exception
      */
     public function getPagoparOrderStatus($id){
@@ -196,10 +370,10 @@ class Pagopar{
         }
         $token = $this->generateToken(self::TOKEN_TIPO_CONSULTA);
 
-        $args = ['hash_pedido'=>$this->hashOrder, 'token'=>$token, 'token_publico'=> self::TOKEN_PUBLICO];
+        $args = ['hash_pedido'=>$this->hashOrder, 'token'=>$token, 'token_publico'=>$this->publicKey];
         $arrayResponse = $this->runCurl($args, self::URL_PEDIDOS);
 
-        print_r($arrayResponse);
+        return $arrayResponse;
     }
 
     /**
@@ -208,42 +382,8 @@ class Pagopar{
      * @return string Token generado
      */
     private function generateToken($typeOfToken){
-        return sha1(self::TOKEN_PRIVADO.$typeOfToken);
-    }
-
-    /**
-     * Retorna las ciudades en forma de array
-     * @param string $typeOfToken Tipo de token generado
-     * @return string Token generado
-     */
-    public function consultarCiudades(){
-        $token = $this->generateToken(self::TOKEN_TIPO_CIUDAD);
-
-        $url = self::URL_BASE.'ciudades/1.1/traer';
-        $args = ['token'=>$token,'token_publico'=> self::TOKEN_PUBLICO];
-        $arrayResponse = $this->runCurl($args, $url);
-
-        return $arrayResponse;
-    }
-
-
-    public function consultarCategorias(){
-        $token = $this->generateToken(self::TOKEN_TIPO_CATEGORIA);
-
-        $url = self::URL_BASE.'categorias/1.1/traer';
-        $args = ['token'=>$token,'token_publico'=> self::TOKEN_PUBLICO];
-        $arrayResponse = $this->runCurl($args, $url);
-        return $arrayResponse;
-    }
-
-    #CALCULAR-FLETE
-    public function calcularFlete($json){
-        $token = $this->generateToken(self::TOKEN_TIPO_FLETE);
-
-        $url = self::URL_BASE.'calcular-flete/1.1/traer';
-        $args = ['token'=>$token,'token_publico'=> self::TOKEN_PUBLICO, 'dato'=> $json];
-        $arrayResponse = $this->runCurl($args, $url);
-        return $arrayResponse;
+        $key = ($this->privateKey)?$this->privateKey:$this->order->privateKey;
+        return sha1($key.$typeOfToken);
     }
 
     #registrar usuario

+ 2 - 2
classes/BuyerPagopar.php

@@ -8,8 +8,8 @@
 class BuyerPagopar{
 
     public $name; //string (Obligatorio) Nombre del producto
-    public $email; //string (Obligatorio) Email del comprador
     public $cityId; //int (Obligatorio) Id de la ciudad
+    public $email; //string Email del Comprador
     public $tel; //string Teléfono del comprador
     public $typeDoc; //string Tipo de documento del comprador
     public $doc; //string Documento del comprador
@@ -32,8 +32,8 @@ class BuyerPagopar{
     public function formatToArray(){
         return [
             'nombre' => $this->name,
-            'email' => $this->email,
             'ciudad' => $this->cityId,
+            'email'  => $this->email,
             'telefono' => $this->tel,
             'tipo_documento' => $this->typeDoc,
             'documento' => $this->doc,

+ 95 - 0
classes/ConsultPagopar.php

@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * Archivo SDK de las funciones de consulta de Pagopar
+ * @author "Pagopar" <desarrollo@pagopar.com>
+ * @version 1 27/4/2017
+ */
+
+class ConsultPagopar{
+    //URLs de configuración
+    const URL_BASE = 'https://api.pagopar.com/api/';
+    const URL_CATEGORIAS = self::URL_BASE.'categorias/1.1/traer';
+    const URL_CIUDADES = self::URL_BASE.'ciudades/1.1/traer';
+
+    //Tipos de Tokens generados
+    const TOKEN_TIPO_CIUDAD = 'CIUDADES';
+    const TOKEN_TIPO_CATEGORIA = 'CATEGORIAS';
+
+    public $privateKey = null;
+    public $publicKey = null;
+
+    /**
+     * Constructor de la clase
+     */
+    public function __construct() {
+
+    }
+
+    /**
+     * Invoca a la URL de acuerdo a los parámetros
+     * @param array $args Parámetros
+     * @param  string $url Url a invocar
+     * @return string Respuesta en formato JSON
+     */
+    private function runCurl($args, $url){
+        $args = json_encode($args);
+
+        $ch = curl_init();
+        $headers= array('Accept: application/json','Content-Type: application/json');
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+
+        curl_setopt($ch, CURLOPT_POST, true);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
+
+        $response = curl_exec($ch);
+        $error = curl_error($ch);
+        $info = curl_getinfo($ch);
+        curl_close($ch);
+
+        return $response;
+    }
+
+    /**
+     * Genera un Token para el pedido
+     * @param string $typeOfToken Tipo de token generado
+     * @return string Token generado
+     */
+    private function generateToken($typeOfToken){
+        return sha1($this->privateKey.$typeOfToken);
+    }
+
+    /**
+     * Obtiene las ciudades de los productos
+     * @return array $resultado Array de objetos con los atributos de las ciudades o,
+     * en caso de error, un Array con resultado "Sin datos"
+     */
+    public function getCities(){
+        $token = $this->generateToken(self::TOKEN_TIPO_CIUDAD);
+
+        $args = ['token'=>$token,'token_publico'=>$this->publicKey];
+        $response = $this->runCurl($args, self::URL_CIUDADES);
+
+        return json_decode($response);
+    }
+
+    /**
+     * Obtiene las categorías de los productos
+     * @return array $resultado Array de objetos con los atributos de las categorías o,
+     * en caso de error, un Array con resultado "Sin datos"
+     */
+    public function getProductCategories(){
+        $token = $this->generateToken(self::TOKEN_TIPO_CATEGORIA);
+
+        $args = ['token'=>$token,'token_publico'=>$this->publicKey];
+        $response = $this->runCurl($args, self::URL_CATEGORIAS);
+        $arrayResponse = json_decode($response);
+
+        return $arrayResponse->resultado;
+    }
+
+}

+ 10 - 13
classes/ItemPagopar.php

@@ -14,15 +14,16 @@ class ItemPagopar{
     public $desc; //string Descripción del producto
     public $url_img; //string Url de la imagen del producto
     public $weight; //string Peso del producto
+    public $category;//int Id de la Categoría
+    public $productId;//int Id del producto (elegido por el usuario)
+    public $large;//string Largo del producto
+    public $width;//string Ancho del producto
+    public $height;//string Alto del producto
     public $sellerPhone; //string Teléfono del vendedor
-    public $sellerEmail; //string Email del vendedor
     public $sellerAddress; //string Dirección del vendedor
     public $sellerAddressRef; //string Referencia de la dirección del vendedor
     public $sellerAddressCoo; //string Coordenadas (latitud y longitud separados por coma) de la dirección del vendedor
-    public $category;
-    /*public $large;
-    public $width;
-    public $height;*/
+    public $sellerPublicKey;//string Clave pública del vendedor
 
     /**
      * Constructor de la clase
@@ -35,8 +36,6 @@ class ItemPagopar{
      * @return array Array del Producto
      */
     public function formatToArray(){
-        $envioAEX1['costo'] = null;
-        $envioAEX1['tiempo_entrega'] = null;
         return [
             'nombre' => $this->name,
             'cantidad' => $this->qty,
@@ -46,17 +45,15 @@ class ItemPagopar{
             'url_imagen' => $this->url_img,
             'peso' => $this->weight,
             'vendedor_telefono' => $this->sellerPhone,
-            'vendedor_email' => $this->sellerEmail,
             'vendedor_direccion' => $this->sellerAddress,
             'vendedor_direccion_referencia' => $this->sellerAddressRef,
             'vendedor_direccion_coordenadas' => $this->sellerAddressCoo,
-            'opciones_envio' => [
-                'metodo_aex' => $envioAEX1
-            ],
+            'public_key' => $this->sellerPublicKey,
             'categoria' => $this->category,
-            /*'largo' => $this->large,
+            'id_producto' => $this->productId,
+            'largo' => $this->large,
             'ancho' => $this->width,
-            'alto' => $this->height*/
+            'alto' => $this->height
         ];
     }
 }

+ 39 - 28
classes/OrderPagopar.php

@@ -9,7 +9,7 @@ require_once 'ItemPagopar.php';
 require_once 'BuyerPagopar.php';
 
 class OrderPagopar{
-    public $order = [];
+    public $order = null;
 
     public $idOrder;
     public $publicKey;
@@ -21,10 +21,11 @@ class OrderPagopar{
 
     /**
      * Constructor de la clase
+     * @param int $id Id del pedido
      */
     public function __construct($id){
         $this->idOrder = $id;
-        $this->order = [
+        $this->order = (object) [
             'tipo_pedido' => null,
             'fecha_maxima_pago' => null,
             'public_key' => null,
@@ -35,6 +36,15 @@ class OrderPagopar{
             'comprador' => null,
             'compras_items' => null
         ];
+        /*$this->order->tipo_pedido = null;
+        $this->order->fecha_maxima_pago = null;
+        $this->order->public_key = null;
+        $this->order->id_pedido_comercio = null;
+        $this->order->monto_total = null;
+        $this->order->token = null;
+        $this->order->descripcion_resumen = null;
+        $this->order->comprador = null;
+        $this->order->compras_items = null;*/
     }
 
     /**
@@ -43,11 +53,11 @@ class OrderPagopar{
      * @throws Exception
      */
     public function addPagoparItem($item){
-        $error = $this->validateItemAttributes($item->name, $item->qty, $item->price, $item->cityId);
+        $error = $this->validateItemAttributes($item->name, $item->qty, $item->price, $item->cityId, $item->productId);
         if($error['status']){
             throw new Exception($error['msg']);
         }
-        $this->order['compras_items'][] = $item->formatToArray();
+        $this->order->compras_items[] = $item->formatToArray();
     }
 
     /**
@@ -56,24 +66,29 @@ class OrderPagopar{
      * @param int $qty (Obligatorio) Cantidad de unidades del producto
      * @param int $price (Obligatorio) Suma total de los precios de los productos
      * @param int $cityId (Obligatorio) Id de la ciudad
+     * @param int $productId (Obligatorio) Id del producto
      * @return array $error Array con el status (true|false) y el mensaje de error
      */
-    private function validateItemAttributes($name, $qty, $price, $cityId){
+    private function validateItemAttributes($name, $qty, $price, $cityId, $productId){
         $error = ['status'=>false,'msg'=>''];
         if(empty($name)){
             $error['status'] = true; $error['msg'] = "Hay un error con el nombre de algún producto";
             return $error;
         }
         if(empty($qty) || !is_numeric($qty) || $qty < 0){
-            $error['status'] = true; $error['msg'] = "Hay un error en la cantidad del producto con nombre '{$name}'";
+            $error['status'] = true; $error['msg'] = "Hay un error en la cantidad del producto '{$name}'";
             return $error;
         }
         if(empty($price) || !is_numeric($price) || $price < 0){
-            $error['status'] = true; $error['msg'] = "Hay un error en el precio del producto con nombre '{$name}'";
+            $error['status'] = true; $error['msg'] = "Hay un error en el precio del producto '{$name}'";
             return $error;
         }
         if(empty($cityId) || !is_numeric($cityId) || $cityId < 0){
-            $error['status'] = true; $error['msg'] = "Hay un error en el ID de la ciudad del producto con nombre '{$name}'";
+            $error['status'] = true; $error['msg'] = "Hay un error en el ID de la ciudad del producto '{$name}'";
+            return $error;
+        }
+        if(empty($productId) || !is_numeric($productId) || $productId < 0){
+            $error['status'] = true; $error['msg'] = "Hay un error en el ID del producto '{$name}'";
             return $error;
         }
         return $error;
@@ -81,7 +96,7 @@ class OrderPagopar{
 
     /**
      * Agrega un comprador al pedido
-
+     * @param object $buyer Comprador
      * @throws Exception
      */
     public function addPagoparBuyer($buyer){
@@ -90,7 +105,7 @@ class OrderPagopar{
             throw new Exception($error['msg']);
         }
 
-        $this->order['comprador'] = $buyer->formatToArray();
+        $this->order->comprador = $buyer->formatToArray();
     }
 
     /**
@@ -144,10 +159,11 @@ class OrderPagopar{
      * Genera un hash del pedido
      * @param int $id Id del pedido
      * @param int $amount Monto total del pedido
+     * @param string $private_key Clave privada
      * @return string Hash del pedido
      */
-    private function generateOrderHash($id = null, $amount = 0, $private_token = null){
-        return sha1($private_token . $id . $amount);
+    public function generateOrderHash($id = null, $amount = 0, $private_key = null){
+        return sha1($private_key . $id . $amount);
     }
 
     /**
@@ -155,14 +171,16 @@ class OrderPagopar{
      * @return string Fecha en formato yyyy-mm-dd hh:mm:ss
      */
     private function makeMaxDateForPayment(){
+        date_default_timezone_set("America/Asuncion");
         //Transformamos el día a horas
         $daysToHours = ($this->periodOfDaysForPayment)?($this->periodOfDaysForPayment*24):0;
-        return date("Y-m-d H:i:s",mktime(date("h")+$this->periodOfHoursForPayment+$daysToHours,
+        return date("Y-m-d H:i:s",mktime(date("H")+$this->periodOfHoursForPayment+$daysToHours,
             date("i"),date("s"),date("m"),date("d"),date("Y")));
     }
 
     /**
      * Obtiene el precio total de la compra
+     * @param array $items Productos
      * @return int Suma total del precio de los Items
      */
     private function getTotalAmount($items){
@@ -175,13 +193,6 @@ class OrderPagopar{
 
     /**
      * Genera el pedido
-     * @param int $idOrder Id del pedido
-     * @param string $publicKey (Obligatorio) Clave pública del comercio
-     * @param string $privateKey (Obligatorio) Clave privada del comercio
-     * @param int $typeOrder (Obligatorio) Tipo de pedido
-     * @param string $desc Descripción del pedido
-     * @param int $periodDays Periodo máximo de días para completar el pago
-     * @param int $periodHours Periodo máximo de horas para completar el pago
      * @return array Array formado del pedido
      * @throws Exception
      */
@@ -199,16 +210,16 @@ class OrderPagopar{
             throw new Exception($error['msg']);
         }
 
-        $totalAmount = $this->getTotalAmount($this->order['compras_items']);
+        $totalAmount = $this->getTotalAmount($this->order->compras_items);
 
         //Datos de configuración del pedido
-        $this->order['public_key'] = $this->publicKey;
-        $this->order['tipo_pedido'] = $this->typeOrder;
-        $this->order['fecha_maxima_pago'] = $this->makeMaxDateForPayment();
-        $this->order['id_pedido_comercio'] = $this->idOrder;
-        $this->order['monto_total'] = $totalAmount;
-        $this->order['token'] = $this->generateOrderHash($this->idOrder,$totalAmount,$this->privateKey);
-        $this->order['descripcion_resumen'] = $this->desc;
+        $this->order->public_key = $this->publicKey;
+        $this->order->tipo_pedido = $this->typeOrder;
+        $this->order->fecha_maxima_pago = $this->makeMaxDateForPayment();
+        $this->order->id_pedido_comercio = $this->idOrder;
+        $this->order->monto_total = $totalAmount;
+        $this->order->token = $this->generateOrderHash($this->idOrder,$totalAmount,$this->privateKey);
+        $this->order->descripcion_resumen = $this->desc;
 
         return $this->order;
     }

+ 86 - 19
readme.md

@@ -1,32 +1,80 @@
-# SDK Pagopar
+# SDK PHP Pagopar
 
 ## Primeros pasos
 
-#### 1. Usar una base de datos
+#### 1. Incluir la clase de Pagopar
+
+Incluimos la clase de Pagopar que se encuentra en el archivo `Pagopar.php`.
+
+```php
+    require 'Pagopar.php';
+```
+
+
+#### 2. Usar una base de datos
 
 **Es necesario crear una base de datos MySQL o usar una ya existente** antes de usar el SDK de Pagopar.
 
-#### 2. Inicializar la base de datos
+#### 3. Inicializar la base de datos
 
-Instanciamos la clase `DBPagopar` con los datos necesarios para inicializar la base de datos. El SDK automáticamente crea una tabla llamada `transactions` en la que se guardarán los pedidos.
+Instanciamos la clase `DBPagopar` con los datos necesarios para inicializar la base de datos.  El SDK automáticamente crea una tabla llamada `transactions` en la que se guardarán los pedidos.
  Los parámetros a ser pasados son todas cadenas: `dbname` (el nombre de la base de datos), `dbuser` (el usuario) y `dbpass` (la contraseña).
 
 
 ```php
- $db = new DBPagopar( dbname , dbuser , dbpass );
+    $db = new DBPagopar( 'dbname' , 'dbuser' , 'dbpass' );
 ```
 
-#### 3. Elegir un nuevo id para un pedido
+#### 4. Elegir un nuevo id para un pedido
 
 Debemos elegir un id para realizar un nuevo pedido o consultar una transacción realizada anteriormente. **En ambos casos el id debe ser un entero mayor a cero**.
 
 En el caso de una **nueva transacción**, debemos elegir un **valor superior al id del último pedido realizado**.
 
-## Realizar un nuevo pedido
+## Ejemplo de nueva transacción
+
+#### Instanciar el pedido
+
+Lo primero que hacemos es crear una variable, en este caso `pedidoPagopar`, e instanciamos la clase de Pagopar, pasandole como parámetro el id del nuevo pedido.
 
-## Código de ejemplo completo
 
 ```php
+    $pedidoPagopar= new Pagopar( idNuevoPedido, $db );
+```
+
+#### Crear transacción de prueba
+
+Para realizar una transacción de prueba podemos usar el método `newTestPagoparTransaction` que realiza un pedido de prueba con valores precargados.
+
+```php
+    $pedidoPagopar= new newTestPagoparTransaction( idNuevoPedido, $db );
+```
+
+Así, para generar un nuevo pedido de prueba de manera sencilla tenemos que:
+
+```php
+    require 'Pagopar.php';
+
+    $db = new  DBPagopar( ’dbname ’ , ’dbuser ’ , ’dbpass ’ );
+    /* Generar  nuevo  pedido */
+    //Id  mayor  al Id del  ultimo  pedido , solo  para  pruebas
+    $idNuevoPedido = nuevo_id;
+    // Generamos  el  pedido
+    $pedidoPagoPar = new  Pagopar($idNuevoPedido ,$db);
+    $pedidoPagoPar ->newTestPagoparTransaction ();
+```
+
+
+Para nuestro ejemplo nos basta usar esta función, pero si se desea hacer una transacción con valores customizables se puede usar el método `newPagoparTransaction`.
+
+
+#### Nueva transacción con valores personalizables
+
+El siguiente código posee valores similares a los del método `newTestPagoparTransaction`, pero con algunas cadenas que deben ser reemplazadas por valores reales.
+
+```php
+
+    require 'Pagopar.php';
 
     $db = new DBPagopar( 'dbname' , 'dbuser' , 'dbpass' );
 
@@ -39,7 +87,7 @@ En el caso de una **nueva transacción**, debemos elegir un **valor superior al
     //Creamos el comprador
     $buyer = new BuyerPagopar();
     $buyer->name            = 'Juan Perez';
-    $buyer->email           = 'correo_electrónico';
+    $buyer->public_key      = 'public_key';
     $buyer->cityId          = 1;
     $buyer->tel             = '0972200046';
     $buyer->typeDoc         = 'CI';
@@ -61,6 +109,7 @@ En el caso de una **nueva transacción**, debemos elegir un **valor superior al
     $item1->desc                = "producto";
     $item1->url_img             = "https://www.hendyla.com/images/lazo_logo.png";
     $item1->weight              = '0.1';
+    $item1->category            = 3;
     $item1->sellerPhone         = '0985885487';
     $item1->sellerEmail         = 'correo_electrónico';
     $item1->sellerAddress       = 'lorep ipsum';
@@ -75,6 +124,7 @@ En el caso de una **nueva transacción**, debemos elegir un **valor superior al
     $item2->desc                = "producto";
     $item2->url_img             = "https://www.hendyla.com/images/lazo_logo.png";
     $item2->weight              = '5.0';
+    $item2->category            = 3;
     $item2->sellerPhone         = '0985885487';
     $item2->sellerEmail         = 'correo_electrónico';
     $item2->sellerAddress       = 'lorep ipsum dolor';
@@ -82,19 +132,36 @@ En el caso de una **nueva transacción**, debemos elegir un **valor superior al
     $item2->sellerAddressCoo    = '-28.75438,-57.1580038';
 
     //Agregamos los productos al pedido
-    $this->order->addPagoparItem($item1);
-    $this->order->addPagoparItem($item2);
+    $pedidoPagoPar->order->addPagoparItem($item1);
+    $pedidoPagoPar->order->addPagoparItem($item2);
 
     //Pasamos los parámetros para el pedido
-    $this->order->publicKey = 'clave pública';
-    $this->order->privateKey = 'clave privada';
-    $this->order->typeOrder = 'VENTA-COMERCIO';
-    $this->order->desc = 'Entrada Retiro';
-    $this->order->periodDays = 1;
-    $this->order->periodDays = 0;
+    $pedidoPagoPar->order->publicKey = 'clave pública';
+    $pedidoPagoPar->order->privateKey = 'clave privada';
+    $pedidoPagoPar->order->typeOrder = 'VENTA-COMERCIO';
+    $pedidoPagoPar->order->desc = 'Entrada Retiro';
+    $pedidoPagoPar->order->periodOfDaysForPayment = 1;
+    $pedidoPagoPar->order->periodOfHoursForPayment = 0;
 
     //Hacemos el pedido
-    $this->newPagoparTransaction();
+    $pedidoPagoPar->newPagoparTransaction();
+
+
+  ```
+
+#### Consultar transacción
+
+ Para consultar un pedido realizado previamente debemos conocer el id del mismo. Una vez que lo tenemos, basta con llamar a `getPagoparOrderStatus`, la cual nos retorna un JSON con las indicaciones de la transacción.
+
+```php
+
+    require 'Pagopar.php';
+
+    $db = new DBPagopar('dbname','dbuser','dbpass');
 
+    /*Consultar pedido*/
+    $idPedido = id_pedido;
+    $pedidoPagopar = new Pagopar($idPedido, $db);
+    $pedidoPagopar->getPagoparOrderStatus($idPedido);
 
-  ```
+   ```