├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── pint.json └── src ├── Api.php ├── Exceptions ├── GenericException.php ├── InstapagoAuthException.php ├── InstapagoBankRejectException.php ├── InstapagoException.php ├── InstapagoInvalidInputException.php ├── InstapagoTimeoutException.php └── ValidationException.php └── Validator.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `instapago` will be documented in this file. 4 | 5 | ## v9.0.0 - 2024-12-22 6 | 7 | ### What's Changed 8 | 9 | * Bump aglipanci/laravel-pint-action from 1.0.0 to 2.2.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/51 10 | * Bump dependabot/fetch-metadata from 1.4.0 to 1.5.1 by @dependabot in https://github.com/abr4xas/php-instapago/pull/52 11 | * Bump aglipanci/laravel-pint-action from 2.2.0 to 2.3.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/53 12 | * Bump dependabot/fetch-metadata from 1.5.1 to 1.6.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/54 13 | * Bump actions/checkout from 3 to 4 by @dependabot in https://github.com/abr4xas/php-instapago/pull/55 14 | * Bump stefanzweifel/git-auto-commit-action from 4 to 5 by @dependabot in https://github.com/abr4xas/php-instapago/pull/56 15 | * Bump aglipanci/laravel-pint-action from 2.3.0 to 2.3.1 by @dependabot in https://github.com/abr4xas/php-instapago/pull/57 16 | * Bump aglipanci/laravel-pint-action from 2.3.1 to 2.4 by @dependabot in https://github.com/abr4xas/php-instapago/pull/59 17 | * Bump dependabot/fetch-metadata from 1.6.0 to 2.0.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/58 18 | * Bump dependabot/fetch-metadata from 2.0.0 to 2.1.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/60 19 | * Bump dependabot/fetch-metadata from 2.1.0 to 2.2.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/61 20 | * adding some changes by @abr4xas in https://github.com/abr4xas/php-instapago/pull/62 21 | 22 | **Full Changelog**: https://github.com/abr4xas/php-instapago/compare/v8.0.0...v9.0.0 23 | 24 | ## v8.0.0 - 2023-05-02 25 | 26 | ### What's Changed 27 | 28 | - Bump dependabot/fetch-metadata from 1.3.4 to 1.3.5 by @dependabot in https://github.com/abr4xas/php-instapago/pull/47 29 | - Bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 by @dependabot in https://github.com/abr4xas/php-instapago/pull/48 30 | - Bump dependabot/fetch-metadata from 1.3.6 to 1.4.0 by @dependabot in https://github.com/abr4xas/php-instapago/pull/49 31 | - actualización a php 8.1 by @abr4xas in https://github.com/abr4xas/php-instapago/pull/50 32 | 33 | **Full Changelog**: https://github.com/abr4xas/php-instapago/compare/v7.0.0...v8.0.0 34 | 35 | ## v7.0.0 - 2022-10-08 36 | 37 | ### What's Changed 38 | 39 | - update repo by @abr4xas in https://github.com/abr4xas/php-instapago/pull/45 40 | - Bump dependabot/fetch-metadata from 1.3.3 to 1.3.4 by @dependabot in https://github.com/abr4xas/php-instapago/pull/46 41 | 42 | ### New Contributors 43 | 44 | - @dependabot made their first contribution in https://github.com/abr4xas/php-instapago/pull/46 45 | 46 | **Full Changelog**: https://github.com/abr4xas/php-instapago/compare/v6.0.0...v7.0.0 47 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Instapago 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 |

5 |

6 | Librería Instapago para PHP 7 |

8 |

9 | NOTA Los logos son propiedad de Instapago y Banesco, respectivamente. 10 |

