Giter Club home page Giter Club logo

gerencianet / gn-api-sdk-php Goto Github PK

View Code? Open in Web Editor NEW
83.0 19.0 47.0 423 KB

SDK em PHP integrada às APIs da Gerencianet preparada para emissão de cobranças Pix com QR Code e Pix Copia e Cola, split/divisão de Pix, boletos, carnês, cartão de crédito, assinatura, link de pagamento, marketplance, iniciação de pagamento Pix via Open Finance, pagamento de boletos, dentre outras funcionalidades.

Home Page: https://dev.gerencianet.com.br/docs/instalacao-sdk-php

License: MIT License

PHP 100.00%
pix boleto carne cartao-de-credito marketplace assinatura link-de-pagamento billet card split

gn-api-sdk-php's People

Contributors

ceciliadeveza avatar claudsonm avatar dannielhugo avatar filipemata avatar franciscotfmc avatar giovani-felipe avatar guilhermecotagn avatar mariopacio avatar mpmnicolau avatar sadycoimbraefi avatar talitacampos avatar thiagogresende avatar whintergoncalves avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gn-api-sdk-php's Issues

Incluir sem composer

Afinal qual arquivo devo incluir caso não deseje utilizar o composer e colocar a sdk direto no diretório?

QR estático

Como gerar cobranças que gerem qr codes estáticos e que possibilitem o uso de webhooks/callbacks? E que tragam todas as informações do pagador. Grato, Caio!

Problema de Invalid resource type: boolean

Ola, uso este sdk em meus módulos mas muitos clientes estão com problema que ocorre ocasionalmente, depois que gera a cobrança e vai realizar o pagamento gera o erro a seguir:
Invalid resource type: boolean

Buscando vi que este erro ocorre no Guzzle que não permite envio de inteiros e boleanos no corpo, e o sdk usa Guzzle, já viram este problema ou se já foi corrigido?

guzzle/guzzle#628

Mensagem de erro na resposta da SDK

Bom dia!

Gostaria de saber como obter uma mensagem de erro mais descritiva ao utilizar a SDK.

Por exemplo, o erro de quando não utilizo uma das chaves pix do Gerencianet (caso eu insira uma chave qualquer propositalmente, apenas para fins de testar o erro),

O que ele vai me retornar, pela SDK , por meio do throw é: "Bad request", apenas.

Trecho do código utilizado: (o mesmo do exemplo)

} catch (GerencianetException $e) {
    print_r($e->code);
    print_r($e->error);
    print_r($e->errorDescription);

    throw new Error($e->error);
} catch (Exception $e) {
    throw new Error($e->getMessage());
}

Porém, caso eu vá na classe "Request" da SDK, localizada em "vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Request.php"

e alterar, no método send, o trecho do código para:

} catch (ClientException $e) {
            throw $e; // Linnha adicionada por mim
            throw new AuthorizationException($e->getResponse()->getStatusCode(),
                       $e->getResponse()->getReasonPhrase(),
                       $e->getResponse()->getBody());
        } catch (ServerException $se) {
            throw new GerencianetException($se->getResponse()->getBody());
        }

Eu consigo obter uma mensagem de erro mais detalhada, como se estivesse fazendo a requisição sem o uso da SDK. Como obter essa mensagem de erro por meio da SDK sem essa alteração de código que fiz?

OBS: Estou utilizando Laravel 4.2

Obrigado.

Remover subscription com status NEW

Pessoal,
Cheguei a testar junto ao Tiago, por telefone, e verificamos que ao tentar dar um hit em /v1/subscription/:id/cancel e este id estiver com status NEW, ele não é cancelado e é retornado um erro alertando que este subscription não existe.
print
print2
Mesmo como verificamos que isso não afeta em nada para a Gerencianet, é um incômodo ter que fazer mais uma validação no sistema para verificar status NEW como se fosse Cancelado.

Como calcular o valor recebido?

Olá boa tarde pessoal?

Sei que talvez aqui não seja o melhor lugar para pedir isso.. mas tentei pelo chat de vocês e não consegui
Estou querendo gerar relatórios automáticos em nosso sistema.. pelo que olhei não consegui via API saber o valor recebido pela transação (valor transacionado - taxas pagas)

Então tentei criar uma função para fazer esse cálculo mas não deu certo.. por acaso tens como ajudar?
Exemplo:

