<commit_before><?php

namespace Shoperti\PayMe\Gateways\SrPago;

use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\TransferException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Shoperti\PayMe\ErrorCode;
use Shoperti\PayMe\Gateways\AbstractGateway;
use Shoperti\PayMe\Response;
use Shoperti\PayMe\Status;
use Shoperti\PayMe\Support\Arr;

class SrPagoGateway extends AbstractGateway
{
    /**
     * Production endpoint.
     *
     * @var string
     */
    protected $endpoint = 'https://api.srpago.com/v1';

    /**
     * Sandbox endpoint.
     *
     * @var string
     */
    protected $sandboxEndpoint = 'https://sandbox-api.srpago.com/v1';

    /**
     * Gateway display name.
     *
     * @var string
     */
    protected $displayName = 'srpago';

    /**
     * API connection token.
     *
     * @var string
     */
    protected $connectionToken;

    /**
     * The date time connection token expiration.
     *
     * @var string
     */
    protected $tokenExpiration;

    /**
     * Sr Pago application key.
     *
     * @var string
     */
    protected $applicationKey;

    /**
     * Sr Pago secret key.
     *
     * @var string
     */
    protected $applicationSecret;

    /**
     * Whether requests are test.
     *
     * @var bool
     */
    protected $isTest;

    /**
     * Map of possible error codes.
     *
     * @var array
     */
    protected $errorCodeMap = [
        'InvalidParamException'       => 'invalid_param',        // Malformed JSON, invalid fields, not required fields
        'InvalidEncryptionException'  => 'invalid_encryption',   // Incorrect data encryption
        'PaymentFilterException'      => 'processing_error',     // System detected supicious elements
        'SuspectedFraudException'     => 'suspected_fraud',      // System detected transaction as fraud
        'InvalidTransactionException' => 'processing_error',     // Transaction started but not processed due to internal rules
        'PaymentException'            => 'card_declined',        // Transaction was rejected by bank
        'SwitchException'             => 'processing_error',     // There's already a transaction with the same order id
        'InternalErrorException'      => 'card_declined',        // Sr pago is not available to process transactions
        'InvalidCardException'        => 'card_declined',        // Card already exists
        'TokenAlreadyUsedException'   => 'card_declined',        // Token has already been used
    ];

    public function __construct(array $config)
    {
        Arr::requires($config, ['private_key']);
        Arr::requires($config, ['secret_key']);

        $this->applicationKey = Arr::get($config, 'private_key');
        $this->applicationSecret = Arr::get($config, 'secret_key');
        $this->isTest = Arr::get($config, 'test', false);

        parent::__construct($config);
    }

    /**
     * Get a fresh instance of the Guzzle HTTP client.
     *
     * @return \GuzzleHttp\Client
     */
    protected function getHttpClient()
    {
        $stack = HandlerStack::create();

        $stack->push(Middleware::retry(function ($retries, RequestInterface $request, ResponseInterface $response = null, TransferException $exception = null) {
            $parsed = $this->parseResponse($response->getBody());

            return $retries < 3 && (
                $exception instanceof ConnectException ||
                $response->getStatusCode() >= 500 &&
                isset($parsed['error']['code']) &&
                !in_array($parsed['error']['code'], array_keys($this->errorCodeMap))
            );
        }, function ($retries) {
            return (int) pow(2, $retries) * 1000;
        }));

        return new GuzzleClient(['handler' => $stack]);
    }