11 | 12 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/instapago/instapago.svg?style=flat-square)](https://packagist.org/packages/instapago/instapago) 13 | [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/abr4xas/php-instapago/run-tests-pest.yml?style=flat-square)](https://github.com/abr4xas/php-instapago/actions?query=workflow%3ATests+branch%3Amaster) 14 | [![Total Downloads](https://img.shields.io/packagist/dt/instapago/instapago.svg?style=flat-square)](https://packagist.org/packages/instapago/instapago) 15 | 16 | ## instalación 17 | 18 | Primero, [`composer`](https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md) 19 | 20 | Luego: 21 | 22 | ``` 23 | $ composer require instapago/instapago 24 | $ composer dumpautoload -o // opcional 25 | ``` 26 | 27 | ### como usar 28 | 29 | >NOTA: Tomar en cuenta que esta nueva versión fue probada usando php8.X, no aseguro que funcione en algo menor a eso, en *teoría* debería pero no estoy seguro. 30 | 31 | ```php 32 | '200', 50 | 'description' => 'test', 51 | 'card_holder' => 'jon doe', 52 | 'card_holder_id' => '11111111', 53 | 'card_number' => '4111111111111111', 54 | 'cvc' => '123', 55 | 'expiration' => '12/2020', 56 | 'ip' => '127.0.0.1', 57 | ]; 58 | 59 | try{ 60 | 61 | $api = new Api('',''); 62 | 63 | $respuesta = $api->directPayment($paymentData); 64 | // hacer algo con $respuesta 65 | }catch(InstapagoException $e){ 66 | 67 | echo $e->getMessage(); // manejar el error 68 | 69 | }catch(InstapagoAuthException $e){ 70 | 71 | echo $e->getMessage(); // manejar el error 72 | 73 | }catch(InstapagoBankRejectException $e){ 74 | 75 | echo $e->getMessage(); // manejar el error 76 | 77 | }catch(InstapagoInvalidInputException $e){ 78 | 79 | echo $e->getMessage(); // manejar el error 80 | 81 | }catch(InstapagoTimeoutException $e){ 82 | 83 | echo $e->getMessage(); // manejar el error 84 | 85 | }catch(ValidationException $e){ 86 | 87 | echo $e->getMessage(); // manejar el error 88 | 89 | }catch(GenericException $e){ 90 | 91 | echo $e->getMessage(); // manejar el error 92 | 93 | } 94 | ``` 95 | 96 | Podemos revisar rápidamente si todo funciona correctamente escribiendo: 97 | 98 | ```bash 99 | $ php -S localhost:8000 100 | ``` 101 | 102 | ### tests 103 | 104 | ```bash 105 | composer test 106 | ``` 107 | 108 | ## Changelog 109 | 110 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 111 | 112 | ## Contributing 113 | 114 | Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. 115 | 116 | ## Security Vulnerabilities 117 | 118 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 119 | 120 | ## Credits 121 | 122 | - [Angel Cruz](https://github.com/abr4xas) 123 | - [All Contributors](../../contributors) 124 | 125 | ## License 126 | 127 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 128 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "instapago/instapago", 3 | "description": "Instapago is a technological solution designed for the market of electronic commerce (eCommerce) in Venezuela and Latin America, with the intention of offering a premium product category, which allows people and companies leverage their expansion capabilities, facilitating payment mechanisms for customers with a friendly integration into systems currently used.", 4 | "keywords": [ 5 | "Instapago", 6 | "instapago" 7 | ], 8 | "homepage": "https://github.com/abr4xas/instapago", 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Angel Cruz", 13 | "email": "angel@tepuilabs.dev", 14 | "role": "Developer" 15 | } 16 | ], 17 | "require": { 18 | "php": "^8.2|^8.3|^8.4", 19 | "guzzlehttp/guzzle": "^7.9.2" 20 | }, 21 | "require-dev": { 22 | "laravel/pint": "^1.18.3", 23 | "mockery/mockery": "^1.6", 24 | "pestphp/pest": "^3.7" 25 | }, 26 | "autoload": { 27 | "psr-4": { 28 | "Instapago\\Instapago\\": "src" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Instapago\\Instapago\\Tests\\": "tests" 34 | } 35 | }, 36 | "scripts": { 37 | "test": "vendor/bin/pest", 38 | "test-coverage": "vendor/bin/pest --coverage", 39 | "format": "vendor/bin/pint" 40 | }, 41 | "config": { 42 | "sort-packages": true, 43 | "allow-plugins": true 44 | }, 45 | "minimum-stability": "dev", 46 | "prefer-stable": true 47 | } 48 | -------------------------------------------------------------------------------- /pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "psr12", 3 | "rules": { 4 | "blank_line_before_statement": true, 5 | "method_argument_space": true, 6 | "single_trait_insert_per_statement": true, 7 | "types_spaces": { 8 | "space": "single" 9 | }, 10 | "align_multiline_comment": true, 11 | "array_indentation": true, 12 | "array_syntax": true, 13 | "concat_space": { 14 | "spacing": "one" 15 | }, 16 | "explicit_string_variable": true, 17 | "fully_qualified_strict_types": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Api.php: -------------------------------------------------------------------------------- 1 | payment('2', $fields); 46 | } catch (InstapagoAuthException | InstapagoBankRejectException | GenericException | InstapagoException | InstapagoInvalidInputException | InstapagoTimeoutException | ValidationException | GuzzleException $e) { 47 | return $e->getMessage(); 48 | } 49 | } 50 | 51 | /** 52 | * Crear un pago diferido o reservado. 53 | */ 54 | public function reservePayment($fields): array | string 55 | { 56 | try { 57 | return $this->payment('1', $fields); 58 | } catch (InstapagoAuthException | InstapagoBankRejectException | GenericException | InstapagoException | InstapagoInvalidInputException | InstapagoTimeoutException | ValidationException | GuzzleException $e) { 59 | return $e->getMessage(); 60 | } 61 | } 62 | 63 | /** 64 | * Completar Pago 65 | * Este método funciona para procesar un bloqueo o pre-autorización 66 | * para así procesarla y hacer el cobro respectivo. 67 | * 68 | * @throws ValidationException 69 | * @throws GenericException 70 | * @throws GuzzleException 71 | * @throws InstapagoTimeoutException 72 | */ 73 | public function completePayment(array $fields): array | string 74 | { 75 | (new Validator())->setValidations('release')->validate($fields); 76 | 77 | $fields = [ 78 | 'KeyID' => $this->keyId, //required 79 | 'PublicKeyId' => $this->publicKeyId, //required 80 | 'id' => $fields['id'], //required 81 | 'amount' => $fields['amount'], //required 82 | ]; 83 | 84 | $obj = $this->curlTransaction('complete', $fields, 'POST'); 85 | 86 | try { 87 | return $this->checkResponseCode($obj); 88 | } catch (InstapagoAuthException | InstapagoBankRejectException | GenericException | InstapagoException | InstapagoInvalidInputException $e) { 89 | return $e; 90 | } 91 | } 92 | 93 | /** 94 | * Información/Consulta de Pago 95 | * Este método funciona para procesar un bloqueo o pre-autorización 96 | * para así procesarla y hacer el cobro respectivo. 97 | * 98 | * @throws ValidationException 99 | * @throws GenericException 100 | * @throws GuzzleException 101 | * @throws InstapagoTimeoutException 102 | */ 103 | public function query(string $id_pago): array | string 104 | { 105 | (new Validator())->setValidations('query')->validate([ 106 | 'id' => $id_pago, 107 | ]); 108 | 109 | $fields = [ 110 | 'KeyID' => $this->keyId, //required 111 | 'PublicKeyId' => $this->publicKeyId, //required 112 | 'id' => $id_pago, //required 113 | ]; 114 | 115 | $obj = $this->curlTransaction('payment', $fields, 'GET'); 116 | 117 | try { 118 | return $this->checkResponseCode($obj); 119 | } catch (InstapagoAuthException | InstapagoBankRejectException | GenericException | InstapagoException | InstapagoInvalidInputException $e) { 120 | return $e->getMessage(); 121 | } 122 | } 123 | 124 | /** 125 | * Cancelar Pago 126 | * Este método funciona para cancelar un pago previamente procesado. 127 | * 128 | * @throws ValidationException 129 | */ 130 | public function cancel(string $id_pago): array | string 131 | { 132 | (new Validator())->setValidations('query')->validate([ 133 | 'id' => $id_pago, 134 | ]); 135 | 136 | $fields = [ 137 | 'KeyID' => $this->keyId, //required 138 | 'PublicKeyId' => $this->publicKeyId, //required 139 | 'id' => $id_pago, //required 140 | ]; 141 | 142 | try { 143 | return $this->curlTransaction('payment', $fields, 'DELETE'); 144 | } catch (GuzzleException | GenericException | InstapagoTimeoutException $e) { 145 | return $e->getMessage(); 146 | } 147 | } 148 | 149 | /** 150 | * Crear un pago. 151 | * 152 | * @param string $type tipo de pago ('1' o '0') 153 | * 154 | * @throws InstapagoAuthException 155 | * @throws InstapagoBankRejectException 156 | * @throws ValidationException 157 | * @throws GenericException 158 | * @throws InstapagoException 159 | * @throws InstapagoInvalidInputException 160 | * @throws InstapagoTimeoutException|GuzzleException 161 | */ 162 | private function payment(string $type, array $fields): array 163 | { 164 | (new Validator())->setValidations('payment')->validate($fields); 165 | 166 | $fields = [ 167 | 'KeyID' => $this->keyId, 168 | 'PublicKeyId' => $this->publicKeyId, 169 | 'amount' => $fields['amount'], 170 | 'description' => $fields['description'], 171 | 'cardHolder' => $fields['card_holder'], 172 | 'cardHolderId' => $fields['card_holder_id'], 173 | 'cardNumber' => $fields['card_number'], 174 | 'cvc' => $fields['cvc'], 175 | 'expirationDate' => $fields['expiration'], 176 | 'statusId' => $type, 177 | 'IP' => $fields['ip'], 178 | ]; 179 | 180 | $obj = $this->curlTransaction('payment', $fields, 'POST'); 181 | 182 | return $this->checkResponseCode($obj); 183 | } 184 | 185 | /** 186 | * Realiza Transacción 187 | * Efectúa y retornar una respuesta a un método de pago. 188 | * 189 | * @param $url string endpoint a consultar 190 | * @param $method string verbo http de la consulta 191 | * @return array resultados de la transacción 192 | * 193 | * @throws GenericException 194 | * @throws InstapagoTimeoutException 195 | * @throws GuzzleException 196 | */ 197 | private function curlTransaction(string $url, array $fields, string $method): array 198 | { 199 | $client = new Client([ 200 | 'base_uri' => 'https://api.instapago.com/', 201 | ]); 202 | 203 | $args = []; 204 | if (! in_array($method, ['GET', 'POST', 'DELETE'])) { 205 | throw new GenericException('Not implemented yet', 1); 206 | } 207 | $key = ($method == 'GET') ? 'query' : 'form_params'; 208 | 209 | $args[$key] = $fields; 210 | 211 | try { 212 | $request = $client->request($method, $url, $args); 213 | $body = $request->getBody()->getContents(); 214 | 215 | return json_decode($body, true); 216 | } catch (ConnectException $e) { 217 | throw new InstapagoTimeoutException('Cannot connect to api.instapago.com'); 218 | } 219 | } 220 | 221 | /** 222 | * Verifica y retornar el resultado de la transacción. 223 | * 224 | * @param array $obj datos de la consulta 225 | * @return array datos de transacción 226 | * 227 | * @throws InstapagoAuthException 228 | * @throws InstapagoBankRejectException 229 | * @throws GenericException 230 | * @throws InstapagoException 231 | * @throws InstapagoInvalidInputException 232 | */ 233 | private function checkResponseCode(array $obj): array 234 | { 235 | return match ($obj['code']) { 236 | '400' => throw new InstapagoInvalidInputException('Datos inválidos.'), 237 | '401' => throw new InstapagoAuthException('Error de autenticación.'), 238 | '403' => throw new InstapagoBankRejectException('Pago rechazado por el banco.'), 239 | '500' => throw new InstapagoException('Error interno del servidor.'), 240 | '503' => throw new InstapagoException('Error al procesar los parámetros de entrada.'), 241 | '201' => $this->getResponse($obj), 242 | default => throw new GenericException('Respuesta no implementada: ' . $obj['code']), 243 | }; 244 | } 245 | 246 | private function getResponse(array $obj): array 247 | { 248 | return [ 249 | 'code' => $obj['code'], 250 | 'message' => $obj['message'], 251 | 'voucher' => html_entity_decode($obj['voucher']), 252 | 'id_pago' => $obj['id'], 253 | 'reference' => $obj['reference'], 254 | 'original_response' => $obj, 255 | ]; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/Exceptions/GenericException.php: -------------------------------------------------------------------------------- 1 | . 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the “Software”), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | * 27 | * @author José Gómez <1josegomezr@gmail.com> 28 | * @license MIT License 29 | * @copyright 2016 José Gómez 30 | */ 31 | 32 | namespace Instapago\Instapago; 33 | 34 | use Instapago\Instapago\Exceptions\ValidationException; 35 | 36 | class Validator 37 | { 38 | private array $validations = []; 39 | 40 | public function setValidations(string $type): self 41 | { 42 | $rules = $this->getValidationRules(); 43 | $this->validations = $rules[$type] ?? []; 44 | 45 | return $this; 46 | } 47 | 48 | /** 49 | * @throws ValidationException 50 | */ 51 | public function validate(array $fields): void 52 | { 53 | $errors = []; 54 | foreach ($this->validations as $key => $filters) { 55 | if (! $this->_validation($fields[$key] ?? null, $filters)) { 56 | $errors[$key] = "Invalid value for {$key}"; 57 | } 58 | } 59 | 60 | if ($errors) { 61 | throw new ValidationException(json_encode($errors)); 62 | } 63 | } 64 | 65 | private function _validation(mixed $value, array $filters): bool 66 | { 67 | $filter = $filters[0]; 68 | $options = $filter === FILTER_VALIDATE_REGEXP ? ['options' => ['regexp' => $filters[1]]] : []; 69 | 70 | return filter_var($value, $filter, $options) !== false; 71 | } 72 | 73 | private function getValidationRules(): array 74 | { 75 | return [ 76 | 'payment' => [ 77 | 'amount' => [FILTER_VALIDATE_FLOAT], 78 | 'description' => [FILTER_VALIDATE_REGEXP, '/^(.{0,140})$/'], 79 | 'card_holder' => [FILTER_VALIDATE_REGEXP, '/^([a-zA-ZáéíóúñÁÉÍÓÚÑ\ ]+)$/'], 80 | 'card_holder_id' => [FILTER_VALIDATE_REGEXP, '/^(\d{5,8})$/'], 81 | 'card_number' => [FILTER_VALIDATE_REGEXP, '/^(\d{16})$/'], 82 | 'cvc' => [FILTER_VALIDATE_INT], 83 | 'expiration' => [FILTER_VALIDATE_REGEXP, '/^(\d{2})\/(\d{4})$/'], 84 | 'ip' => [FILTER_VALIDATE_IP], 85 | ], 86 | 'release' => [ 87 | 'amount' => [FILTER_VALIDATE_FLOAT], 88 | 'id' => [FILTER_VALIDATE_REGEXP, '/^([0-9a-f]{8})\-([0-9a-f]{4})\-([0-9a-f]{4})\-([0-9a-f]{4})\-([0-9a-f]{12})$/'], 89 | ], 90 | 'query' => [ 91 | 'id' => [FILTER_VALIDATE_REGEXP, '/^([0-9a-f]{8})\-([0-9a-f]{4})\-([0-9a-f]{4})\-([0-9a-f]{4})\-([0-9a-f]{12})$/'], 92 | ], 93 | ]; 94 | } 95 | } 96 | --------------------------------------------------------------------------------