Um pagamento com valor transacional de R$ 516.93 e foi parcelado em 10x
Com as taxas padrão de 4,99% + 0,29 e 1,99% a.m
O valor recebido foi R$ 432,58 
A diferença é de R$ 84,35

Aqui está a função que tentamos criar para calcular isso 👇

calculaJurosGerenciaNet(516.93, 10); 
function calculaJurosGerenciaNet(float $valor, int $parcelamento) {
      $parcelas = [];
      $recebido_total = 0;

      // Valor - taxa transacional 4,99% + 0,29
      $taxa = (float) number_format(($valor / 100 * 4.99) + 0.29, 2);
      $valor_menos_taxa = (float) number_format($valor - $taxa, 2);

      // Valor - taxa antecipacao 1,99%
      $valor_parcela = (float) number_format($valor_menos_taxa / $parcelamento, 2);
      $valor_liq_parcela = (float) number_format($valor_parcela - ($valor_parcela / 100 * 1.99), 2);

      for($i = 1; $i <= $parcelamento; $i++) {

          $juros_parcela = $i * 1.99;
          $recebido_parcela = (float) number_format($valor_liq_parcela - ($valor_liq_parcela / 100 * $juros_parcela), 2);

          $parcelas[] = [
              'parcela' => $i,
              'liquido_parcela' => $recebido_parcela,
              'juros' => $juros_parcela
          ];

          $recebido_total += $recebido_parcela;
      }

      dd($recebido_total, ($valor - $recebido_total));
}

Erro ao gerar pagamento

property_does_not_existsArray ( [property] => id [message] => A propriedade [id] informada não existe. )

Problema ao instalar pacote via composer

Olá! Fui instalar o pacote via composer e retornou um erro de dependências:

Problem 1
- gerencianet/gerencianet-sdk-php 1.0.0 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.1 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.10 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.11 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.12 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.2 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.3 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.4 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.5 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.6 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.7 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- gerencianet/gerencianet-sdk-php 1.0.9 requires codeclimate/php-test-reporter ^0.1.2 -> satisfiable by codeclimate/php-test-reporter[v0.1.2].
- Conclusion: don't install codeclimate/php-test-reporter v0.1.2
- Installation request for gerencianet/gerencianet-sdk-php ^1.0 -> satisfiable by gerencianet/gerencianet-sdk-php[1.0.0, 1.0.1, 1.0.10, 1.0.11, 1.0.12, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.9].

O que está acontecendo?

Guzzle v7 é imcompatível

Instalar via composer require gerencianet/gerencianet-sdk-php gera um erro se o pacote guzzlehttp/guzzle já estiver presente em composer.lock com versão superior à v7.

A limitação de usar apenas v6 pode gerar problemas no longo prazo ou quando entrar em EOL.

A solução é o downgrade da versão do Guzzle até as dependências serem ajustadas.

Guzzle Version Guidance.

como identificar um retorno de erro?

Olá, estou implementando o Gerencianet em nosso sistema para a geração dos boletos. Estamos ultilizando o API com PHP.

Porém minha dúvida é como posso saber se o retorno ocorrido foi o 200? Ou seja se tudo ocorreu bem?

Pois precisava no PHP dizer se caso o retorno não tenha sido 200 para gerar um alerta e/ou refazer o processo.

Podem me ajudar com isso?

Falta opção de timeout para as request

Por padrão o Guzzle espera indefinidamente a request terminar. Se há algum problema na rede, ou nos servidores, da forma que está não é possível para a aplicação tomar alguma decisão quando a resposta demora muito para vir. Em geral o servidor web ou o FPM vai interromper a execução do código no meio e retornar um HTTP 500.
Seria legal se houvesse um timeout padrão, ou melhor ainda, se fosse possível configurar o timeout.

Imgino que pela estrutura do sdk teria que ser algo como:

// na inicialização
$Api = new Gerencianet([
	'client_id' => $apiKeys['client_id'],
	'client_secret' => $apiKeys['client_secret'],
	'sandbox' => true,
	'timeout' => 30 // segundos
]);

// ou
$Api->setTimeout(30);
$Api->createCharge([], $body);

Forçando versão 7.4 do guzzlehttp/guzzle

Olá,

