PK       ! s}Q;¥"  ¥"    src/ResponseCode.phpnu „[µü¤        <?php

namespace Omnipay\RedSys;

class ResponseCode
{
    private $code;
    private $title;
    private $description;

    public function __construct($code, $title, $description)
    {
        $this->code = $code;
        $this->title = $title;
        $this->description = $description;
    }

    public function getCode()
    {
        return $this->code;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param $code
     * @return null|static
     */
    public static function find($code)
    {
        $codes = static::all();
        $lookupCode = $code;

        $integerCode = (int)$code;
        if ($integerCode >= 2 && $integerCode <= 99) {
            $lookupCode = '0002-0099';
        } elseif ($integerCode >= 181 && $integerCode <= 182) {
            $lookupCode = '0181-0182';
        } elseif ($integerCode >= 208 && $integerCode <= 209) {
            $lookupCode = '0208-0209';
        } elseif ($integerCode >= 501 && $integerCode <= 503) {
            $lookupCode = '0501-0503';
        }

        if (isset($codes[$lookupCode])) {
            return new static($code, $codes[$lookupCode][0], $codes[$lookupCode][1]);
        }

        return null;
    }

    public static function all()
    {
        return [
            '0000' => [
                'TRANSACCION APROBADA',
                'Transaction authorised by card issuing bank',
            ],
            '0001' => [
                'TRANSACCION APROBADA PREVIA IDENTIFICACION DE TITULAR',
                'Exclusive code for transactions Verified by Visa or MasterCard SecureCode. The transaction has been authorised and the issuing bank informs us that it has correctly authenticated the identity of the cardholder.',
            ],
            '0002-0099' => [
                'TRANSACCION APROBADA',
                'Transaction authorised by issuing bank',
            ],
            '0101' => [
                'EXPIRED CARD',
                'Transaction rejected because card expiry date entered during payment is prior to that currently valid.',
            ],
            '0102' => [
                'CARD TEMPORARILY BLOCKED OR UNDER SUSPICION OF FRAUD',
                'Card temporarily blocked by issuing bank or under suspicion of fraud',
            ],
            '0104' => [
                'OPERATION NOT ALLOWED',
                'Operation not allowed for this type of card.',
            ],
            '0106' => [
                'NO. ATTEMPTS EXCEEDED',
                'Number of attempts with erroneous PIN exceeded.',
            ],
            '0107' => [
                'CONTACT ISSUER',
                'Issuing bank does not allow automatic authorisation. It is necessary to call your authorisation centre to obtain manual approval.',
            ],
            '0109' => [
                'IDENTIFICATION OF MERCHANT OR TERMINAL INVALID',
                'Rejected because merchant is not correctly registered in international card systems.',
            ],
            '0110' => [
                'AMOUNT INVALID',
                'Transaction amount unusual for this type of merchant requesting payment authorisation.',
            ],
            '0114' => [
                'CARD DOES NOT SUPPORT TYPE OF OPERATION REQUESTED',
                'Operation not allowed for this type of card.',
            ],
            '0116' => [
                'INSUFFICIENT BALANCE',
                'The cardholder has insufficient credit to meet payment.',
            ],
            '0118' => [
                'CARD NOT REGISTERED',
                'Card inexistent or not registered by issuing bank.',
            ],
            '0125' => [
                'CARD NOT EFFECTIVE',
                'Card inexistent or not registered by issuing bank.',
            ],
            '0129' => [
                'CVV2/CVC2 ERROR',
                'The CVV2/CVC2 code (three digits on back of card) entered by consumer is erroneous.',
            ],
            '0167' => [
                'CONTACT ISSUER SUSPECTED FRAUD',
                'Due to suspicion that transaction is fraudulent the issuing bank does not allow automatic authorisation. It is necessary to call your authorisation centre to obtain manual approval.',
            ],
            '0180' => [
                'NON-SERVICE CARD',
                'Operation not allowed for this type of card.',
            ],
            '0181-0182' => [
                'CARD WITH DEBIT OR CREDIT RESTRICTIONS',
                'Card temporarily blocked by issuing bank.',
            ],
            '0184' => [
                'AUTHENTICATION ERROR',
                'Exclusive code for transactions Verified by Visa or MasterCard SecureCode. Transaction rejected because issuing bank cannot authenticate the cardholder.',
            ],
            '0190' => [
                'REJECTION WITHOUT SPECIFYING MOTIVE',
                'Transaction rejected by issuing bank but without reporting the reason.',
            ],
            '0191' => [
                'ERRONEOUS EXPIRY DATE',
                'Transaction rejected because card expiry date entered during payment does not match that currently valid.',
            ],

            '0201' => [
                'EXPIRED CARD',
                'Transaction rejected because card expiry date entered during payment is prior to that currently valid. In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],
            '0202' => [
                'CARD TEMPORARILY BLOCKED OR UNDER SUSPICION OF FRAUD',
                'Card temporarily blocked by issuing bank or under suspicion of fraud In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],
            '0204' => [
                'OPERATION NOT ALLOWED',
                'Operation not allowed for this type of card. In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],
            '0207' => [
                'CONTACT ISSUER',
                'Issuing bank does not allow automatic authorisation. It is necessary to call your authorisation centre to obtain manual approval. In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],
            '0208-0209' => [
                'CARD LOST OR STOLEN',
                'Card blocked by issuing bank as holder has reported it is stolen or lost. In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],
            '0280' => [
                'CVV2/CVC2 ERROR',
                'Exclusive code for transactions in which 3-figit CVV2 code is requested (Visa card) or CVC2 (MasterCard) on back of card. The CVV2/CVC2 code entered by purchaser is erroneous. In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],
            '0290' => [
                'REJECTION WITHOUT SPECIFYING MOTIVE',
                'Transaction rejected by issuing bank but without reporting the reason. In addition, the issuing bank considers that the card is subject to possible fraud.',
            ],

            '0400' => [
                'CANCELLATION ACCEPTED',
                'Cancellation or partial chargeback transaction accepted by issuing bank.',
            ],
            '0480' => [
                'ORIGINAL OPERATION NOT FOUND OR TIME-OUT EXCEEDED',
                'The cancellation or partial chargeback not accepted because original operation not located or because issuing bank has not responded within predefined time-out limit.',
            ],
            '0481' => [
                'CANCELLATION ACCEPTED',
                'Cancellation or partial chargeback transaction accepted by issuing bank. However, issuing bank response received late, outside predefined time-out limit.',
            ],

            '0500' => [
                'RECONCILIATION ACCEPTED',
                'Reconciliation transaction accepted by issuing bank.',
            ],
            '0501-0503' => [
                'ORIGINAL OPERATION NOT FOUND OR TIME-OUT EXCEEDED',
                'The reconciliation was not accepted because original operation not located or because issuing bank has not responded within predefined time-out limit.',
            ],
            '9928' => [
                'CANCELLATION OF PRE-AUTHORISATION PERFORMED BY SYSTEM',
                'System has cancelled deferred pre-authorisation as over 72 hours have passed.',
            ],
            '9929' => [
                'CANCELLATION OF PRE-AUTHORISATION PERFORMED BY MERCHANT',
                'The cancellation of the pre-authorisation was accepted.',
            ],
        ];
    }
}
PK       ! ÝLÄ w  w    src/Encoder.phpnu „[µü¤        <?php

namespace Omnipay\RedSys;

final class Encoder
{
    public function encode(array $input)
    {
        $output = json_encode($input);
        $output = base64_encode($output);
        return $output;
    }

    public function decode($input)
    {
        $output = base64_decode($input);
        $output = json_decode($output, true);
        return $output;
    }
}
PK       ! ,B5»  »    src/Signer.phpnu „[µü¤        <?php

namespace Omnipay\RedSys;

use Sarciszewski\PHPFuture\Security;

final class Signer
{
    private $encryptor;

    public function __construct($secretKey)
    {
        $this->encryptor = new Encryptor($secretKey);
    }

    public function generateSignature($data, $keyData)
    {
        $key = $this->encryptor->encrypt($keyData);

        $res = hash_hmac('sha256', $data, $key, true);

        return base64_encode($res);
    }

    public function validateSignature($signature, $data, $keyData)
    {
        $expectedSignature = $this->generateSignature($data, $keyData);

        // Constant Time String Comparison @see http://php.net/hash_equals
        if (function_exists('hash_equals')) {
            return hash_equals($signature, $expectedSignature); // (PHP 5 >= 5.6.0, PHP 7)
        }
        else {
            // Polyfill for PHP < 5.6.
            return Security::hashEquals($signature, $expectedSignature);
        }
    }
}
PK       ! (–Òp/  /  (  src/Message/CompletePurchaseResponse.phpnu „[µü¤        <?php

namespace Omnipay\RedSys\Message;

use Omnipay\Common\Message\AbstractResponse;
use Omnipay\RedSys\ResponseCode;

/**
 * RedSys Complete Purchase Response
 */
class CompletePurchaseResponse extends AbstractResponse
{
    public function isSuccessful()
    {
        return preg_match('/^00[0-9][0-9]$/', $this->getCode());
    }

    public function getCode()
    {
        return $this->data['Ds_Response'];
    }

    public function getMessage()
    {
        $responseCode = ResponseCode::find($this->getCode());
        return $responseCode ? $responseCode->getDescription() : null;
    }

    public function getTransactionReference()
    {
        return $this->data['Ds_Order'];
    }

    public function getTransactionId()
    {
        //return $this->data['Ds_Order'];
        return '';
    }
}
PK       ! TŽš–˜  ˜     src/Message/PurchaseResponse.phpnu „[µü¤        <?php

namespace Omnipay\RedSys\Message;

use Omnipay\Common\Message\AbstractResponse;
use Omnipay\Common\Message\RedirectResponseInterface;

/**
 * RedSys Purchase Response
 */
class PurchaseResponse extends AbstractResponse implements RedirectResponseInterface
{
    public function isSuccessful()
    {
        return false;
    }

    public function isRedirect()
    {
        return true;
    }

    public function getRedirectUrl()
    {
        return $this->getRequest()->getEndpoint();
    }

    public function getRedirectMethod()
    {
        return 'POST';
    }

    public function getRedirectData()
    {
        return $this->getData();
    }
}
PK       ! º®"L  L    src/Message/PurchaseRequest.phpnu „[µü¤        <?php

namespace Omnipay\RedSys\Message;

/**
 * RedSys Purchase Request
 */
class PurchaseRequest extends RequestBase
{
    public function setTransactionId($value)
    {
    	/*
        if (!preg_match('/^[0-9]{4}[0-9a-zA-Z]{0,8}$/', $value)) {
            throw new \InvalidArgumentException('Invalid transaction id');
        }
        */
        return parent::setTransactionId($value);
    }

    public function setTransactionReference($value)
    {
    	/*
        if (!preg_match('/^[0-9]{4}[0-9a-zA-Z]{0,8}$/', $value)) {
            throw new \InvalidArgumentException('Invalid transaction reference');
        }
        */
        return parent::setTransactionReference($value);
    }

    public function setTitular($titular)
    {
        return $this->setParameter('titular', $titular);
    }

    public function getMerchantCode()
    {
        return $this->getParameter('merchantCode');
    }

    public function setMerchantCode($value)
    {
        return $this->setParameter('merchantCode', $value);
    }

    public function getSecretKey()
    {
        return $this->getParameter('secretKey');
    }

    public function setSecretKey($value)
    {
        return $this->setParameter('secretKey', $value);
    }

    public function getTerminal()
    {
        return $this->getParameter('terminal');
    }

    public function setTerminal($value)
    {
        return $this->setParameter('terminal', $value);
    }

    public function getMerchantName()
    {
        return $this->getParameter('merchantName');
    }

    public function setMerchantName($value)
    {
        return $this->setParameter('merchantName', $value);
    }

    public function setConsumerLanguage($consumerLanguage)
    {
        return $this->setParameter('consumerLanguage', $consumerLanguage);
    }

    public function getExtraData()
    {
        return $this->getParameter('extraData');
    }

    public function setExtraData($value)
    {
        return $this->setParameter('extraData', $value);
    }

    public function getTransactionType()
    {
        return '0';
    }

    public function getAuthorisationCode()
    {
        return $this->getParameter('authorisationCode');
    }

    public function setAuthorisationCode($value)
    {
        return $this->setParameter('authorisationCode', $value);
    }

    public function getPayMethods()
    {
        return $this->getParameter('payMethods');
    }

    public function setPayMethods($value)
    {
        return $this->setParameter('payMethods', $value);
    }

    protected function getMerchantOrder()
    {
        return $this->getTransactionReference() ?: $this->getTransactionId();
    }
    
    protected function getCurrencyNumber()
    {
    	return $this->getParameter('currencyNumber');
    }
    
    public function setCurrencyNumber($value)
    {
    	return $this->setParameter('currencyNumber', $value);
    }

    public function getData()
    {
        $this->validate('amount', 'currency', 'transactionId', 'merchantCode', 'terminal');
        $parameters = [
	        'DS_MERCHANT_AMOUNT'				=> $this->getAmountInteger(),
	        'DS_MERCHANT_ORDER'					=> $this->getMerchantOrder(),
	        'DS_MERCHANT_MERCHANTCODE'			=> $this->getMerchantCode(),
	        'DS_MERCHANT_CURRENCY'				=> $this->getCurrencyNumber(),
	        'DS_MERCHANT_TRANSACTIONTYPE'		=> $this->getTransactionType(),
	        'DS_MERCHANT_TERMINAL'				=> $this->getTerminal(),
	        'DS_MERCHANT_MERCHANTURL'			=> $this->getNotifyUrl(),
	        'DS_MERCHANT_URLOK'					=> $this->getReturnUrl(),
	        'DS_MERCHANT_URLKO'					=> $this->getCancelUrl(),
	        'Ds_Merchant_ConsumerLanguage'		=> $this->getParameter('consumerLanguage'),
	        'Ds_Merchant_ProductDescription'	=> $this->getDescription(),
	        'Ds_Merchant_Titular'				=> '',
	        'Ds_Merchant_MerchantData'			=> sha1($this->getNotifyUrl()),
	        'Ds_Merchant_MerchantName'			=> $this->getMerchantName(),
	        'Ds_Merchant_Module'				=> 'EShop Shopping Cart',
        ];
        
        if ($this->getPayMethods())
        {
        	$parameters['Ds_Merchant_PayMethods'] = $this->getPayMethods();
        }
        
        $parameters = $this->getEncoder()->encode($parameters);
        $signature = $this->getSigner()->generateSignature($parameters, $this->getMerchantOrder());

        $data = [
          'Ds_MerchantParameters' => $parameters,
          'Ds_Signature' => $signature,
          'Ds_SignatureVersion' => 'HMAC_SHA256_V1',
        ];

        return $data;
    }

    public function sendData($data)
    {
        return $this->response = new PurchaseResponse($this, $data);
    }
}
PK       ! çJ°®Æ  Æ    src/Message/RequestBase.phpnu „[µü¤        <?php

namespace Omnipay\RedSys\Message;

use Omnipay\Common\Message\AbstractRequest;
use Omnipay\RedSys\Encoder;
use Omnipay\RedSys\Signer;

abstract class RequestBase extends AbstractRequest
{
    protected $liveEndpoint = 'https://sis.redsys.es/sis/realizarPago';

    protected $testEndpoint = 'https://sis-t.redsys.es:25443/sis/realizarPago';

    /**
     * @var \Omnipay\RedSys\Encoder
     */
    private $encoder;

    /**
     * @var \Omnipay\RedSys\Signer
     */
    private $signer;

    public function getEncoder()
    {
        if (!isset($this->encoder)) {
            $this->encoder = new Encoder();
        }
        return $this->encoder;
    }

    public function setEncoder(Encoder $encoder)
    {
        $this->encoder = $encoder;
    }

    public function getSigner()
    {
        if (!isset($this->signer)) {
            $this->validate('secretKey');
            $this->signer = new Signer($this->getParameter('secretKey'));
        }
        return $this->signer;
    }

    public function setSigner(Signer $signer)
    {
        $this->signer = $signer;
    }

    public function getEndpoint()
    {
        return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint;
    }
}
PK       ! Ï~äíE  E  '  src/Message/CompletePurchaseRequest.phpnu „[µü¤        <?php

namespace Omnipay\RedSys\Message;

use Omnipay\Common\Exception\InvalidResponseException;

/**
 * RedSys Complete Purchase Request
 */
class CompletePurchaseRequest extends PurchaseRequest
{
    public function getData()
    {
        $query = $this->httpRequest->request;
        $signature = strtr($query->get('Ds_Signature'), '-_', '+/');
        $parameters = strtr($query->get('Ds_MerchantParameters'), '-_', '+/');

        $data = $this->getEncoder()->decode($parameters);

        if (!$this->getSigner()->validateSignature($signature, $parameters, $data['Ds_Order'])) {
            throw new InvalidResponseException('Invalid signature: ' . $signature);
        }

        return $data;
    }

    public function sendData($data)
    {
        return $this->response = new CompletePurchaseResponse($this, $data);
    }
}
PK       ! 6ˆ?Â5  5    src/Gateway.phpnu „[µü¤        <?php

namespace Omnipay\RedSys;

use Omnipay\Common\AbstractGateway;
use Omnipay\RedSys\Message\CompletePurchaseRequest;
use Omnipay\RedSys\Message\PurchaseRequest;

/**
 * RedSys Gateway
 */
class Gateway extends AbstractGateway
{
    public function getName()
    {
        return 'RedSys';
    }

    public function getDefaultParameters()
    {
		return array(
			'currencyNumber'	=> 'redsys_moneda',
            'terminal'			=> 'redsys_terminal',
            'merchantName'		=> 'redsys_nombre',
			'merchantCode'		=> 'redsys_fuc',
            'transactionType'	=> 'redsys_trans',
            'testMode'			=> 'redsys_mode',
			'secretKey'			=> 'redsys_clave256',
			'payMethods'		=> 'redsys_pagos'
        );
    }

    public function setMerchantName($merchantName)
    {
        return $this->setParameter('merchantName', $merchantName);
    }

    public function setMerchantCode($merchantCode)
    {
        return $this->setParameter('merchantCode', $merchantCode);
    }

    public function setSecretKey($secretKey)
    {
        return $this->setParameter('secretKey', $secretKey);
    }

    public function setTerminal($terminal)
    {
        return $this->setParameter('terminal', $terminal);
    }

    public function setConsumerLanguage($consumerLanguage)
    {
        return $this->setParameter('consumerLanguage', $consumerLanguage);
    }

    public function setReturnUrl($returnUrl)
    {
        return $this->setParameter('returnUrl', $returnUrl);
    }

    public function setCancelUrl($cancelUrl)
    {
        return $this->setParameter('cancelUrl', $cancelUrl);
    }

    public function purchase(array $parameters = array())
    {
        //return $this->createRequest(PurchaseRequest::class, $parameters);
    	return $this->createRequest('\Omnipay\RedSys\Message\PurchaseRequest', $parameters);
    }

    public function completePurchase(array $parameters = array())
    {
        //return $this->createRequest(CompletePurchaseRequest::class, $parameters);
    	return $this->createRequest('\Omnipay\RedSys\Message\CompletePurchaseRequest', $parameters);
    }
}
PK       ! ¹Ð[ì€  €    src/Encryptor.phpnu „[µü¤        <?php
namespace Omnipay\RedSys;

final class Encryptor
{
	private $secretKey;

	public function __construct($secretKey)
	{
		$this->secretKey = base64_decode($secretKey);
	}

	public function encrypt($message)
	{
		if (function_exists('openssl_encrypt'))
		{
			return self::encrypt3DESOpenSSL($message, $this->secretKey);
		}

		return self::encrypt3DESMcrypt($message, $this->secretKey);
	}

	protected static function encrypt3DESOpenSSL($message, $key)
	{
		$l       = ceil(strlen($message) / 8) * 8;
		$message = $message . str_repeat("\0", $l - strlen($message));

		return substr(openssl_encrypt($message, 'des-ede3-cbc', $key, OPENSSL_RAW_DATA, "\0\0\0\0\0\0\0\0"), 0, $l);
	}

	protected static function encrypt3DESMcrypt($message, $key)
	{
		$iv = implode(array_map('chr', array(0, 0, 0, 0, 0, 0, 0, 0)));

		return mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);
	}
}PK       ! U"c€]  ]    composer.jsonnu „[µü¤        {
    "name": "swisnl/omnipay-redsys",
    "type": "library",
    "description": "RedSys driver for the Omnipay payment processing library",
    "keywords": [
        "gateway",
        "merchant",
        "omnipay",
        "pay",
        "payment",
        "redsys"
    ],
    "homepage": "https://github.com/swisnl/omnipay-redsys",
    "license": "MIT",
    "authors": [
        {
            "name": "Cees Geene",
            "email": "cees@swis.nl"
        },
        {
            "name": "Omnipay RedSys Contributors",
            "homepage": "https://github.com/swisnl/omnipay-redsys/contributors"
        }
    ],
    "autoload": {
        "psr-4": { "Omnipay\\RedSys\\" : "src/" }
    },
    "require": {
        "omnipay/common": "~2.0",
        "sarciszewski/php-future": "^0.4.2"
    },
    "require-dev": {
        "omnipay/tests": "~2.0"
    }
}
PK         ! s}Q;¥"  ¥"                  src/ResponseCode.phpnu „[µü¤        PK         ! ÝLÄ w  w              é"  src/Encoder.phpnu „[µü¤        PK         ! ,B5»  »              Ÿ$  src/Signer.phpnu „[µü¤        PK         ! (–Òp/  /  (            ˜(  src/Message/CompletePurchaseResponse.phpnu „[µü¤        PK         ! TŽš–˜  ˜               ,  src/Message/PurchaseResponse.phpnu „[µü¤        PK         ! º®"L  L              /  src/Message/PurchaseRequest.phpnu „[µü¤        PK         ! çJ°®Æ  Æ              ¢A  src/Message/RequestBase.phpnu „[µü¤        PK         ! Ï~äíE  E  '            ³F  src/Message/CompletePurchaseRequest.phpnu „[µü¤        PK         ! 6ˆ?Â5  5              OJ  src/Gateway.phpnu „[µü¤        PK         ! ¹Ð[ì€  €              ÃR  src/Encryptor.phpnu „[µü¤        PK         ! U"c€]  ]              „V  composer.jsonnu „[µü¤        PK      Ç  Z    