    /**
     * Log in with the application.
     *
     * @return string
     */
    public function loginApplication()
    {
        $request = [
            'auth' => [
                $this->applicationKey,
                $this->applicationSecret,
            ],
            'headers' => [
                'Content-Type'  => 'application/json',
                'Accept'        => 'application/json',
            ],
            'json'  => [
                'application_bundle' => '',
            ],
        ];<commit_msg>Comment about gateway responses<commit_after><?php

namespace Shoperti\PayMe\Gateways\SrPago;

use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\TransferException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Shoperti\PayMe\ErrorCode;
use Shoperti\PayMe\Gateways\AbstractGateway;
use Shoperti\PayMe\Response;
use Shoperti\PayMe\Status;
use Shoperti\PayMe\Support\Arr;

class SrPagoGateway extends AbstractGateway
{
    /**
     * Production endpoint.
     *
     * @var string
     */
    protected $endpoint = 'https://api.srpago.com/v1';

    /**
     * Sandbox endpoint.
     *
     * @var string
     */
    protected $sandboxEndpoint = 'https://sandbox-api.srpago.com/v1';

    /**
     * Gateway display name.
     *
     * @var string
     */
    protected $displayName = 'srpago';

    /**
     * API connection token.
     *
     * @var string
     */
    protected $connectionToken;

    /**
     * The date time connection token expiration.
     *
     * @var string
     */
    protected $tokenExpiration;

    /**
     * Sr Pago application key.
     *
     * @var string
     */
    protected $applicationKey;

    /**
     * Sr Pago secret key.
     *
     * @var string
     */
    protected $applicationSecret;

    /**
     * Whether requests are test.
     *
     * @var bool
     */
    protected $isTest;

    /**
     * Map of possible error codes.
     *
     * @var array
     */
    protected $errorCodeMap = [
        'InvalidParamException'       => 'invalid_param',        // Malformed JSON, invalid fields, not required fields
        'InvalidEncryptionException'  => 'invalid_encryption',   // Incorrect data encryption
        'PaymentFilterException'      => 'processing_error',     // System detected supicious elements
        'SuspectedFraudException'     => 'suspected_fraud',      // System detected transaction as fraud
        'InvalidTransactionException' => 'processing_error',     // Transaction started but not processed due to internal rules
        'PaymentException'            => 'card_declined',        // Transaction was rejected by bank
        'SwitchException'             => 'processing_error',     // There's already a transaction with the same order id
        'InternalErrorException'      => 'card_declined',        // Sr pago is not available to process transactions
        'InvalidCardException'        => 'card_declined',        // Card already exists
        'TokenAlreadyUsedException'   => 'card_declined',        // Token has already been used
    ];

    public function __construct(array $config)
    {
        Arr::requires($config, ['private_key']);
        Arr::requires($config, ['secret_key']);

        $this->applicationKey = Arr::get($config, 'private_key');
        $this->applicationSecret = Arr::get($config, 'secret_key');
        $this->isTest = Arr::get($config, 'test', false);

        parent::__construct($config);
    }

    /**
     * Get a fresh instance of the Guzzle HTTP client.
     *
     * @return \GuzzleHttp\Client
     */
    protected function getHttpClient()
    {
        $stack = HandlerStack::create();

        $stack->push(Middleware::retry(function ($retries, RequestInterface $request, ResponseInterface $response = null, TransferException $exception = null) {
            $parsed = $this->parseResponse($response->getBody());

            // Be aware that this gateway validation error responses may be an HTTP 500 code.
            return $retries < 3 && ($exception instanceof ConnectException ||
                (
                    $response->getStatusCode() >= 500 &&
                    isset($parsed['error']['code']) &&
                    !in_array($parsed['error']['code'], array_keys($this->errorCodeMap))
                )
            );
        }, function ($retries) {
            return (int) pow(2, $retries) * 1000;
        }));

        return new GuzzleClient(['handler' => $stack]);
    }

    /**
     * Log in with the application.
     *
     * @return string
     */
    public function loginApplication()
    {
        $request = [
            'auth' => [
                $this->applicationKey,
                $this->applicationSecret,
            ],
            'headers' => [
                'Content-Type'  => 'application/json',
                'Accept'        => 'application/json',
            ],
            'json'  => [
                'application_bundle' => '',
            ],
        ];
{'fraction_non_alphanumeric': 0.12251912628894555, 'fraction_numerical': 0.0027719259341390397, 'mean_word_length': 2.102855177158583, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 59, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4995863', 'n_tokens_mistral': 2489, 'n_tokens_neox': 2404, 'n_words': 563}