Desde a versão 5.1.2 a dependência guzzlehttp/guzzle está declarada de forma específica para a versão 7.4:

"guzzlehttp/guzzle": "7.4"

Onde o correto deveria ser:

"guzzlehttp/guzzle": "^7.4"

Call to undefined method GuzzleHttp\Utils::chooseHandler()

Olá

Recentemente o SDK presente em uma de minhas aplicações parou misteriosamente de pegar rs, e somente em uma delas, apontando um erro aparentemente impossível.

Bibliotecas que tenho instalado:

  • gerencianet/gerencianet-sdk-php 4.1.1
  • guzzlehttp/guzzle 7.4.1
  • guzzlehttp/promises 1.5.1
  • guzzlehttp/psr7 2.1.0
  • psr/http-client 1.0.1
  • psr/http-factory 1.0.1
  • psr/http-message 1.0.1
  • qualisafe/temsaude dev-main e9cec1f
  • ralouphie/getallheaders 3.0.3
  • symfony/deprecation-contracts v2.5.0

Erro que estou recebendo
Fatal error: Uncaught Error: Call to undefined method GuzzleHttp\Utils::chooseHandler() in /home/qualisafe/dev.qualisafeseguros.com.br/bot-cartao-credito/vendor/guzzlehttp/guzzle/src/functions.php:61 Stack trace: #0 /home/qualisafe/dev.qualisafeseguros.com.br/painel-adm/vendor/guzzlehttp/guzzle/src/HandlerStack.php(42): GuzzleHttp\choose_handler() #1 /home/qualisafe/dev.qualisafeseguros.com.br/painel-adm/vendor/guzzlehttp/guzzle/src/Client.php(65): GuzzleHttp\HandlerStack::create() #2 /home/qualisafe/dev.qualisafeseguros.com.br/bot-cartao-credito/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Request.php(36): GuzzleHttp\Client->__construct(Array) #3 /home/qualisafe/dev.qualisafeseguros.com.br/bot-cartao-credito/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Auth.php(27): Gerencianet\Request->__construct(Array) #4 /home/qualisafe/dev.qualisafeseguros.com.br/bot-cartao-credito/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/ApiRequest.php(15): Gerencianet\Auth->__construct(Array) #5 /home/qualisafe/de in /home/qualisafe/dev.qualisafeseguros.com.br/bot-cartao-credito/vendor/guzzlehttp/guzzle/src/functions.php on line 61

Esse erro começou a ocorrer hoje de manhã, após ter presenciado instabilidade no ambiente de homologação ontem a tarde. O que torna o erro aparentemente impossível, seria o conteúdo do arquivo vendor/guzzle/guzzlehttp/src/Utils.php

<?php

namespace GuzzleHttp;

use GuzzleHttp\Exception\InvalidArgumentException;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Handler\CurlMultiHandler;
use GuzzleHttp\Handler\Proxy;
use GuzzleHttp\Handler\StreamHandler;
use Psr\Http\Message\UriInterface;

final class Utils
{
    /**
     * Debug function used to describe the provided value type and class.
     *
     * @param mixed $input
     *
     * @return string Returns a string containing the type of the variable and
     *                if a class is provided, the class name.
     */
    public static function describeType($input): string
    {
        switch (\gettype($input)) {
            case 'object':
                return 'object(' . \get_class($input) . ')';
            case 'array':
                return 'array(' . \count($input) . ')';
            default:
                \ob_start();
                \var_dump($input);
                // normalize float vs double
                /** @var string $varDumpContent */
                $varDumpContent = \ob_get_clean();

                return \str_replace('double(', 'float(', \rtrim($varDumpContent));
        }
    }

    /**
     * Parses an array of header lines into an associative array of headers.
     *
     * @param iterable $lines Header lines array of strings in the following
     *                        format: "Name: Value"
     */
    public static function headersFromLines(iterable $lines): array
    {
        $headers = [];

        foreach ($lines as $line) {
            $parts = \explode(':', $line, 2);
            $headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null;
        }

        return $headers;
    }

    /**
     * Returns a debug stream based on the provided variable.
     *
     * @param mixed $value Optional value
     *
     * @return resource
     */
    public static function debugResource($value = null)
    {
        if (\is_resource($value)) {
            return $value;
        }
        if (\defined('STDOUT')) {
            return \STDOUT;
        }

        return \GuzzleHttp\Psr7\Utils::tryFopen('php://output', 'w');
    }

