Commit 92cbc267 authored by sluc23's avatar sluc23
Browse files

code cleanup and change main repo url

parent 45a28908
......@@ -20,19 +20,19 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
const REDSYS_TRANSACTION_TYPE_OPERATION_STANDARD = 0;
/**
* We only need one instance of this object. So we use the singleton
* pattern and cache the instance in this variable
*
* @var object
* @static
*/
* We only need one instance of this object. So we use the singleton
* pattern and cache the instance in this variable
*
* @var object
* @static
*/
static private $_singleton = NULL;
/**
* mode of operation: live or test
*
* @var object
*/
* mode of operation: live or test
*
* @var object
*/
protected $_mode = NULL;
/**
......@@ -47,28 +47,28 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
public $_processorName = NULL;
/**
* Constructor
*
* @param string $mode the mode of operation: live or test
*
* @return void
*/
function __construct($mode, &$paymentProcessor) {
* Constructor
*
* @param string $mode the mode of operation: live or test
*
* @return void
*/
public function __construct($mode, &$paymentProcessor) {
$this->_mode = $mode;
$this->_paymentProcessor = $paymentProcessor;
$this->_processorName = 'Redsys';
}
/**
* Singleton function used to manage this object
*
* @param string $mode the mode of operation: live or test
*
* @return object
* @static
*
*/
static function &singleton($mode, &$paymentProcessor) {
* Singleton function used to manage this object
*
* @param string $mode the mode of operation: live or test
*
* @return object
* @static
*
*/
public static function &singleton($mode, &$paymentProcessor) {
$processorName = $paymentProcessor["name"];
if (self::$_singleton[$processorName] === NULL) {
self::$_singleton[$processorName] = new self($mode, $paymentProcessor);
......@@ -77,12 +77,12 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
}
/**
* This function checks to see if we have the right config values
*
* @return string the error message if any
* @public
*/
function checkConfig() {
* This function checks to see if we have the right config values
*
* @return string the error message if any
* @public
*/
public function checkConfig() {
$config = CRM_Core_Config::singleton();
$error = array();
......@@ -107,7 +107,7 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
*
* @param type $params
*/
function doDirectPayment(&$params) {
public function doDirectPayment(&$params) {
CRM_Core_Error::fatal(E::ts("This function is not implemented"));
}
......@@ -115,7 +115,7 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
* This function calls the Redsys servers and sends them information
* about the payment.
*/
function doTransferCheckout(&$params, $component = 'contribute') {
public function doTransferCheckout(&$params, $component = 'contribute') {
$config = CRM_Core_Config::singleton();
......@@ -178,8 +178,9 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
// Force http if set.
$redsys_settings = CRM_Core_BAO_Setting::getItem("Redsys Settings", 'redsys_settings');
if ($redsys_settings['ipn_http'] == '1')
if ($redsys_settings['ipn_http'] == '1') {
$merchantUrl = preg_replace('/^https:/i', 'http:', $merchantUrl);
}
// The payment processor id can be named payment_processor (contribution pages).
if (array_key_exists('payment_processor', $params)) {
......@@ -190,14 +191,14 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
}
// Get the terminal for this payment processor.
if(array_key_exists('merchant_terminal_' . $paymentProcessorId, $redsys_settings)) {
if (array_key_exists('merchant_terminal_' . $paymentProcessorId, $redsys_settings)) {
if ($redsys_settings['merchant_terminal_' . $paymentProcessorId]) {
$merchantTerminal = $redsys_settings['merchant_terminal_' . $paymentProcessorId];
}
}
// Use the default terminal if the processor doesn't have an assigned one
if(!$merchantTerminal) {
if (!$merchantTerminal) {
$merchantTerminal = empty($redsys_settings['merchant_terminal']) ? 1 :
$redsys_settings['merchant_terminal'];
}
......@@ -225,7 +226,7 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
}
$miObj = new RedsysAPI();
$miObj->setParameter("Ds_Merchant_Amount", (int)(round($params["amount"] * 100)));
$miObj->setParameter("Ds_Merchant_Amount", (int) (round($params["amount"] * 100)));
$miObj->setParameter("Ds_Merchant_Order", strval(self::formatAmount($params["contributionID"], 12)));
$miObj->setParameter("Ds_Merchant_MerchantCode", $this->_paymentProcessor["user_name"]);
$miObj->setParameter("Ds_Merchant_Currency", self::REDSYS_CURRENCY_EURO);
......@@ -274,13 +275,13 @@ class CRM_Core_Payment_Redsys extends CRM_Core_Payment {
return $ipn->single($input, $ids, $objects, FALSE, FALSE);
}
static function formatAmount($amount, $size, $pad = 0){
public static function formatAmount($amount, $size, $pad = 0) {
$amount_str = preg_replace('/[\.,]/', '', strval($amount));
$amount_str = str_pad($amount_str, $size, $pad, STR_PAD_LEFT);
return $amount_str;
}
static function trimAmount($amount, $pad = '0'){
public static function trimAmount($amount, $pad = '0') {
return ltrim(trim($amount), $pad);
}
......
......@@ -2,15 +2,15 @@
class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
CONST REDSYS_RESPONSE_CODE_ACCEPTED = '0000';
const REDSYS_RESPONSE_CODE_ACCEPTED = '0000';
private $_errors;
private $_redsysAPI;
function __construct() {
public function __construct() {
parent::__construct();
$this->_redsysAPI = new RedsysAPI;
$this->_redsysAPI = new RedsysAPI();
$this->_errors = array(
"101" => "Tarjeta caducada",
"102" => "Tarjeta en excepción transitoria o bajo sospecha de fraude",
......@@ -50,7 +50,7 @@ class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
);
}
function single(&$input, &$ids, &$objects, $recur = FALSE, $first = FALSE) {
public function single(&$input, &$ids, &$objects, $recur = FALSE, $first = FALSE) {
$contribution = &$objects['contribution'];
if (!$recur) {
......@@ -75,7 +75,7 @@ class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
civicrm_api3('contribution', 'create', array('id' => $input['contributionID'], 'contribution_status_id' => 'Cancelled', 'cancel_reason' => $input['reasonCode'], 'cancel_date' => date('Y-m-d')));
}
catch (CiviCRM_API3_Exception $e) {
if($e->getMessage()) {
if ($e->getMessage()) {
CRM_Core_Error::debug_log_message("Redsys IPN Error Updating contribution: " . $e->getMessage());
}
}
......@@ -94,7 +94,7 @@ class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
return TRUE;
}
function getInput(&$input, &$ids) {
public function getInput(&$input, &$ids) {
$input = array(
// GET Parameters.
'module' => self::retrieve('md', 'String', 'GET', TRUE),
......@@ -137,7 +137,7 @@ class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
}
}
function validateData($paymentProcessor, &$input, &$ids, &$objects, $required = TRUE, $paymentProcessorID = NULL) {
public function validateData($paymentProcessor, &$input, &$ids, &$objects, $required = TRUE, $paymentProcessorID = NULL) {
$signatureNotif = $this->_redsysAPI->createMerchantSignatureNotif($paymentProcessor["password"], $input["Ds_MerchantParameters"]);
if ($input['Ds_MerchantCode'] != $paymentProcessor["user_name"]) {
......@@ -153,7 +153,7 @@ class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
return parent::validateData($input, $ids, $objects, $required, $paymentProcessorID);
}
static function retrieve($name, $type, $location = 'POST', $abort = TRUE) {
public static function retrieve($name, $type, $location = 'POST', $abort = TRUE) {
static $store = NULL;
$value = CRM_Utils_Request::retrieve($name, $type, $store, FALSE, NULL, $location);
if ($abort && $value === NULL) {
......@@ -164,7 +164,7 @@ class CRM_Core_Payment_RedsysIPN extends CRM_Core_Payment_BaseIPN {
return $value;
}
static function trimAmount($amount, $pad = '0') {
public static function trimAmount($amount, $pad = '0') {
return ltrim(trim($amount), $pad);
}
......
......@@ -4,6 +4,7 @@ require_once 'CRM/Core/Form.php';
use CRM_Redsys_ExtensionUtil as E;
class CRM_Redsys_Form_Settings extends CRM_Core_Form {
public function buildQuickForm() {
$this->add('checkbox', 'ipn_http', 'Use http for IPN Callback');
$this->add('text', 'merchant_terminal', 'Merchant Terminal', array('size' => 5));
......@@ -26,7 +27,7 @@ class CRM_Redsys_Form_Settings extends CRM_Core_Form {
parent::buildQuickForm();
}
function setDefaultValues() {
public function setDefaultValues() {
$defaults = array();
$redsys_settings = CRM_Core_BAO_Setting::getItem("Redsys Settings", 'redsys_settings');
if (!empty($redsys_settings)) {
......
......@@ -17,7 +17,7 @@ class CRM_Redsys_Upgrader extends CRM_Redsys_Upgrader_Base {
return TRUE;
}
private static function buildMenu(){
private static function buildMenu() {
$query = "SELECT id FROM `civicrm_navigation` WHERE name = 'CiviContribute'";
$dao = CRM_Core_DAO::executeQuery($query);
if ($dao->fetch()) {
......
......@@ -36,12 +36,12 @@ class CRM_Redsys_Upgrader_Base {
/**
* Obtain a reference to the active upgrade handler.
*/
static public function instance() {
if (! self::$instance) {
public static function instance() {
if (!self::$instance) {
// FIXME auto-generate
self::$instance = new CRM_Redsys_Upgrader(
'com.ixiam.payment.redsys',
realpath(__DIR__ .'/../../../')
realpath(__DIR__ . '/../../../')
);
}
return self::$instance;
......@@ -57,7 +57,7 @@ class CRM_Redsys_Upgrader_Base {
* CRM_Redsys_Upgrader_Base::_queueAdapter($ctx, 'methodName', 'arg1', 'arg2');
* @endcode
*/
static public function _queueAdapter() {
public static function _queueAdapter() {
$instance = self::instance();
$args = func_get_args();
$instance->ctx = array_shift($args);
......@@ -206,7 +206,7 @@ class CRM_Redsys_Upgrader_Base {
* @return array(revisionNumbers) sorted numerically
*/
public function getRevisions() {
if (! is_array($this->revisions)) {
if (!is_array($this->revisions)) {
$this->revisions = array();
$clazz = new ReflectionClass(get_class($this));
......@@ -239,8 +239,9 @@ class CRM_Redsys_Upgrader_Base {
return TRUE;
}
// ******** Hook delegates ********
/**
* Hook delegates
*/
public function onInstall() {
$files = glob($this->extensionDir . '/sql/*_install.sql');
if (is_array($files)) {
......@@ -301,4 +302,5 @@ class CRM_Redsys_Upgrader_Base {
default:
}
}
}
Package: com.ixiam.payment.redsys
Copyright (C) 2018, Ruben <r.pineda@ixiam.com>
Licensed under the GNU Affero Public License 3.0 (below).
-------------------------------------------------------------------------------
......
# CiviCRM Redsys Payment Processor #
This is a Payment Processor for CiviCRM that allows you to work with Redsys from within CiviCRM.
This is a Redsys Payment Processor for CiviCRM.
- For more info about RedSys, check its web site: http://www.redsys.es/
For more information about CiviCRM payment processors, see:
- For more information about CiviCRM payment processors, see:
http://book.civicrm.org/user/current/contributions/payment-processors/
## Release Notes ##
### v2.2.0 ###
- Update the Redsys api (redsysHMAC256_API_PHP_7.0.0), replacing the mcrypt to openssl
### v2.1 ###
- Copy the description "Financial type name" on Redsys description when is generated by drupal webform
### v2.0 ###
- Support for CiviCRM 5.3.0
### v1.9 ###
- Fix issue https://github.com/ixiam/com.ixiam.payment.redsys/issues/26
### v1.8 ###
- Support for CiviCRM 4.7
- Support for Wordpress
### v1.7 ###
- Multiterminal settings support
### v1.6 ###
- More settings to customize Merchant Terminal number if it is not "1"
### v1.5 ###
- New Settings to force http urls in ipn callback, if Redsys doesn't support the SSL certificate installed in the website
### v1.4 ###
- When is used in webforms, returns to thankyou page defined or back to the webform if the contribution is canceled in Redsys UI
### v1.3 ###
- Send email receipt on Contribution completion if it is set up
- For Event Registration pages, change Participant's status on Contribution completion
### v1.2.1 ###
Version 1.2 has been updated to meet the new Redsys requirements regarding password sha256 encryption.
More information here: https://canales.redsys.es/canales/ayuda/migracionSHA256.html
For Releases Notes, please check file [RELEASES.md](RELEASES.md)
## Contact ##
......@@ -90,7 +46,7 @@ After installing and activating the extension, you'll need to configure your pay
* Add a new Payment Processor (Administer / System Settings / Payment Processor)
* Select Redsys Payment Processor as Payment Processor Type
* Configure it with your Mechant Account Id (número de comercio) and Encription Password (clave secreta de encriptación),
* By default the test key is sq7HjrUOBfKmC576ILgskD5srU870gJ7
* By default the test key is sq7HjrUOBfKmC576ILgskD5srU870gJ7
### Requirements ###
......@@ -99,11 +55,11 @@ Version 2.0 works with CiviCRM 5.3.0 or newer versions.
### Error Log
To search if is failing in some cases, search in ConfigLog from civicrm the workd "Redsys IPN Error"
To search if it's failing in some cases, search in ConfigLog from civicrm the word "Redsys IPN Error"
## License ##
Redsys Payment Processor for CiviCRM. Copyright (C) 2013 - 2019 Amnesty International (originally developed by Ixiam http://www.ixiam.com).
Redsys Payment Processor for CiviCRM. Copyright (C) 2013 - 2020 Ixiam http://www.ixiam.com (originally supported by Amnesty International)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
......
## Release Notes ##
### v2.2.1 ###
- Code Cleanup and migration to https://lab.civicrm.org/extensions/redsys
- Fix decimal point issue when sending float amounts
### v2.2.0 ###
- Update the Redsys api (redsysHMAC256_API_PHP_7.0.0), replacing the mcrypt to openssl
### v2.1 ###
- Copy the description "Financial type name" on Redsys description when is generated by drupal webform
### v2.0 ###
- Support for CiviCRM 5.3.0
### v1.9 ###
- Fix issue https://github.com/ixiam/com.ixiam.payment.redsys/issues/26
### v1.8 ###
- Support for CiviCRM 4.7
- Support for Wordpress
### v1.7 ###
- Multiterminal settings support
### v1.6 ###
- More settings to customize Merchant Terminal number if it is not "1"
### v1.5 ###
- New Settings to force http urls in ipn callback, if Redsys doesn't support the SSL certificate installed in the website
### v1.4 ###
- When is used in webforms, returns to thankyou page defined or back to the webform if the contribution is canceled in Redsys UI
### v1.3 ###
- Send email receipt on Contribution completion if it is set up
- For Event Registration pages, change Participant's status on Contribution completion
### v1.2.1 ###
Version 1.2 has been updated to meet the new Redsys requirements regarding password sha256 encryption.
More information here: https://canales.redsys.es/canales/ayuda/migracionSHA256.html
<?php
/**
* NOTA SOBRE LA LICENCIA DE USO DEL SOFTWARE
*
* El uso de este software está sujeto a las Condiciones de uso de software que
* se incluyen en el paquete en el documento "Aviso Legal.pdf". También puede
* obtener una copia en la siguiente url:
* http://www.redsys.es/wps/portal/redsys/publica/areadeserviciosweb/descargaDeDocumentacionYEjecutables
*
* Redsys es titular de todos los derechos de propiedad intelectual e industrial
* del software.
*
* Quedan expresamente prohibidas la reproducción, la distribución y la
* comunicación pública, incluida su modalidad de puesta a disposición con fines
* distintos a los descritos en las Condiciones de uso.
*
* Redsys se reserva la posibilidad de ejercer las acciones legales que le
* correspondan para hacer valer sus derechos frente a cualquier infracción de
* los derechos de propiedad intelectual y/o industrial.
*
* Redsys Servicios de Procesamiento, S.L., CIF B85955367
*/
class RedsysAPI{
/****** Array de DatosEntrada ******/
var $vars_pay = array();
/****** Set parameter ******/
function setParameter($key,$value){
$this->vars_pay[$key]=$value;
}
/****** Get parameter ******/
function getParameter($key){
return $this->vars_pay[$key];
}
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////// FUNCIONES AUXILIARES: ////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
/****** 3DES Function ******/
function encrypt_3DES($message, $key){
// Se cifra
$l = ceil(strlen($message) / 8) * 8;
return substr(openssl_encrypt($message . str_repeat("\0", $l - strlen($message)), 'des-ede3-cbc', $key, OPENSSL_RAW_DATA, "\0\0\0\0\0\0\0\0"), 0, $l);
}
/****** Base64 Functions ******/
function base64_url_encode($input){
return strtr(base64_encode($input), '+/', '-_');
}
function encodeBase64($data){
$data = base64_encode($data);
return $data;
}
function base64_url_decode($input){
return base64_decode(strtr($input, '-_', '+/'));
}
function decodeBase64($data){
$data = base64_decode($data);
return $data;
}
/****** MAC Function ******/
function mac256($ent,$key){
$res = hash_hmac('sha256', $ent, $key, true);//(PHP 5 >= 5.1.2)
return $res;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////// FUNCIONES PARA LA GENERACIÓN DEL FORMULARIO DE PAGO: ////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
/****** Obtener Número de pedido ******/
function getOrder(){
$numPedido = "";
if(empty($this->vars_pay['DS_MERCHANT_ORDER'])){
$numPedido = $this->vars_pay['Ds_Merchant_Order'];
} else {
$numPedido = $this->vars_pay['DS_MERCHANT_ORDER'];
}
return $numPedido;
}
/****** Convertir Array en Objeto JSON ******/
function arrayToJson(){
$json = json_encode($this->vars_pay); //(PHP 5 >= 5.2.0)
return $json;
}
function createMerchantParameters(){
// Se transforma el array de datos en un objeto Json
$json = $this->arrayToJson();
// Se codifican los datos Base64
return $this->encodeBase64($json);
}
function createMerchantSignature($key){
// Se decodifica la clave Base64
$key = $this->decodeBase64($key);
// Se genera el parámetro Ds_MerchantParameters
$ent = $this->createMerchantParameters();
// Se diversifica la clave con el Número de Pedido
$key = $this->encrypt_3DES($this->getOrder(), $key);
// MAC256 del parámetro Ds_MerchantParameters
$res = $this->mac256($ent, $key);
// Se codifican los datos Base64
return $this->encodeBase64($res);
}
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////// FUNCIONES PARA LA RECEPCIÓN DE DATOS DE PAGO (Notif, URLOK y URLKO): ////////////
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
/****** Obtener Número de pedido ******/
function getOrderNotif(){
$numPedido = "";
if(empty($this->vars_pay['Ds_Order'])){
$numPedido = $this->vars_pay['DS_ORDER'];
} else {
$numPedido = $this->vars_pay['Ds_Order'];
}
return $numPedido;
}
function getOrderNotifSOAP($datos){
$posPedidoIni = strrpos($datos, "<Ds_Order>");
$tamPedidoIni = strlen("<Ds_Order>");
$posPedidoFin = strrpos($datos, "</Ds_Order>");
return substr($datos,$posPedidoIni + $tamPedidoIni,$posPedidoFin - ($posPedidoIni + $tamPedidoIni));
}
function getRequestNotifSOAP($datos){
$posReqIni = strrpos($datos, "<Request");
$posReqFin = strrpos($datos, "</Request>");
$tamReqFin = strlen("</Request>");
return substr($datos,$posReqIni,($posReqFin + $tamReqFin) - $posReqIni);
}
function getResponseNotifSOAP($datos){
$posReqIni = strrpos($datos, "<Response");
$posReqFin = strrpos($datos, "</Response>");
$tamReqFin = strlen("</Response>");
return substr($datos,$posReqIni,($posReqFin + $tamReqFin) - $posReqIni);
}
/****** Convertir String en Array ******/
function stringToArray($datosDecod){
$this->vars_pay = json_decode($datosDecod, true); //(PHP 5 >= 5.2.0)
}
function decodeMerchantParameters($datos){
// Se decodifican los datos Base64
$decodec = $this->base64_url_decode($datos);
// Los datos decodificados se pasan al array de datos
$this->stringToArray($decodec);
return $decodec;
}
function createMerchantSignatureNotif($key, $datos){
// Se decodifica la clave Base64
$key = $this->decodeBase64($key);
// Se decodifican los datos Base64
$decodec = $this->base64_url_decode($datos);
// Los datos decodificados se pasan al array de datos
$this->stringToArray($decodec);
// Se diversifica la clave con el Número de Pedido
$key = $this->encrypt_3DES($this->getOrderNotif(), $key);
// MAC256 del parámetro Ds_Parameters que envía Redsys
$res = $this->mac256($datos, $key);
// Se codifican los datos Base64
return $this->base64_url_encode($res);