    /**
     * Chooses and creates a default handler to use based on the environment.
     *
     * The returned handler is not wrapped by any default middlewares.
     *
     * @throws \RuntimeException if no viable Handler is available.
     *
     * @return callable(\Psr\Http\Message\RequestInterface, array): \GuzzleHttp\Promise\PromiseInterface Returns the best handler for the given system.
     */
    public static function chooseHandler(): callable
    {
        $handler = null;
        if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) {
            $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
        } elseif (\function_exists('curl_exec')) {
            $handler = new CurlHandler();
        } elseif (\function_exists('curl_multi_exec')) {
            $handler = new CurlMultiHandler();
        }

        if (\ini_get('allow_url_fopen')) {
            $handler = $handler
                ? Proxy::wrapStreaming($handler, new StreamHandler())
                : new StreamHandler();
        } elseif (!$handler) {
            throw new \RuntimeException('GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.');
        }

        return $handler;
    }

    /**
     * Get the default User-Agent string to use with Guzzle.
     */
    public static function defaultUserAgent(): string
    {
        return sprintf('GuzzleHttp/%d', ClientInterface::MAJOR_VERSION);
    }

    /**
     * Returns the default cacert bundle for the current system.
     *
     * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
     * If those settings are not configured, then the common locations for
     * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
     * and Windows are checked. If any of these file locations are found on
     * disk, they will be utilized.
     *
     * Note: the result of this function is cached for subsequent calls.
     *
     * @throws \RuntimeException if no bundle can be found.
     *
     * @deprecated Utils::defaultCaBundle will be removed in guzzlehttp/guzzle:8.0. This method is not needed in PHP 5.6+.
     */
    public static function defaultCaBundle(): string
    {
        static $cached = null;
        static $cafiles = [
            // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
            '/etc/pki/tls/certs/ca-bundle.crt',
            // Ubuntu, Debian (provided by the ca-certificates package)
            '/etc/ssl/certs/ca-certificates.crt',
            // FreeBSD (provided by the ca_root_nss package)
            '/usr/local/share/certs/ca-root-nss.crt',
            // SLES 12 (provided by the ca-certificates package)
            '/var/lib/ca-certificates/ca-bundle.pem',
            // OS X provided by homebrew (using the default path)
            '/usr/local/etc/openssl/cert.pem',
            // Google app engine
            '/etc/ca-certificates.crt',
            // Windows?
            'C:\\windows\\system32\\curl-ca-bundle.crt',
            'C:\\windows\\curl-ca-bundle.crt',
        ];

        if ($cached) {
            return $cached;
        }

        if ($ca = \ini_get('openssl.cafile')) {
            return $cached = $ca;
        }

        if ($ca = \ini_get('curl.cainfo')) {
            return $cached = $ca;
        }

        foreach ($cafiles as $filename) {
            if (\file_exists($filename)) {
                return $cached = $filename;
            }
        }

        throw new \RuntimeException(
            <<< EOT
No system CA bundle could be found in any of the the common system locations.
PHP versions earlier than 5.6 are not properly configured to use the system's
CA bundle by default. In order to verify peer certificates, you will need to
supply the path on disk to a certificate bundle to the 'verify' request
option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
need a specific certificate bundle, then Mozilla provides a commonly used CA
bundle which can be downloaded here (provided by the maintainer of cURL):
https://curl.haxx.se/ca/cacert.pem. Once
you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
ini setting to point to the path to the file, allowing you to omit the 'verify'
request option. See https://curl.haxx.se/docs/sslcerts.html for more
information.
EOT
        );
    }

    /**
     * Creates an associative array of lowercase header names to the actual
     * header casing.
     */
    public static function normalizeHeaderKeys(array $headers): array
    {
        $result = [];
        foreach (\array_keys($headers) as $key) {
            $result[\strtolower($key)] = $key;
        }

        return $result;
    }

    /**
     * Returns true if the provided host matches any of the no proxy areas.
     *
     * This method will strip a port from the host if it is present. Each pattern
     * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
     * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
     * "baz.foo.com", but ".foo.com" != "foo.com").
     *
     * Areas are matched in the following cases:
     * 1. "*" (without quotes) always matches any hosts.
     * 2. An exact match.
     * 3. The area starts with "." and the area is the last part of the host. e.g.
     *    '.mit.edu' will match any host that ends with '.mit.edu'.
     *
     * @param string   $host         Host to check against the patterns.
     * @param string[] $noProxyArray An array of host patterns.
     *
     * @throws InvalidArgumentException
     */
    public static function isHostInNoProxy(string $host, array $noProxyArray): bool
    {
        if (\strlen($host) === 0) {
            throw new InvalidArgumentException('Empty host provided');
        }

        // Strip port if present.
        [$host] = \explode(':', $host, 2);

        foreach ($noProxyArray as $area) {
            // Always match on wildcards.
            if ($area === '*') {
                return true;
            }

            if (empty($area)) {
                // Don't match on empty values.
                continue;
            }

            if ($area === $host) {
                // Exact matches.
                return true;
            }
            // Special match if the area when prefixed with ".". Remove any
            // existing leading "." and add a new leading ".".
            $area = '.' . \ltrim($area, '.');
            if (\substr($host, -(\strlen($area))) === $area) {
                return true;
            }
        }

        return false;
    }

    /**
     * Wrapper for json_decode that throws when an error occurs.
     *
     * @param string $json    JSON data to parse
     * @param bool   $assoc   When true, returned objects will be converted
     *                        into associative arrays.
     * @param int    $depth   User specified recursion depth.
     * @param int    $options Bitmask of JSON decode options.
     *
     * @return object|array|string|int|float|bool|null
     *
     * @throws InvalidArgumentException if the JSON cannot be decoded.
     *
     * @link https://www.php.net/manual/en/function.json-decode.php
     */
    public static function jsonDecode(string $json, bool $assoc = false, int $depth = 512, int $options = 0)
    {
        $data = \json_decode($json, $assoc, $depth, $options);
        if (\JSON_ERROR_NONE !== \json_last_error()) {
            throw new InvalidArgumentException('json_decode error: ' . \json_last_error_msg());
        }

        return $data;
    }

    /**
     * Wrapper for JSON encoding that throws when an error occurs.
     *
     * @param mixed $value   The value being encoded
     * @param int   $options JSON encode option bitmask
     * @param int   $depth   Set the maximum depth. Must be greater than zero.
     *
     * @throws InvalidArgumentException if the JSON cannot be encoded.
     *
     * @link https://www.php.net/manual/en/function.json-encode.php
     */
    public static function jsonEncode($value, int $options = 0, int $depth = 512): string
    {
        $json = \json_encode($value, $options, $depth);
        if (\JSON_ERROR_NONE !== \json_last_error()) {
            throw new InvalidArgumentException('json_encode error: ' . \json_last_error_msg());
        }

        /** @var string */
        return $json;
    }

    /**
     * Wrapper for the hrtime() or microtime() functions
     * (depending on the PHP version, one of the two is used)
     *
     * @return float UNIX timestamp
     *
     * @internal
     */
    public static function currentTime(): float
    {
        return (float) \function_exists('hrtime') ? \hrtime(true) / 1e9 : \microtime(true);
    }

    /**
     * @throws InvalidArgumentException
     *
     * @internal
     */
    public static function idnUriConvert(UriInterface $uri, int $options = 0): UriInterface
    {
        if ($uri->getHost()) {
            $asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
            if ($asciiHost === false) {
                $errorBitSet = $info['errors'] ?? 0;

                $errorConstants = array_filter(array_keys(get_defined_constants()), static function (string $name): bool {
                    return substr($name, 0, 11) === 'IDNA_ERROR_';
                });

                $errors = [];
                foreach ($errorConstants as $errorConstant) {
                    if ($errorBitSet & constant($errorConstant)) {
                        $errors[] = $errorConstant;
                    }
                }

                $errorMessage = 'IDN conversion failed';
                if ($errors) {
                    $errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
                }

                throw new InvalidArgumentException($errorMessage);
            }
            if ($uri->getHost() !== $asciiHost) {
                // Replace URI only if the ASCII version is different
                $uri = $uri->withHost($asciiHost);
            }
        }

        return $uri;
    }

    /**
     * @internal
     */
    public static function getenv(string $name): ?string
    {
        if (isset($_SERVER[$name])) {
            return (string) $_SERVER[$name];
        }

        if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== false && $value !== null) {
            return (string) $value;
        }

        return null;
    }

    /**
     * @return string|false
     */
    private static function idnToAsci(string $domain, int $options, ?array &$info = [])
    {
        if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) {
            return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info);
        }

        throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old');
    }
}

Tentei com ambas as versões 7.0 e 7.4, e nenhuma das duas resolveu meu problema, estou utilizando o PHP 7.4.35, e na outra aplicação que possuo, o SDK funciona normalmente. Já limpei o cache do composer diversas e re-instalei as libs várias vezes também.

Poderiam me dar uma ajuda com isso?

Curl 28 - Criação de Charge One Step

Ao criar um boleto, não é possível obter resposta da requisição, mas o boleto é criado no painel. O boleto foi criado no ambiente de homologação. Seguindo os passos da documentação: Criação de Boleto em One Step (Um passo)

string(196) "cURL error 28: Operation timed out after 30001 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://sandbox.gerencianet.com.br/v1/charge/one-step"

Undefined variable $message

Sempre quando acontece alguma Exception está retornando essa mensagem:

PHP version: 8.1.17

ErrorException {#3444
  #message: "Undefined variable $message"
  #code: 0
  #line: 48
  #severity: E_WARNING
}

Está indicando que a variável $message aqui na linha 48 está fora do escopo:

private function apiReturns($error, $code){
if (isset($error['message'])) {
$message = $error['message'];
$this->code = $code;
$this->errorDescription = $error['message'];
} else if (isset($error['error'])) { // error API Cobranças
$message = isset($error['error_description']['message']) ? $error['error_description']['message'] : $error['error_description'];
$this->code = $error['code'];
$this->error = $error['error'];
$this->errorDescription = $error['error_description'];
} else if (isset($error['type'])) { // error API cobv e reports
$this->code = $error['status'];
$this->error = $error['title'] . ". " . $error['detail'];
$this->errorDescription = $error['violacoes'];
} else { // error API Pix
$message = (isset($error['erros']['mensagem']) ? $error['mensagem'] . ": " . $error['caminho'] . " " . $error['erros']['mensagem'] : $error['mensagem'] . ": " . $error['mensagem']);
$this->code = $code;
$this->error = (isset($error['erros']) ? $error['mensagem'] : $error['nome']);
$this->errorDescription = (isset($error['erros']) ? $error['erros'] : $error['mensagem']);
}
parent::__construct($message, $this->code);
}

Inicializando $message = null; dentro do escopo do método deverá solucionar esta questão.
Então posso enviar um pull request sobre isso? 👨‍💻

Problema ao criar cobrança imediata

Venho obtendo o seguinte erro ao criar uma cobrança imediata usando o PHP8+Codeigniter4. Pela ordem, estou criando a chave Pix, o WebHook da chave e quando eu crio a cobrança, recebo essa mensagem de que a chave não pertence à Gerencianet. Porém, quando eu consulto a chave criada, ela se encontra lá.

{
    "title": "GuzzleHttp\\Exception\\ClientException",
    "type": "GuzzleHttp\\Exception\\ClientException",
    "code": 400,
    "message": "Client error: `POST https://api-pix.gerencianet.com.br/v2/cob` resulted in a `400 Bad Request` response:\n{\"nome\":\"chave_invalida\",\"mensagem\":\"A chave informada não faz referência à conta Gerencianet autenticada\"}\n",
    "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php",
    "line": 113,
    "trace": [
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/guzzle/src/Middleware.php",
            "line": 69,
            "function": "create",
            "class": "GuzzleHttp\\Exception\\RequestException",
            "type": "::"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 204,
            "function": "GuzzleHttp\\{closure}",
            "class": "GuzzleHttp\\Middleware",
            "type": "::"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 153,
            "function": "callHandler",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "::"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/TaskQueue.php",
            "line": 48,
            "function": "GuzzleHttp\\Promise\\{closure}",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "::"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 248,
            "function": "run",
            "class": "GuzzleHttp\\Promise\\TaskQueue",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 224,
            "function": "invokeWaitFn",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 269,
            "function": "waitIfPending",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 226,
            "function": "invokeWaitList",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/promises/src/Promise.php",
            "line": 62,
            "function": "waitIfPending",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/vendor/guzzlehttp/guzzle/src/Client.php",
            "line": 187,
            "function": "wait",
            "class": "GuzzleHttp\\Promise\\Promise",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/app/Controllers/QR.php",
            "line": 349,
            "function": "request",
            "class": "GuzzleHttp\\Client",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/system/CodeIgniter.php",
            "line": 877,
            "function": "index",
            "class": "App\\Controllers\\QR",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/system/CodeIgniter.php",
            "line": 416,
            "function": "runController",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/system/CodeIgniter.php",
            "line": 324,
            "function": "handleRequest",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        },
        {
            "file": "/var/www/xyz.com/public_html/public/index.php",
            "line": 37,
            "function": "run",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        }
    ]
}

Se isso não for um bug então não sei o que é, pois esse problema ocorre de forma intermitente.

Grato, Caio.

Possibilidade de Fraude nos Pagamentos

Olá, estou analisando e fazendo a implementação da nova API GN e identifiquei uma possibilidade de burlar o esquema de recebimento de qualquer meio de pagamento que for gerado no site, devido a falta de um relacionamento entre o Client ID, Client Secret e o Domínio quer ira roda a API.

Hoje quando eu crio uma nova Aplicação para gerar um novo CID e CS no painel de APIs da GN eu não informo nenhum domínio do qual rodará a API, é deveria ter essa informação, somente para geração de CID e CS da Produção, no Playground deve continuar sem mesmo para ter a possibilidade de testar a Aplicação em qualquer lugar, porem a produção tem que esta limitada a executar somente em um único domínio.

Uma forma de burlar isso e eu identificar um site que usa os sistema de pagamento da GerenciaNet, e descobri se eles utilizam o banco de dados para armazenar o CID e CS ou se estão salvando essa informação em um arquivo .json, nem todos os desenvolvedores fazem restrição de acesso externo aos arquivos .json da hospedagem e alguns em algum momento recebe uma invasão em sua hospedagem.

Tendo conhecimento do local de armazenamento dessas informações o cracker poderia simplesmente substituir pelo CID e SC dele e todo pagamento processado será creditado na conta GN do cracker, sem que o real destinatário do crédito perceba até que seus clientes comecem a reclamar que estão pagaram e não esta sendo confirmado seus pagamentos. até lá o dinheiro já foi tirando da conta GN e cracker desaparecido do mapa...

Se existir uma relação entre os CIDs, SCs e o domínio da aplicação isso jamais poderia acontecer tendo em vista que o cracker teria que invadir a conta GN do proprietário para trocar o domínio, isso é muito menos provável de conseguir.

Eu trabalho também com outras APIs, e se não me engano vi esse nível de segurança em uma delas.

Parece também que existe essa API para Android e iOS, não vi como funciona, mas já desenvolvi projetos nas duas plataformas e acredito que para esse esquema se tornar válido para elas tb, o APP deveria comunicar com uma WebService para processar o pagamento, e seria o domínio dessa WebService que estaria relacionado aos CIDs e SCs deixando o APP mesmo só como um intermediador, depois com mais tempo vou da uma olhada nessa API pra Android e iOS e ver como funciona.

Eu já trabalhei uma agencia que tinha um gerente preguiçoso que não atualizava as versões dos WordPress instalados nas sub-contas de um dedicado, só no tempo que trabalhei lá vi esse dedicado ser hackeado 3 vezes por causa das falhas de segurança não corrigida por falta de atualizar as versões, mais de 200 sites prejudicados, em algum deles os cara trocava arquivo e deixava mensagens, com isso já da pra percebe que tiveram acesso ao FTP das contas e provavelmente os bancos de dados, imagine que desses 200 sites, 50 fossem lojas virtuais rodando a API da GN, o cara substituiria os CIDs e SCs e por alguns dias iria faturar bem nas costas dos outros...

API não está no padrão da RFC 7231

Por algum motivo, a API da Gerencianet não está no padrão da RFC 7231 e, entre outras coisas, costuma retornar códigos de status dentro da resposta, inclusive misturando 200 do HTTP com códigos de erro customizados...

Outro problema é que o backend da Gerencianet em si só entende 200 como resposta de suscesso na URL de notificação e o status 204 No Content são considerados como erros no painel da plataforma...

A padronização da API de acordo com a RFC e possível criação de webhooks autenticados seriam ideais (podendo enviar os dados do endpoint GET /v1/charge/:id diretamente ao invés da forma atual de mandar notification).

QR reutilizável

Como posso/poderia configurar o atributo Point of Initiation Method (PIM) através da API da Gerencianet? Gostaria de poder configurar o valor 11 para QR reutilizável e 12 para não reutilizável. Grato, Caio!

Ao criar um pix

Notice: Undefined index: error_description in /home/meuprojeto/public_html/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Exception/GerencianetException.php on line 21

Notice: Undefined index: error in /home/meuprojeto/public_html/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Exception/GerencianetException.php on line 27

Notice: Undefined index: error_description in /home/meuprojeto/public_html/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Exception/GerencianetException.php on line 28

Notice: Undefined index: code in /home/meuprojeto/public_html/vendor/gerencianet/gerencianet-sdk-php/src/Gerencianet/Exception/GerencianetException.php on line 30

Esse erro sumiu quando atualizei a SDK, vi que teve uma atualização em um arquivo há 26 dias, mas pelo que notei só foi fixado esse alerta, a exceção não retorna nenhum erro.

Isso é quando cria uma chave ou gera um pix, não é sempre que aparece essa mensagem, e quando não aparece o PIX ou a chave são gerados certinho ou seja o código está funcionando, é só algumas exceções.

Guzzlehttp muito desatualizado

Pessoal,

Quando rodei o composer require do SDK de vocês deu conflito com o Guzzle que eu estou rodando no projeto (6.0.2). Percebi que você usam o 5.3.0, existe alguma previsão de update?

Att.

Callback para confirmação de pagamento - Como pegar o token?

Bom dia!

Estou tendo dificuldades com o callback de pagamento do boleto, aquele payload que a Gerencianet envia para a minha URL de notificação com o status de pagamento para que meu sistema possa atualizar seu status interno.

Mais especificamente, isto: https://dev.gerencianet.com.br/docs/notificacoes-recebendo#section-2-consultando-detalhes-de-uma-notifica-o

A dificuldade que estou tendo é em pegar o Token da notificação, uma vez que preciso dele para solicitar o status de pagamento na API do GerenciaNet.

O Payload de notificação (callback) enviado pela GerenciaNet possui o seguinte formato:

$_POST:

array(2) {
    ["code"] =>  int(200)
    ["data"] =>  array(2) {
        [0] => array(6) {
            ["id"] => int(1)
            ["type"] => string(6) "charge"
            ["custom_id"] => string(2) "11"
            ["status"] => array(2) {
                ["current"] =>   string(3) "new"
                ["previous"] =>   null
            }
            ["identifiers"] => array(1) {
                    ["charge_id"] =>   int(140609999)
            }
            ["created_at"] => string(19) "2019-02-28 19:15:33"
        }
        [1] => array(6) {
            ["id"] => int(2)
            ["type"] => string(6) "charge"
            ["custom_id"] => string(2) "11"
            ["status"] => array(2) {
                ["current"] =>   string(7) "waiting"
                ["previous"] =>   string(3) "new"
            }
            ["identifiers"] => array(1) {
                    ["charge_id"] =>   int(140609999)
            }
            ["created_at"] => string(19) "2019-02-28 19:15:33"
        }
  }
}

Como pode ver, não tem o Token que preciso para consultar na API o status daquele boleto:
2019-03-01_08-33-08

Uma informação adicional que pode ser útil, quando crio o boleto, minha URL de notificação é gerada desta forma:
meusite.com?invoiceid=ID&hash=HASH

Erro Botão de Boleto

Estou tentando pagar via botão de boleto e esta gerando o seguinte erro:

Não foi possível finalizar sua solicitação. Por favor, entre em contato com o suporte Gerencianet.

Pix Endpoints - Cobranças com vencimento (COBV)

Olá pessoal. 🙋🏻‍♂️

Estou utilizando esse sdk para criar a cobrança Pix com data de vencimento.

Foi então que notei que está faltando esses endpoints:

PUT /v2/cobv/:txid
PATCH /v2/cobv/:txid
GET /v2/cobv
GET /v2/cobv/:txid

Já adicionei eles no src/Gerencianet/config.json

Então posso enviar um pull request?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.